Go Down

Topic: Proyecto: digitalización locomotora LGB años 40. (Read 1 time) previous topic - next topic

victorjam

#15
Nov 14, 2017, 08:05 pm Last Edit: Nov 14, 2017, 08:15 pm by victorjam
Hola chicos.

Ya lleva un tiempo sin decir nada y tengo algo mas listo.

Como comenté, el tren lleva dos placas. La del centro que lleva las conexiones de luces y chimenea y la de atrás que posee un regulador.

Aquí os muestro un detalle de la central:



Como ya no me vale he tenido que hacer una para realizar las nuevas conexiones de delante y detras.

He aquí el resultado:




Hacia ella van:

  • Las tres luces delanteras.
  • La corriente de las vias. La utilizo para alimentar la chimenea. Como no queriamos controlarla con el attiny, lo hacemos mediante un interruptor que va en la parte posterior y accede a la cabina de la locomotora.
  • El conector de las luces traseras, así como la salida a la placa trasera


He buscado las fotos de la placa trasera que hice, pero no las encuentro, se ve que las borre accidentalmente. Pero no tiene misterio, simplemente van los zócalos de las bombillas que ahora son leds (totalmente compatibles por suerte) y el conector que da corriente a los vagones traseros.

victorjam

#16
Nov 14, 2017, 08:31 pm Last Edit: Nov 14, 2017, 08:40 pm by victorjam
Ya tengo la locomotora finalizada.

No sé si se verá el video, no sé si no se ha subido o que pero aqui dejo el enlace.

https://youtu.be/KAODEfXU-tU

Para que lo veais.

Como aclaración, hemos cambiado la opción de control. La idea original era fabricarnos un mando a distancia con un Mega y una pantalla táctil, pero mi amigo pensó que le gustaba mas la idea de controlarlo desde el ordenador, ya que tiene una remesa de portatiles del año la pera sin uso y queria utilizar alguno.

Así que la opción de control es PC+Arduino+NRF24. Dado que el portatil es viejo: pentium M con 256 de RAM y XP de sistema operativo; estoy utilizando Borland Builder C++ 6.0 para hacer la interfaz del programa.



De momento con poco exito. Aunque el programa funciona y controlo las vias/locomotora, tengo una tasa de errores muy alta y un comportamiento anomalo del programa. Y llevo atascado con él mucho tiempo.

El mayor problema es la comunicación Arduino-PC. La red NRF funciona al 100% pero la comunicación serie da problemas y la verdad no lo entiendo.



Tengo dos versiones de programa. Una sin interfaz, consola o MSDOS, como querais llamarla. La tasa de errores en esta es baja, por no decir nula, pero cutre a mas no poder. En cambio la versión visual, es bonita, pero no sé porque falla.

Sé que el foro no es de programación en Windows, pero dado que lo comunico con un Arduino, si alguien me quiere aconsejar, será de mucho gusto por mi parte ofrecerle toda la información que precise.

PD. Ahora que lo veo y me he dado cuenta, os propongo un juego: mirar la foto de las vias. Teniendo en cuenta que la polaridad es fija en cada rail. ¿Notais algo raro?

noter

¿Con qué has programado el interfaz windows?
¿Qué problema o diferencia de funcionalidad te está dando respecto del interfaz de consola?
Puedes pegar o adjuntar el código del programa a ver si alguien puede detectar la posible fuente del problema.

victorjam

#18
Nov 15, 2017, 08:01 am Last Edit: Nov 15, 2017, 08:02 am by victorjam Reason: attachments
Utilizo un método de trabajo un poco raro:

Por norma general, lo primero es hacer un programa de consola que haga lo básico, en este caso, se trataba de mandar paquetes al arduino, analizar la
respuesta y mostrar. Cuando el código en consola funciona lo adapto a la interfaz gráfica.

En ambos casos he usado el compilador de Borland Builder C++ en su versión 6. No me pidais correr la version 10.2 en un pentium M por favor :D.

No utilizo ninguna libreria de comunciones de Delphi/BCB (TCommPort o similar), utilizo una propia utilizando la api de windows y creada de forma muy similar a la de Arduino: begin, read, write

Cuando envio información, lo que hago es crear un paquete con la estructura:

Code: [Select]

struct message {
 word fn;     // función a realizar.
 word value;  // parametro de la función.
 word option; // parametro opcional, no se usa, pero está ahi.
};

