Envío de archivos vía puerto serie (VB6)

Hola de nuevo. En este post les voy a presentar un experimento que recientemente hice en Visual Basic 6.0.

Decidí hacerlos por 3 cosas:

  • Me encanta Visual Basic 6 xD
  • Tenía un poco de tiempo libre
  • No he visto muchos ejemplos de esto en Internet (búsqueda en Google, Youtube)

El video con la demostración está en mi canal de Youtube

Para comenzar hay que tener en cuenta ciertas consideraciones:

  • La transferencia del archivo es byte por byte, será más, o menos rápida dependiendo de la velocidad con la que trabajamos el puerto serie (baudios por segundo).
  • Podemos calcular el retardo que ha de haber entre el envío de un byte y otro de acuerdo a los baudios por segundo que tengamos configurados en el puerto serie.
  • El tamaño máximo del archivo a enviar está determinado por el tamaño máximo de un arreglo. En VB6 es el valor máximo de la parte positiva de Long, esto es (2^31)-1 bytes = 2Gb.
  • La aplicación cliente, tendrá que capturar lo que se envía por el puerto serie e irlo almacenando en memoria, después, al “guardar” solo meteremos el contenido de la memoria en un archivo.
  • Para probar la aplicación en la misma PC, unir los puertos 2 y 3 (RX / TX) del puerto serie.

Conceptos básicos del puerto serie

El objetivo de este post no es enseñarte los conceptos básicos del puerto serie, pero tampoco puedo omitir algunas generalidades:

Lógica inversa: Para representar un bit, el  protocolo RS232 utiliza valores entre -15/-3v y +3/+15v (típicamente -12v y +12v), de tal forma que -12v equivalen a 1 y +12v equivalen a 0. La imagen representa la transmisión de algunos bits usando -15v (1) y +15v (0).

Baudios por segundo: Es el número de cambios en el estado de la señal que suceden en un segundo. Si la señal cambia de estado 100 veces en un segundo, se dice que la velocidad del puerto es de 100 baudios por segundo. La siguiente imagen muestra la representación de 2 baudios por segundo.

2 baudios por segundo

Configuración: Para que las aplicaciones que se comunican usando RS232 “se entiendan” deben someterse a cierta configuración. Estos son algunos de los parámetros que podemos cambiar en la misma:

  • Bit de inicio y el bit de parada. Sin estos bits, los dispositivos conectados no sabrían donde termina un caracter y empieza otro. Cuando se recibe un bit de inicio (binario 0), se entiende que un número fijo de bits (determinado por el parámetro bits de datos), sigue al bit de inicio. A continuación, el sistema recibe uno o dos bits de parada (binario 1).
  • Bit de paridad. Para verificar la integridad del caracter enviado se utiliza el bit de paridad, esta puede ser par o impar. Por ahora no adentraré en este tema.
  • Velocidad. Es el número de baudios que se transmiten en un segundo, el valor más utilizado es 9600.
  • Bits de datos: Especifica cuántos bits de datos se envían después del bit de inicio. Usualmente son 7 u 8. Si se ocupan 7 bits de datos, podrémos representar un caracter de la tabla ASCII, esto es, de CHR$(0) a CHR$(127) . Si se ocupan 8 bits de datos, podrémos transmitir un caracter de la tabla ASCII extendida -de CHR$(0) a CHR(255)-.

La configuración que utiliza la aplicación que muestro es: 9600 baudios por segundo, 1 bit de inicio, 1 bit de parada, sin paridad (esto podemos abreviarlo como 9600,N,8,1).

Configuración: 9600,N,8,1

Baudios por segundo vs bits por segundo: Un error común es afirmar que la velocidad de baudios es equivalente a la velocidad de bits, si bien un baudio representa sin problemas un bit, ambas velocidades no son las mismas; ya que, considerando una configuración donde se usa un bit de inicio, ocho bits de datos y un bit de parada se requieren 10 bits para transmitir un caracter (1 + 8 + 1 = 10).

Calcular bits por segundo en relación a los baudios por segundo

Recordemos que esta aplicación enviará archivos, y tal como se hace siempre que se envían archivos, serán enviados byte por byte. Para darle tiempo de que envíe un byte antes de enviar el otro, debemos calcular cuanto tarda en enviar cada uno, esto con el fin de hacer un retardo mayor antes de enviar el otro.

Sabiendo la configuración que usaremos en el puerto serie tenemos: (bps=baudios por segundo)

  • 9600 bps. Sin bit de paridad, 1 bit de inicio, 1 bit de parada = 10 bits por caracter.
  • Dividimos 9600 bps / 10 bits que usa cada caracter = 960 (transmitiremos 960 bytes por segundo)
  • Como cada byte tiene 8 bits, calculamos la velocidad de transmisión: 960 *8 =  7680 bits/s (este paso es meramente informativo).
  • Calculamos cuanto tarda el envío: (1 segundo / 960 bytes por segundo) * 1000 = 1.04166666 bytes/milisegundo.

De tal forma que un retardo mayor a  1.05 funciona. Yo utilicé 50 milisegundos, a que es un valor estándar.

Formulario de la aplicación ejemplo

