Configuración del puerto Serial

Puerto Serial Parametro
Windows/Linux COM/ttyUSB
Baudrate 115200
Bit 8
Controlflow none
Stop bit 1

Descripción del protocolo

El protocolo de comunicación entre la BoardDroid y la PC Host con puerto serial se compone de un inicio de mensaje STX y un final de mensaje ETX, así como de una verificación de trama de datos CRC.

El frame de datos para el protocolo de comunicación:

Frame de datos que envia la BoardDroid

Screenshot

Frame de datos que envía la PC (AppLinker)

Screenshot

CRC: Se realiza una verificación del frame de datos con un Checksum, se aplica una operación tipo suma a cada byte segun corresponda.

Pila de comandos

Los comandos disponibles para esta aplicación se muestran a continuación

Screenshot

Descripción de comandos

1. Hardware verification: Este comando se utiliza para verificar si el hardware esta presente en el sistema, permite a la pliación conocer el estatus del hardware (desconectado o conectado)

2. Disable cash and card: Este comando deshabilita todos los dispositivos conectados al bus de datos MDB (Multi Drop Bus).

3. Enable cash: Permite habilitar monedero y/o billetero para aceptar el efectivo depositado por los usuarios.

4. Insert cash: Este comando es envíado por la tarjeta cada vez que detecta efectivo depositado, este datos es envía en una cadena de valores ASCII como se muestra a continuación.

Screenshot

El valor de divide entre 10 para tener el punto decial en las monedas de 50 centavos Mexicanas. La tarjeta siempre mandara el acumulado de lo ingresado en efectivo, cuando de deshabilita los dispositivos se reinicia el contador a $0.00 pesos. El monto máximo que puede aceptar es de $999.50 pesos Mexicanos.

5. Exchange operation: Este comando es enviado por la aplicación de escritorio y permite ordenarle a la tarjeta BoardDroid que le indique a los dispositivos de cobro un monto en efectivo para ser entregado.

Screenshot

6. Card operation: Este comando permite a la aplicación de escritorio enviar la orden de cobro con tarjeta, el dispositivo campatible es Nayax, nayax requiere de un identificaro que puede ser de 0 a 255 y el precio de venta.

Screenshot

Es importante que la aplicación quede en modo escucha (se puede desplegar una pantalla que indique al usuario que inserte su tarjeta), ya que la tarjeta BoardDroid enviara los datos correspondiente siempre y cuando se cobre o se termine el tiempo para cobro asignado por la aplicación Host. Cuando el cobro es lanzado se debe de escuchar la respuesta de la tarjeta electrónica, tal como se muestra a continuación:

Screenshot

Ejemplo de implementación

A continuación se muestra secciones de codigo en lenguage Basic y C#, la finalidad de esta documentación es proporcionar una guia en estos lenguages para poder implementar el protocolo de comunicación,

Screenshot

A continuación se describen algunos metodos y funciones en Visual Basic y C#

VB Setting port

Public WithEvents SerialPort1 As New IO.Ports.SerialPort

SerialPort1.PortName = NamePortArray(PointerNamePort2)
SerialPort1.DataBits = 8
SerialPort1.BaudRate = 115200
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Open()
SendCMDtoVM(CMD_CHECK_BOARD)

C# Setting port