class query {
 word to;     // para quien es el mensaje.
 message msg; // mensaje, función y valor.
};


El PC necesita enviar una peticion o query, a un determinado dispositivo to con un determinado mensaje msg. Para ello lo transmite al Arduino, que recibe el mensaje y se encarga de transmitirlo por radio. El Arduino recibe la respuesta del dispositivo y se la manda al PC como respuesta
utilizando la misma estructura de mensaje.

Quote
Como curiosidad, y como demostración de que todos los compiladores no son iguales, primero intente enviar la estructura por el puerto serie directamente, pero daba errores hasta que me di cuenta que sizeof(query) en el IDE de arduino es 8 (lo lógico y normal), y en BCB es 9 (me sobra un byte...). De hay que tubiera que pasar la información a un array.
query es una clase que tiene un método send() que envia por puerto serie el mensaje, espera la respuesta y la procesa, comprobando si hay errores en la comunicación.

La locomotora tiene un mecanismo de seguridad, que si no recibe un mensaje en un minuto, este como este, se para. Este mecanismo lo pensé en un principio por si fallaba la radio evitar que la locomotora descarrilase. Por ello en la interfaz visual utilizo un hilo para la comunicación que siempre envia a las vias y a la locomotora un mensaje para ver su estado.

En consola, hay un bucle que infinito que si hay una tecla pulsada asociada a un determinado mensaje, lo envia y procesa. Incluso un modo automatico que cada x tiempo manda un mensaje para ver el estado de la via y de la locomotora.

En ambos caso compruebo los errores, llevando una cuenta de ellos y en consola muestro siempre el código de error devuelto. En la interfaz visual, aun no me he propuesto ver el error pero si sé cuantos hay y lo que tarda en ejecutarse el bucle del hilo. Generalmente el mayor error que hay en la interfaz visual es de timeout: no recibe respuesta aunque la trama se halla enviado bien.

Os adjunto el código que llevo hasta ahora:

  • Unit1 es el dialogo principal (pantalla de vias y locomotora).
  • Unit2 es el dialogo de configurar el puerto serie.
  • Unit3 no hace nada de momento, formulario vacio.
  • Unit4 donde está el código de las locomotoras.
  • Unit5 el hilo de trabajo. Es una clase TThread de BCB.
  • cserial es la libreria del puerto serie.
  • winmess, es una rutina que muestra un mensaje en caso de que la llamada a una api de windows falle, mas que nada para saber por qué.


No tengo a mano el código de consola, pero esta tarde lo subiré sin falta.

victorjam

He aquí el código de consola (No cabe en todo el post, así que continuará en el siguiente):

Code: [Select]

// debug es una macro que ayuda a la verificación del programa.
#define debug

#include "CSerial.h"
#include <stdio.h>
#include <conio.h>

// Incluyo el fichero .cpp directamente para no tener que crear un proyecto.
#include "cserial.cpp"

CSerial Serial;

#define MAX_FRAMESIZE 256
#define HI(x) ((x)>>8)&0xFF
#define LO(x) ((x)&0xFF)

//@ Define los errores que se pueden producir al enviar un mensaje.
#define QRY_NO_ERROR        0
#define QRY_NO_SERIAL_OPEN  1
#define QRY_ERROR_TIMEOUT   2
#define QRY_ERROR_OVERFLOW  3
#define QRY_ERROR_UNDERFLOW 4
#define QRY_ERROR_ID        5

//@ Funciones al estilo Arduino.
#define delay(x) Sleep((x))
#define millis() GetTickCount()

//@ Estan tomados del código de la libreria de ModBus.
unsigned int T1_5=2;
unsigned int T3_5=37;

//@ Parametros que deseo de vias y de locomotora.
int velocidad=0;
int velocidad_deseada=0;
int direccion=0;
int error=0;
int vias;

//@ Estructura del mensaje. Es el payload del NRF, es decir, lo que cada radio
//  se transmite entre ellas.
struct message {
  unsigned short function; // Función a ejecutar.
  unsigned short value;    // Valor del parametro de la función.
  unsigned short option;   // Un valor opcional.
};

