Por fin me hago de un momento para pasar por acá...
usuario_registrado:
Tratá de registrarte en el foro porque hay un montón de "usuario_registrado" y no se sabe quien es quien.
El objeto Timer de VB no es para nada preciso. Es bastante aproximado, pero no sirve para sincronizar correctamente con un Pic, que es mucho mas exacto. Depende mucho de la ocupación del procesador en el intervalo de tiempo que cuenta y como Windows tiene la costumbre de tener subprocesos corriendo en segundo plano (algunos que ni siquiera aparecen en el administrador de tareas) NO te va a servir si querés cierta exactitud. Yo ya lo comprobé en infinidad de situaciones. Una mejora es utilizar la API de Windows que se ocupa de los timers, pero tampoco mejora demasiado.
La solución pasa por otro lado, si lo que buscás es leer por el puerto serie cada cierto intervalo de tiempo te conviene programar el pic para que envíe los datos cada 500ms y hacer un "protocolo" casero para manejar los mensajes.
Seguí leyendo que más adelante te doy una solución que te puede funcionar...
************************
hhpp:
La solución que aporta Nocturno debería funcionar... pero me parece que te estás olvidando de algo más. Existen propiedades del objeto MsComm que sirven para gestionar el buffer de entrada y salida del puerto serie que si no están bien configuradas te hacen el error que mencionás.
Hasta donde yo entiendo vos leés el puerto cada intervalos de tiempo o presionando un botón en el formulario (en el evento Button_Click). El problema pasa porque en el momento que vos leés el puerto, en el buffer de recepción tenés 5 o 6 datos acumulados que ya te envió el pic. Tomemos un ejemplo:
El pic te manda un dato cada 500ms... vos leés el puerto cada 2 segundos. Mientras el pic envía la pc guarda los datos en el buffer (que es una memoria temporal) hasta que se lean. En el momento que se leen los datos se vacía el buffer. Entonces, a los 2 segundos, te va a devolver una cadena conteniendo los 4 datos seguidos (500ms x 4 = 2 segundos). Se entiende?
Ahora bien, la solución:
Manejar la comunicación por eventos! Acá va un ejemplo, supongamos que el control MsComm en tu formulario se llama "Comm".
Private serie as String
Private buffer as String
Private buffer2 as String
Private Sub Form_Load() "Configurar el puerto ni bien arranca el programa...
Comm.CommPort = 1 "Puerto com1
Comm.Settings = "19200,N,8,1" "Velocidad, paridad, etc...
Comm.InputLen = 0 "Explicado después.
Comm.RThreshold = 1 "Produce el evento OnComm cada 1 caracter.
Comm.PortOpen = True "Abre el puerto.
End Sub
"Comm.InputLen = 0" es la cantidad de caracteres que va a leer cada vez que se hace un Input, si le ponés 5 te va a leer 5 nomás, si hay 20 no te va a vaciar el buffer, te va a dejar 15 en espera. Con 0 le decís que lea TODO el buffer y que lo vacíe completamente en cada lectura.
"Comm.RThreshold = 1" no hace exactamente lo que dice... pero bueno. Funciona bien así, tendría que disparar un evento por cada caracter recibido pero lo dispara cuando encuentra un retorno de carro ASCII "13". Mejor!
Después generamos el evento...
Private Sub Comm_OnComm()
If Comm.InputLen > 7 Then
Comm.PortOpen = False
Comm.PortOpen = True
Exit Sub
End If
buffer = Comm.Input
If buffer = "" Then Exit Sub
buffer2 = Left$(buffer, Len(buffer) - 1)
Text1.Text = buffer2
Call ControlSerie
End Sub
Esto es fácil, el pic envía un dato seguido del ASCII 13, cada vez que MsComm encuentra un ASCII 13 salta el evento OnComm. Entonces lo que hay que hacer es enviar los datos seguido ahí nomas de un ASCII 13.
Ahí le puse que si el buffer tenía más de 7 caracteres que lo descarte y vacíe el buffer. Esto es por si se acumulan datos (basura) en el puerto hasta que el programa termina de arrancar y estar operativo (desde la carga del form y activación del puerto hasta llegar al punto de que pueda atender las interrupciones). SOLO EN EL CASO QUE SE SEPA QUE LOS DATOS DEL PIC NO SUPERAN ESTA CANTIDAD. Se puede especificar otro valor distinto a 7 o ignorar toda la condición.
Despues está la condición de que si la cadena está vacía ("") que la ignore.
"buffer2 = Left$(buffer, Len(buffer) - 1)" es para filtrar el ASCII 13 del final de la cadena.
"Call ControlSerie" llama a otra rutina (si existe) que se encargue de hacer alguna acción dependiendo del valor de buffer2.
************************
Volviendo al tema de "usuario_registrado" (conseguite un nick!!!)
Protocolo "re-casero" (y fácil)
Supongamos que tenés que leer 3 pulsadores y 3 ADC"s....
En el pic te haces un programa que envíe los datos de esta manera según el caso. Te lo explico "metafóricamente" porque no sé en que lenguaje trabajás.
Pulsador 1: "1" + chr(13)
Pulsador 2: "2" + chr(13)
Pulsador 3: "3" + chr(13)
ADC1: "A" + valor1 + chr(13)
ADC1: "B" + valor1 + chr(13)
ADC1: "C" + valor1 + chr(13)
valor1..2..3 es el valor del ADC en cuestión, se manda toda la línea como una cadena (sin los +). En PicBasic sería "C",valor1,CR con CR como constante con el valor 13 (CR con 13").
El primer problema es que las cadenas tienen longitud variable.... para los pulsadores tenemos cadenas de 1 caracter mientras que para los ADC"s pueden ser de 4 o 5 caracteres (incluyendo el retorno de carro y suponiendo una conversión de 8 bytes).
La solución en VB aplicando los teoremas del ejemplo anterior es lo que sigue...
Vamos a crear el procedimiento "ControlSerie" anteriormente citado:
Public Sub ControlSerie()
Dim largo As Byte
Dim i As Byte
Dim idPote As String
Dim valPote As Integer
On Error GoTo salir
largo = Len(buffer2)
If largo = 1 Then ´Es un pulsador!!!
Select Case buffer2
Case "1"
"Acción para el pulsador nro 1.
Case "2"
"Acción para el pulsador nro 2.
Case "3"
"Acción para el pulsador nro 3.
End Select
Else
idPote = Left$(buffer2, 1) "Identifica si es A, B o C.
Select Case idPote
Case "A"
idPote = Right$(buffer2, largo - 2) "Ahora con el valor...
"idPote tiene el valor de A... hacer lo que haya que hacer acá!
Case "B"
idPote = Right$(buffer2, largo - 2) "Ahora con el valor...
"idPote tiene el valor de B... hacer lo que haya que hacer acá!
Case "C"
idPote = Right$(buffer2, largo - 2) "Ahora con el valor...
"idPote tiene el valor de C... hacer lo que haya que hacer acá!
End Select
End If
salir: "En caso de error se viene derecho para acá.
End Sub
********************
Espero que les sirva, por ahora me cansé de escribir, je je!!
Salu2.