private void InicializarPuerto()
{
    try
    {
        SerialPort1.PortName = "COM3";
        SerialPort1.BaudRate = 115200;
        SerialPort1.DataBits = 8;
        SerialPort1.StopBits = StopBits.One;
        SerialPort1.Parity = Parity.None;
        SerialPort1.ReadTimeout = 1000;
        SerialPort1.Open();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

VB Data recive

Dim RX_DATA As Integer
    RX_DATA = SerialPort1.BytesToRead
    If RX_DATA = 9 Then
        Dim RS232_Buff As Byte() = New Byte(RX_DATA - 1) {}
        SerialPort1.Read(RS232_Buff, 0, RX_DATA)
        Me.Invoke(New DisplayDelegate(AddressOf Processing_RX_Buffer), New Object() {BytetoHex(RS232_Buff)})
    End If
End Sub

C# Data recive

private void SerialPort1_DataReceived(object s, SerialDataReceivedEventArgs e)
{
    byte[] data = new byte[SerialPort1.BytesToRead];
    SerialPort1.Read(data, 0, data.Length);

    if(data.Length == 9)
        Processing_RX_Buffer(BytetoHex(data));
}

VB processing data recive

Private Sub Processing_RX_Buffer(ByVal displayChar As String)

    Dim chars As Char() = displayChar.ToCharArray()
    Dim Buffer_uC_RX((chars.Length / 2) - 1) As String

    Dim OneChar As String
    Dim Cheksum As Integer = 0

    Dim FLagSTX As Boolean = False
    Dim PointCMD As Integer = 0
    Dim PointCHKSUM As Integer = 0

    Dim FLagETX As Boolean = False
    Dim PointETX As Integer = 0

    'AGRUPANDO DATOS 
    For i = 0 To (chars.Length / 2) - 1
        Try
            OneChar = (chars(i * 2) + chars((i * 2) + 1))
            Buffer_uC_RX(i) = OneChar
        Catch ex As Exception
        End Try
    Next

    'Se localiza si existe ETX = F2 y STX = F3
    If Buffer_uC_RX(0) = "F2" Then
        FLagSTX = True
        PointCMD = 1
    End If
    If Buffer_uC_RX(7) = "F3" Then
        FLagETX = True
        PointETX = 7
    End If

    If (FLagSTX = True) And (FLagETX = True) And (Buffer_uC_RX.Length - 1 = 8) Then

        For i = PointCMD To PointETX
            Cheksum += Convert.ToInt32(Buffer_uC_RX(i), 16)
        Next
        Cheksum = Cheksum And 255
        PointCHKSUM = 8

        If Buffer_uC_RX(PointCMD) = "A1" And Convert.ToInt32(Buffer_uC_RX(PointCHKSUM), 16) = Cheksum Then 'Recivir Dinero Depositado
            'BOARDROID
            DataCash.MoneyIn = 0
            DataCash.MoneyIn += (Convert.ToInt32(Buffer_uC_RX(2), 16) - 48) * 1000
            DataCash.MoneyIn += (Convert.ToInt32(Buffer_uC_RX(3), 16) - 48) * 100
            DataCash.MoneyIn += (Convert.ToInt32(Buffer_uC_RX(4), 16) - 48) * 10
            DataCash.MoneyIn += (Convert.ToInt32(Buffer_uC_RX(5), 16) - 48)
            DataCash.MoneyIn /= 10

        ElseIf Buffer_uC_RX(PointCMD) = "A2" And Convert.ToInt32(Buffer_uC_RX(PointCHKSUM), 16) = Cheksum Then 'Recibir Dinero Dispensado
            DataCash.RETUNR10P = (Convert.ToInt32(Buffer_uC_RX(2), 16)) '10
            DataCash.RETUNR5P = (Convert.ToInt32(Buffer_uC_RX(3), 16)) '5
            DataCash.RETUNR2P = (Convert.ToInt32(Buffer_uC_RX(4), 16)) '2
            DataCash.RETUNR1P = (Convert.ToInt32(Buffer_uC_RX(5), 16)) '1
            DataCash.RETUNR50cP = (Convert.ToInt32(Buffer_uC_RX(6), 16)) '.50c

            DataCash.Cambio_No_Dev += DataCash.Money_Out - DataCash.Money_dispensed

        ElseIf Buffer_uC_RX(PointCMD) = "B0" And Convert.ToInt32(Buffer_uC_RX(PointCHKSUM), 16) = Cheksum Then 'uC master Responde OK
            '###SE CONFIRMA CONEXIÓN CON EL HARDWARE###
            TmrPortFound.Stop() 'SE DETIENE TIMER PARA BUSQUEDA DE HARDWARE
            TmrUSBDisct.Start() 'SE INICIA TIMER PARA DETECTAR DESCONEXIONES
        End If

    End If

End Sub

C# processing data recive

private void Processing_RX_Buffer(string displayChar)
{
    char[] chars = displayChar.ToCharArray();
    string[] Buffer_uC_RX = new string[(chars.Length / 2)];
    string OneChar = null;
    int Cheksum = 0;
    bool FLagSTX = false;
    int PointCMD = 0;
    int PointCHKSUM = 0;
    bool FLagETX = false;
    int PointETX = 0;

    for (int i = 0; i <= (chars.Length / 2) - 1; i++)
    {
        try
        {
            OneChar = (chars[i * 2].ToString() + chars[(i * 2) + 1]).ToString();
            Buffer_uC_RX[i] = OneChar;
        }
        catch (Exception)
        {
        }
    }

    for (int i = 0; i <= Buffer_uC_RX.Length - 1; i++)
    {
        if (Buffer_uC_RX[i] == "F2")
        {
            FLagSTX = true;
            PointCMD = i + 1;
        }
        else if (Buffer_uC_RX[i] == "F3")
        {
            FLagETX = true;
            PointETX = i;
            break;
        }
    }

    if (FLagSTX & FLagETX & (Buffer_uC_RX.Length - 1 == 8))
    {
        for (int i = PointCMD; i <= PointETX; i++)
        {
            Cheksum += Convert.ToInt32(Buffer_uC_RX[i], 16);
        }

        Cheksum = Cheksum & 255;
        PointCHKSUM = PointETX + 1;

        /*Recibir Dinero Depositado*/
        if (Buffer_uC_RX[PointCMD] == "A1" & Convert.ToInt32(Buffer_uC_RX[PointCHKSUM], 16) == Cheksum)
        {

            MoneyIn = 0;
            MoneyIn += (Convert.ToInt32(Buffer_uC_RX[2], 16) - 48) * 100;
            MoneyIn += (Convert.ToInt32(Buffer_uC_RX[3], 16) - 48) * 10;
            MoneyIn += (Convert.ToInt32(Buffer_uC_RX[4], 16) - 48) * 1;
            MoneyIn += (Convert.ToInt32(Buffer_uC_RX[5], 16)) * 0.5;

        /*Recibir Dinero Dispensado*/
        }
        else if (Buffer_uC_RX[PointCMD] == "A2" & Convert.ToInt32(Buffer_uC_RX[PointCHKSUM], 16) == Cheksum)
        {
            Money_dispensed = 0;
            Money_dispensed += Convert.ToInt32(Buffer_uC_RX[2], 16) * 10;
            Money_dispensed += Convert.ToInt32(Buffer_uC_RX[3], 16) * 5;
            Money_dispensed += Convert.ToInt32(Buffer_uC_RX[4], 16) * 2;
            Money_dispensed += Convert.ToInt32(Buffer_uC_RX[5], 16) * 1;
            Money_dispensed += Convert.ToInt32(Buffer_uC_RX[6], 16) * 0.5;

            Cambio_No_Dev = Money_Out - Money_dispensed;

            RETUNR10P = (Convert.ToInt32(Buffer_uC_RX[2], 16));//10
            RETUNR5P = (Convert.ToInt32(Buffer_uC_RX[3], 16));//5
            RETUNR2P = (Convert.ToInt32(Buffer_uC_RX[4], 16));//2
            RETUNR1P = (Convert.ToInt32(Buffer_uC_RX[5], 16));//1
            RETUNR50cP = (Convert.ToInt32(Buffer_uC_RX[6], 16));//.50c

        /*uC master Responde OK*/
        }
        else if (Buffer_uC_RX[PointCMD] == "B0" & Convert.ToInt32(Buffer_uC_RX[PointCHKSUM], 16) == Cheksum)
        {
            Status_CMD = true;
        }
    }
    else
    {
        System.Threading.Thread.Sleep(400);
        SerialPort1.Write(CMD_ENQ_CMD, 0, CMD_ENQ_CMD.Length);
    }
}