//@ Clase query. Es lo que el Arduino y el PC se retransmiten. Lleva implicito
//  un miembro to que es la dirección de destino del mensaje (locomotoras o
//  vias ).
class query {
public:
    unsigned short to;
    message msg;
query();
    query (unsigned int _to, unsigned short _fn, unsigned short _val, unsigned short _opt);
int send(CSerial &Serial);
    void show();
  private:
    //@ El id del destino y el mensaje lo introduciré en un array que será el
    //  paquete que enviare. Tengo también el tamaño.
    unsigned char frame[MAX_FRAMESIZE];
    int framesize;
    //@ En la llamada a send(..) define el tiempo que esperará antes de dar un
    //  error de timeout.
    int timeout_time;
   
};

//@ Solo sirve para mostrar la información del mensaje.
void query::show() {
  printf("query.to           =%4x\n", to);
  printf("query.msg.function =%4x\n", msg.function);
  printf("query.msg.value    =%4x\n", msg.value);
  printf("query.msg.option   =%4x\n", msg.option);
  printf("--------------------------\n");
}

//@ Crea un mensaje pasandole los parametro to (para quien) y el mensaje { fn,val,opt }
query::query(unsigned int _to, unsigned short _fn, unsigned short _val, unsigned short _opt) {
to = _to;
msg.function = _fn;
msg.value = _val;
msg.option = _opt;
  timeout_time = 5000;
}

//@ Un constructor vacio.
query::query() {
to = 00;
msg.function = 0x00;
msg.value = 0x00;
msg.option = 0x00;
  timeout_time = 5000;
}

//@ La función enviar... es el corazón del programa:
int query::send(CSerial &Serial) {
   int i,j;
   unsigned short crc;
   // Comprobamos que el puerto serie está abierto, si no lo está salimos.
   if ( !Serial.isOpen() ) return QRY_NO_SERIAL_OPEN;

   // Preparamos el frame.
frame[0]=LO(to);
frame[1]=HI(to);
frame[2]=LO(msg.function);
frame[3]=HI(msg.function);
frame[4]=LO(msg.value);
frame[5]=HI(msg.value);
frame[6]=LO(msg.option);
frame[7]=HI(msg.option);
   framesize=8;
   #ifdef debug
     // Muestra el frame...
     gotoxy(1,9); printf(">>");
     for (j=0; j<framesize; j++) printf("[%X]", frame[j]);
   #endif
   

   // Enviamos el frame.
   for (i=0; i<framesize; i++) {
     Serial.write(frame[i]);
     //Sleep(T1_5);
   }
   //@ Dado que tenia problemas con la velocidad, habia veces que esperando
   //  el tiempo indicado como T1_5, mejoraba.

   
   //@ Este tiempo es necesario. No sé porque, si no espero 150ms no recibo
   //  absolutamente nada. La respuesta debería ser inmediata.
   Sleep(150);

   //@ Espero el tiempo de espera, si pasa demasiado tiempo damos un mensaje
   //  de error timeout.
   DWORD t;
   t = GetTickCount();
   while ( !Serial.available() ) {
     if ( GetTickCount() > t + timeout_time ) {
       return QRY_ERROR_TIMEOUT;
     }
   }

   //@ Ya hay datos en el puerto serie. Debemos leerlos todos (si hay mas bytes
   //  también.
   i=0; unsigned char b;
   while ( Serial.available() ) {
     b = Serial.read();
     if ( i < MAX_FRAMESIZE ) frame[i]=b;
     i++;
     Sleep(2);
   }
   //@ Aquí esperaba otros 150 ms para poder seguir, pero este no es necesario.
   //Sleep(150);

   //@ Hay mas caracteres de los deseados: error de overflow.
   if ( i>8 ) return QRY_ERROR_OVERFLOW;
   //@ Hay menos caracteres de los deseados: error de underflow.
   if ( i<8 )
   {
     if ( Serial.available() ) while ( Serial.available() ) Serial.read();
     return QRY_ERROR_UNDERFLOW;
   }

   //@ Comprobamos el id para ver que hemos recibido algo correcto.
   unsigned short _to = frame[1]<<8 | frame[0];
   if ( to != _to )
     return QRY_ERROR_ID;
   #ifdef debug
     //@ Muestro lo que he recibido.
     gotoxy(1,10); printf("<<");
     for (j=0; j<i; j++) printf("[%X]", frame[j]);
     delay(2000);
   #endif
   //@ Obtengo la información que me ha devuelto el arduino en el
   //  query.
   to = _to;
   msg.function = frame[3]<<8 | frame[2];
   msg.value    = frame[5]<<8 | frame[4];
   msg.function = frame[7]<<8 | frame[6];
   //@ Retorno sin errores.
   return QRY_NO_ERROR;
}