El formulario de la aplicación es bastante simple. Del lado derecho tenemos los siguientes controles: DriveList, FolderList y FileList, los cuales sincronizamos para que podamos elegir el archivo a enviar. Esta parte es la que se usa en la computadora que va a enviar los archivos.

Desde la computadora que se usará para recibir el archivo, usarémos la parte izquierda del formulario, la cual solo tiene 2 botones: uno para poner a escuchar el puerto y otro para guardar lo capturado.

También posee un cuadro de texto donde aparecen los bytes recibidos que se van almacenando en la memoria.

Enviar el archivo byte por byte

Para asegurar que se envía y recibe un byte a la vez, se cambian las siguientes propiedades del control COM en tiempo de diseño:

  • InBufferSize = 1
  • OutBufferSize = 1

La propiedad InBufferSize establece cuantos bytes pueden quedar a la espera de ser recibidos. Estos serán leídos cuando llamemos a la propiedad Input del control COM.

La propiedad OutBufferSize establece cuantos bytes serán enviados cada vez que llamemos a la propiedad Output del control COM.

Para enviar el archivo debemos abrirlo en modo binario, esto para poder leerlo byte a byte e irlo enviando.

Al abrir el archivo en modo binario, este contará con un apuntador colocado en el primer byte, dicho apuntador podemos moverlo a diferentes posiciones para apuntar a otro byte.

Usaremos también la función LOF() para determinar el tamaño del archivo y saber cuantas posiciones podemos mover el apuntador:

' obtenemos un número de archivo disponible
nFile = FreeFile

' en txSendFile.Text está la ruta completa del archivo a enviar
' lo abrimos en modo binario, eso coloca el apuntador en la primera posición
Open txSendFile.Text For Binary As #nFile 

' Con la funcion LOF, obtenemos el tamaño del archivo en bytes
fileLenght = LOF(nFile) 

' La siguiente variable es para ir moviendo el apuntador
i = 0

' recorremos el archivo con un while
Do While Not EOF(nFile)
 ' leemos el byte apuntado y lo metemos a la variable dataa
 Get nFile, , dataa
 
 ' pausas para que termine la lectura
 DoEvents: DoEvents: DoEvents

 ' movemos el apuntador al siguiente byte
 i = i + 1

 ' enviamos el byte leído
 MSComm1.Output = Chr$(dataa)
 
 ' hacemos el retardo
 Sleep (50)
Loop

'cerramos el archivo 
Close nFile
MsgBox ("Envío completado" & vbCrLf & i & " bytes enviados."), vbInformation + vbOKOnly, "Envío de archivos por puerto serie"

Captura de los bytes enviados

La captura de los bytes enviados se realiza en un control Timer que tiene intervalos de 50ms, dicho intervalo debe ser igual al especificado en el envío.

Se irán leyendo los bytes recibidos a la vez que se se almacenan en un arreglo del tipo Byte. Como no sabemos el tamaño del archivo, no podemos fijar el tamaño de dicho arreglo, así que este irá creciendo dinámicamente con ReDim Preserve.

' verificamos si hay bytes a la espera de ser leídos
If MSComm1.InBufferCount > 0 Then
  ' Aumentamos el tamaño del arreglo sin eliminar los datos que ya contiene
  ' bytesRecibidos al comienzo es 0, iremos incrementándolo para
  ' saber qué tamaño darle al arreglo. buf es el arreglo
  ReDim Preserve buf(bytesRecibidos)

  ' Metemos el Byte recibido en la última posición del arreglo
  buf(bytesRecibidos) = Asc(MSComm1.Input)

  ' Mostramos el byte recibido
  txBytesRecibidos.Text = txBytesRecibidos.Text & Chr$(buf(bytesRecibidos))

  ' aumentamos en uno los byes recibidos, para tener donde guardar el siguiente
  ' byte
  bytesRecibidos = bytesRecibidos + 1
End If

Para guardar el archivo, unicamente convertimos los bytes del arreglo en un String Unicode y metemos el resultado en un archivo

datas = StrConv(buf, vbUnicode)
 filito = FreeFile
 Open "\bufer.txt" For Append As #filito
 Print #filito, datas
 Close #filito

Probar aplicación ejemplo en la misma PC

Para probar la aplicación, solo debes unir los pines 2 y 3 del puerto serie de tu ordenador (RX y TX)

Probar la aplicación en 2 PCs diferentes

Unimos los puertos serie de ambas computadoras de manera cruzada mediante los pines 2 y 3 (RX y TX), además de conectar el Pin 5 (GND).

Descarga el ejemplo

Para descargar el ejemplo, clona o guarda como ZIP este repositorio de Github https://github.com/underdog1987/VB6-Send-Files-Via-SerialPort

Si te gustó y/o sirvió, considera realizar una donación. Con ello me ayudarás a continuar realizando nuevos proyectos.

  • Donar vía Paypal
  • Donar con BTC: 18mjrDBQShvN6cCdkkTmzwJMqdqMCrLoC1
  • Donar con BTC (opción 2): 3C2PAkh17xDvFfCREaNmRRgxyWijkYovwB
  • Donar con ETH: 0xe07f56439c70A0aceCEfDf6E560CC484bafE64fC
  • Donar con ETH (opción 2): 0x2eb00a33bd27ba903a4a526b958e774764a63289

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.