Encontre un post en github (clic aquí) en donde elaboran un convertidor de MDB a RS232 usando un ARDUINO MEGA como maestro y Arduino Uno como esclavo MDB. Lo he probado con un validador de billetes y funciona bien.
He intentado modificar el código para que solo use un solo Arduino en la comunicación, el problema radica en que no logro poner el validador de billetes en estado
activo. El validador es de la marca MEI modelo CXB2. Estoy usando un arduino mega 2560. He estado enviando la siguiente secuencia para la intentar
activar el validador (la misma que la del proyecto).
- RESET
- POLL
- SETUP
- BILL TYPE
- POLL
Las 4 primeras instrucciones las envío desde el void setup, la quinta instrucción la estoy constantemente enviando desde el void loop, pero la respuesta que obtengo siempre es validador inactivo (06 09 0F). La verdad estoy atorado y no se en donde me estoy equivocando. Anexo codigo, por el momento, solo estoy leyendo datos HEX. De antemano gracias.
/* Instrucciones del validador de billetes */
#define RESET 0x30
#define SETUP 0x31
#define SECURITY 0x32
#define POLL 0x33
#define BILL_TYPE 0x34
#define ESCROW 0x35
#define STACKER 0x36
#define EXP_CMD 0x37
/* Estructura para manejar datos MDB */
struct MDB_Byte {
byte datos;
byte modo;
};
struct MDB_Byte MDB_Buffer[37]; // Buffer para leer datos desde el dispositivo MDB
struct MDB_Byte CMD_RST[2] = { {0x30,0x1},{0x30,0x0} };
struct MDB_Byte CMD_POLL[2] = { {0x33,0x1},{0x33,0x0} };
struct MDB_Byte CMD_SETUP[2] = { {0x31,0x1},{0x31,0x0} };
struct MDB_Byte CMD_BILL[6];
struct MDB_Byte CMD_STK[2] = {{0x36,0x1},{0x36,0x0}};
volatile int MDB_Buffer_Count=0;
// Indicadores de estado de la recepcion de datos de MDB
int rcvcomplete; // Mensaje MDB recibido
int mdboverflow; // Mensaje MDB incorrecto
byte MsgError = 0x00;
byte MsgAnt = 0x01;
void setup() {
Serial.begin(9600); // PC
MDB_Config(); // Hacia el MDB, Puerto Serial1
/*Secuencia que debe seguir la activación del MDB*/
// COMANDO RESET
MDB_Buffer_Count = 0;
for(int i =0; i < sizeof(CMD_RST); i++)
{ write_9bit(CMD_RST[i]);}
delay(500);
// COMANDO POLL
for(int i =0; i<sizeof(CMD_POLL); i++)
{ write_9bit(CMD_POLL[i]); }
MDB_Buffer_Count = 0 ;
if( Procesar_Respuesta() >= 1 )
{ for(int i =0; i < MDB_Buffer_Count; i++)
{ Serial.write(MDB_Buffer[i].datos ); }
}
delay(30);
//COMANDO SETUP
for(int i =0; i < sizeof(CMD_SETUP); i++)
{ write_9bit(CMD_SETUP[i]); }
MDB_Buffer_Count = 0 ;
if( Procesar_Respuesta() >= 1 )
{ for(int i =0; i < MDB_Buffer_Count; i++)
{ Serial.write(MDB_Buffer[i].datos ); }
}
// COMANDO BILL
CMD_BILL[0] = {0x34,0x1};
CMD_BILL[1] = {0xFF,0x0};
CMD_BILL[2] = {0xFF,0x0};
CMD_BILL[3] = {0x00,0x0};
CMD_BILL[4] = {0x00,0x0};
CMD_BILL[5] = {0x32,0x0};
for(int i =0; i < sizeof(CMD_BILL); i++)
{ write_9bit(CMD_BILL[i]); }
}
void loop() {
MDB_Buffer_Count = 0 ;
for(int i =0; i<sizeof(CMD_POLL); i++)
{ write_9bit(CMD_POLL[i]); }
if( Procesar_Respuesta() >= 1 )
{ for(int i =0; i < MDB_Buffer_Count; i++)
{ Serial.write(MDB_Buffer[i].datos ); }
}
delay(500);
}
void MDB_Config()
{
/* Configuracion del Baud Rate a 9600 bps. Pags 223-226 hoja de datos ATMEGA2560
vienen tablas con valores para valores conocidos de frecuencia de reloj */
UBRR1H = 0; UBRR1L = 103;
/* Configuracion del registro UCSR0A -> USART CONTROL AND STATUS REGISTER A
Elimina el double speed USART */
UCSR1A &= ~(1<<U2X1);
/* Configuracion de paridad, stop bits y modo de transmision asincrono
Para ello se modifica el registro UCSR0C (Pag 220-221 datasheet atmega2560):
Modo asincrono: Bit UMSELn1 y Bit UMSELn0, ambos en 0
Sin paridad : Bit UPMn1 y Bit UPMn0 ambos en 0
1 Bit de Stop: Bit USBSn en 0
Tamano de caracter : Bits UCSZn1 - UCSZn0 Bits. Para 8 bits ambos en 0
El noveno bit de tamano puede ser establecido poniendo
en 1 el bit UCSZn2 del registro UCSRnB */
UCSR1C = (0<<UMSEL11)|(0<<UMSEL10)|(0<<UPM11)|(0<<UPM10)|(0<<USBS1)|(1<<UCSZ11)|(1<<UCSZ10);
/* Se pone en 1 para que envie 9 bits de datos*/
UCSR1B |= (1<<UCSZ12);
/* Activacion de los pines TX y RX */
UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
}
// Escribe conjuntos de bytes MDB
void write_9bit(struct MDB_Byte mdbb)
{ while( !(UCSR1A)&(1<<UDRE1)); //Espera a que se vacie el buffer de transmision
if(mdbb.modo == 0x1)
UCSR1B |= (1<<TXB81); // Escribe '1' en el 9no bit
else
UCSR1B &= ~(1<<TXB81); //Escribe '0' en el 9no bit
UDR1 = mdbb.datos; // Se copia el dato a enviar
}
/*Funcion para leer 9 bits de datos. */
unsigned int read_9bit()
{ unsigned char resh, resl;
int rtr = 0;
/*Espera para recibir los datos*/
while( ( !(UCSR1A & (1<<RXC1)) ) and rtr <50 )
{ delay(1); //rtr ++;
}
if(rtr == 50) {
mdboverflow = 1; rcvcomplete = 1; }
/*Obtiene el 9 bit, luego, los datos del buffer*/
resh = UCSR1B;
resl = UDR1;
resh = (resh>>1) & 0x01; // Se filtra el 9 bit
return ( (resh << 8) | resl ); // Se regresa los 8 bits de datos
}
void MDB_getByte(struct MDB_Byte* mdbb) {
int b;
b = 0;
b = read_9bit();
memcpy(mdbb,&b,2);
}
byte MDB_CHK() { // Validador de checksum de datos provenientes del MDB
int sum = 0;
for(int i=0; i<(MDB_Buffer_Count-1); i++)
sum += MDB_Buffer[i].datos;
if (MDB_Buffer[MDB_Buffer_Count-1].datos == (sum&0xFF))
return 1;
else
return 0;
}
void MDB_read(){
MDB_getByte(&MDB_Buffer[MDB_Buffer_Count]);
MDB_Buffer_Count++;
if(MDB_Buffer_Count == 35)
{ rcvcomplete = 1;
mdboverflow = 1; }
if(MDB_Buffer[MDB_Buffer_Count -1].modo && MDB_CHK())
{rcvcomplete = 1; }
}
int Procesar_Respuesta()
{ byte state = 0;
mdboverflow = 0; rcvcomplete = 0;
while (!rcvcomplete)
{ MDB_read(); }
if( rcvcomplete && (!mdboverflow) )
{
if(MDB_Buffer_Count>0)
{
if(MDB_Buffer_Count>1)
{ //Serial.print("MDB BUF: "); Serial.println(MDB_Buffer_Count);
MDB_write(0x00);
if(MDB_Buffer[0].datos == 0 )
state = 0;
else
state = 1;
}
else {
if(MDB_Buffer_Count == 1){ } }
}
} return state;
}