//@ Estas cadenas sirven para mostrar el error que ha sido.
char *errorString[]= {
  "OK",
  "FALLO: Leer velocidad.",
  "FALLO: Al poner velocidad.",
  "FALLO: La máquina no esta parada, no se pueda cambiar la direccion",
  "FALLO: Al cambiar la direccion",
  "FALLO: Al parar la maquina",
  "FALLO: Al leer el estado de la via",
  "FALLO: Al cambiar la via"
};

//@ Leer las vias el mensaje es {01,01,00,00}.
void leerVias() {
  int r;
  query q = query(01,01,00,00);
  r = q.send(Serial);
  if ( r==QRY_NO_ERROR ) {
    error=0;
    vias=q.msg.value;
  }
  else
    error=6;
}

//@ Cambiar via. El mensaje tiene al forma {01,02,via,00}.
void cambiarVia(int v) {
  int r;
  query q = query(01,02,v,0);
  r = q.send(Serial);
  if ( r==QRY_NO_ERROR ) error=0;
  else
    error=7;
}

//@ Leer la velocidad. El mensaje tiene la forma {02,00,00,00}
//  La respuesta ha de ser un mensaje { 02, 00, velocidad, direccion }
void leerVelocidad(){
  int r;
  query q = query(02,00,00,00);
  r = q.send(Serial);
  if ( r==QRY_NO_ERROR )
  {
    velocidad = (int)q.msg.value;
    direccion = (int)q.msg.option;
    error = 0;
  }
  else
    error = 1;
}
//@ Poner la velocidad. El mensaje tiene la forma {02, 01, velocidad, 00 }
void ponerVelocidad(int x)
{
  int r;
  query q = query(02,01,x,00);
  r = q.send(Serial);
  if ( r==QRY_NO_ERROR )
    error = 0;
  else
    error = 2;
}

//@ Poner direccion. El mensaje tine la forma {02, 02, direccion, 00}
//  donde direccion puede ser 2 (hacia atrás) o 1 (hacia delante).
//  Como protección del motor la locomotora solo permite cambiar la
//  dirección cuando la máquina está parada. Si la velocidad no es 0
//  nos devuelve un mensaje {02, 02, FF, 00} indicando que no puede
//  cambiar la dirección.
void pondireccion(int d) {
  int r;
  query q = query(02,02,d,00);
  r = q.send(Serial);
  if ( r==QRY_NO_ERROR )
  {
    if ( q.msg.value==0xFF ) error=3;
    else error=0;
  }
  else
    error=4;
}

//@ PARADA DE EMERGENCIA. Para la locomotora de golpe, poniendo la
//  direccion y la velocidad a 0 de golpe. El mensaje es de la
//  forma {02, 03, 00, 00}
void parar() {
  int r;
  query q = query(02,03,00,00);
  r = q.send(Serial);
  if ( r==QRY_NO_ERROR ) error=0;
  else error = 5;
}

 

victorjam

Continuación del código:

Code: [Select]


// Aquí el programa pirncipal.
void main()
{
 
  //@ Mi arduino lo detecta en el puerto 28. Así que abrimos el
  //  puerto serie.
DWORD dwErr = Serial.begin(28,9600,SERIAL_8N2);
if ( dwErr!=NO_ERROR ) {
printf("No se puede abrir el puerto!");
return ;
}
  //@ Otro de mis intentos de reducir errores.
  Serial.timeouts();
 

  bool exit=false;
  bool automatic=false;
  int result;
  velocidad = 0;
  DWORD timer;
  long errorcount=0;
  // bucle infinito.
  // Si hay una tecla ejecuta la correspondiente acción asociada a ella.
  while ( !exit )
  {
    clrscr();
    gotoxy(1,1);
    printf("[ESC] Salir [Up] Subir [Dn] Bajar [Rt][Lt] Direccion [Space-Leer] [Enter] Poner\n");
    printf("[p] Auto [s] Parar [1..8] Cambiar vias\n");
    printf("Velocidad: %d Velocidad deseada: %d\n", velocidad, velocidad_deseada);
    printf("Direccion: %d \n", direccion);
    printf("Vias: %d\n", vias);
    printf("Contador de errores: %d\n", errorcount);
    printf("Error: %s\n", errorString[error]);
    printf("%s\n", automatic?"SI":"NO");
    if ( kbhit() )
    {
      char ch = getch();
      switch ( ch ) {
        case 72: if ( velocidad_deseada < 255 ) velocidad_deseada++; break;
        case 80: if ( velocidad_deseada > 0 )   velocidad_deseada--; break;
        case 75: pondireccion(2); break;
        case 77: pondireccion(1); break;
        case 32: leerVelocidad(); break;
        case 13: ponerVelocidad(velocidad_deseada); break;
        case 27: exit=true;
        case 83: parar(); break;
        case 115: parar(); break;
        case 90: leerVias(); break;
        case 122: leerVias(); break;
        case 49: cambiarVia(1); break;
        case 50: cambiarVia(2); break;
        case 51: cambiarVia(3); break;
        case 52: cambiarVia(4); break;
        case 53: cambiarVia(5); break;
        case 54: cambiarVia(6); break;
        case 55: cambiarVia(7); break;
        case 56: cambiarVia(8); break;
        case 112: automatic=!automatic; timer=millis(); break;
        default: break;
      }
    if ( error!=0 ) errorcount++;
    }
    else
    {
      // Para que no de pantallazos.
      delay(100);
    }
    if ( automatic )
    {
      // En modo automatico lee la locomotora cada 5s aunque no se haya pulsado
      // una tecla.
      if ( millis() > timer + 5000 ) {
        leerVelocidad();
        timer = millis();
      }
    }
  }

  //@ Al salir del programa cerramos el puerto de comunicaciones.
  Serial.close();
}


También lo añado como attachment para aquel que quiera descargarlo.

victorjam

Obviamente, sin el código del mando, me direis que no se puede hacer nada:

Code: [Select]

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define NODE 00

#define MAX_BUFFER_LEN 32

struct message {
  unsigned int function;
  unsigned int value;
  unsigned int option;
};

struct query {
  unsigned int to;
  message msg;
};

query q;

RF24 radio(9,10);           // La radio.
RF24Network network(radio); // La red.
bool chipConnected;         // Indica que hemos detectado el chip.

// Hace parpadear un pin. Me sirve para indicar que la radio está o
// conectada.
void flash(int pin) {
  digitalWrite(pin,HIGH);
  delay(500);
  digitalWrite(pin,LOW);
  delay(500); 
}

// Lo mismo, pero le indicamos cuantas veces (y el tiempo).
void flash(int pin, int many, int duration=500) {
  for (int i=0; i<many; i++) {
     digitalWrite(pin, HIGH);
     delay(duration);
     digitalWrite(pin, LOW);
     delay(duration);
  }
}

// Sirve para comprobar que en el puerto serie tenemos datos y leemos
// lo que hemos de enviar.
int update_query(query &q) {
  int i;
  byte frame[MAX_BUFFER_LEN];
  byte b;
  // Si hay datos en el puerto serie los leemos.
  i=0;
  if ( Serial.available() ) {
    while ( Serial.available() ) {
      b = Serial.read();
      if ( i<MAX_BUFFER_LEN ) frame[i]=b;
      i++;
      delayMicroseconds(1562); //  OJO! sin esto no funciona.
    }
  }
  else
    return 0; // Si no hay datos no hacemos nada.
 
  // El frame es fijo y es 8. Retornamos de la funcion y salimos sin hacer nada.
  // esto provocara un error de timeout en el ordenador.
  if ( i!=8 ) { Serial.flush(); return 0; }

  // No hacemos otro tipo de corrección. En el frame esta el valor query y lo
  // obtenemos.
  q.to           = frame[1]<<8 | frame[0];
  q.msg.function = frame[3]<<8 | frame[2];
  q.msg.value    = frame[5]<<8 | frame[4];
  q.msg.option   = frame[7]<<8 | frame[6];
 
  return 1;
}

// Responder a una consulta. Solo envia la consulta por el puerto serie.
int response_query(query &q) {
  Serial.write((unsigned char*)&q, sizeof(query));
  Serial.flush();
  //delayMicroseconds(37000);
}

// Escribe en la red, la consulta.
bool netWrite(query &q) {
  RF24NetworkHeader h(q.to);
  return network.write(h, &q.msg, sizeof(message));
}

// Lee de la red una consulta.
bool netRead(query &q) {
  RF24NetworkHeader h;
  network.read(h, &q.msg, sizeof(message));
  q.to = h.from_node;
}

void setup() {
  Serial.begin(9600,SERIAL_8N2);
  while(!Serial);
  pinMode(2,OUTPUT);
  digitalWrite(2,LOW);

  radio.begin();
  network.begin(90,NODE);
  chipConnected = radio.isChipConnected();
}

void loop()
{
  network.update(); // Comprobamos la red.
  // Si hay un paquete disponible se lo mandamos al PC.
  if ( network.available() ) { netRead(q); response_query(q); }
  // Si hay un mensaje por parte del PC, lo enviamo a la red
  if ( update_query(q) )
  {
    // El paquete es para la red, no para el mando, así que lo escribe.
    if ( q.to!=00 )
      netWrite(q);
    else
    {
      // El paquete es para el mando, de momento solo sirve para ver
      // si el chip esta conectado {00,00,00,00} y hacer que se encienda
      // un led en el pin 2 {00, 01, 00, 00}.
      if ( q.msg.function=0x00 ) q.msg.value=radio.isChipConnected();
      if ( q.msg.function=0x01 ) digitalWrite(2, q.msg.value);
      // Responde directamente, no tiene que esperar a que hay un mensaje
      // de radio ni nada.
      response_query(q);
    }
  }



victorjam

Voy a explicaros un poco la libreria serial que utilizo. La libreria la desarrolle hace un tiempo, cuando era aficionado a los GPS y tuve la necesidad de leer datos de un GPS Garmin en el ordenador. La libreria funcionaba bien con él. Con el tiempo la he ido adaptando. Cuando me enfrenté a la tarea de conectar un pc y convertirlo en un maestro Modbus, la cambié un poco. Y luego vi que me gustaba mas la forma de las funciones de la libreria Serial de Arduino y la reescribí otra vez un poco.

Básicamente utiliza la api de win32 y las funciones asociadas a él. No explicaré como se hace ya que hay un tuto bastante bueno en la parte de documentación escrito por Metaconta, que por cierto ¿estas por ahí?, creo que tu me podrías ser de ayuda...

La librería consta de la siguientes funciones:

begin

Inicializa el puerto serie, pero no lo abre. Sirve para indicar los parametros de puerto, velocidad, bits de datos, bits de stop y bits de parada. Al principio utilizaba solo una función setConfig que era un poco engorrosa de llamar. Así que al final se ha quedado en la forma de Arduino:

Code: [Select]

    Serial1.begin(1,9600,SERIAL_8N2);
    Serial2.begin(2,9600); // Por defecto es SERIAL_8N2 usado en el modbus.


open/close

Abre o cierra el puerto serie. En el caso de la apertura, crea un handle al fichero, y prepara las estructuras necesarias para su uso. En caso de fallo devuelve
el error. Para saber si el puerto serie esta abierto se puede llamar a la función isOpen(..)

read/write

Lectura/escritura del puerto serie. Igualmente que en Arduino se puede usar de dos formas: leer o escribir un byte, o un array. De momento no he implementado una funcion print, ni creo que sea necesario por ahora. Ejemplos:

Code: [Select]

    unsigned char *puntero;
    Serial1.write(b);                       // Escribe un byte.
    Serial1.write(puntero, cantidad_bytes); // Escribe un array.
    Serial2.read(b);                        // Lee un byte.
    Serial2.read(puntero, cantidad_bytes);  // Lee un array.


available

Igualmente que en arduino indica cuantos caracteres hay disponibles en la cola del puerto serie, si no hay ninguno devuelve 0.

Por último quedan las funciones: setRTS(..), restore(..) y timeouts(..) . La primera fue un experimento fallido para intentar controlar el circuito del modbus, poniendo el pin RTS del RS232 conectado a los pins RE/DE del MAX485. Aunque la función trabaja perfectamente, no conseguí que la linea de control cambiará. restore elimina los posibles errores que haya en el RS232 y la última, timeouts, modifica los valores por defecto en los que el RS232 del PC dará un time out.

Si alguien quiere usarla, y sobretodo, si me la quiere corregir, que lo haga, ni licencias ni nada, solo que si le ve un fallo, me lo indique para poder corregirlo. La dejaré como attachment, aunque ya está incluida cuando subí el código del programa en Builder C++.






Go Up