Semana 13

Esta semana continuaremos con el ejercicio de la semana 12 relacionado con máquinas de estado y finalmente realizaremos la evaluación.

Sesión 1

En la semana 12 analizamos y describimos paso a paso el problema. Vamos a retomar desde allí, pero ahora nos concentraremos en el modelo de la solución y luego en la implementación del modelo.

Ejercicio 1: enunciado del problema

En un proyecto interactivo se requiere conectar un controlador a una aplicación interactiva (AI).

Considere:

  • Para simular la AI utilice scriptcommunicator. Esto se requiere porque debemos transmitir bytes NO caracteres ASCII. Ojo!
  • La AI siempre iniciará la comunicación.
  • La secuencia de bytes más grande será de 20 bytes.

PASOS para realizar la comunicación:

  1. La AI inicia una transacción enviando el byte 3E.
  2. El controlador deberá responder con el byte 4A.
  3. La AI no podrá continuar hasta no recibir la respuesta del controlador. Una vez el controlador responda, la AI enviará al controlador un paquete de bytes así:
1
2
3
4
5
 Byte 1 : longitud
 Byte 2 : Dirección
 Byte 3 : Comando
 Byte 4 a n : Datos
 Byte n+1: verificacion
  • El byte de longitud, es el primer byte de la trama e indica cuántos bytes la AI enviará a continuación, es decirm de byte 2 hasta el byte n + 1.
  • La AI calculará el byte de verificación así: Byte1 XOR Byte2 XOR … XOR ByteN.
  • En C la operación XOR se realiza utilizando el operador
1
^
  1. El controlador esperará hasta un 1 segundo a que la trama llegue. Si esta condición

NO se cumple el controlador enviará a la AI el byte 3D. La AI deberá inciar de nuevo la secuencia de comunicación desde el paso 1.

Una vez el controlador tenga la trama completa calculará el byte de cerificación de la misma manera que la AI lo hizo. El resultado debe ser igual al bytes de verificación recibido. Sí el byte de verificación calculado no corresponde al byte de verificación recibido, el controlador enviará el byte 3F y la AI deberá reenviar la trama. Sí hay coincidencia el controlador deberá responder a la AI con el byte 4A y luego enviar la siguiente secuencia de bytes:

1
2
3
4
 Byte 1 : longitud
 Byte 2 : Byte4 recibido
 Byte m : Byten recibido
 Byte m+1 : verificación
  1. Sí la AI recibe correctamente el paquete deberá responder con el byte 4A. El controlador quedará preparado para volver al paso 1, es decir, esperar por una nueva trama. Sí ha pasado 1 segundo y el controlador no recibe el 4A, entonces deberá retransmitir el paquete a la AI. Este comportamiento solo se detendrá hasta que la AI envie el 4A.

Ejercicio 2: modelo de la solución

Un posible modelo de la solución es este:

../_images/SM_model.jpg

Ejercicio 3: implementación

Y una posible implementación del modelo es este otro modelo en C++:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 void setup() {
   Serial.begin(115200);
 }

 void taskCom() {
   enum class state_t {WAIT_INIT, WAIT_PACKET, WAIT_ACK};
   static state_t state = state_t::WAIT_INIT;
   static uint8_t bufferRx[20] = {0};
   static uint8_t dataCounter = 0;
   static uint32_t timerOld;
   static uint8_t bufferTx[20];

   switch (state) {
     case  state_t::WAIT_INIT:
       if (Serial.available()) {
         if (Serial.read() == 0x3E) {
           Serial.write(0x4A);
           dataCounter = 0;
           timerOld = millis();
           state = state_t::WAIT_PACKET;
         }
       }

       break;

     case state_t::WAIT_PACKET:

       if ( (millis() - timerOld) > 1000 ) {
         Serial.write(0x3D);
         state = state_t::WAIT_INIT;
       }
       else if (Serial.available()) {
         uint8_t dataRx = Serial.read();
         if (dataCounter >= 20) {
           Serial.write(0x3F);
           dataCounter = 0;
           timerOld = millis();
           state = state_t::WAIT_PACKET;
         }
         else {
           bufferRx[dataCounter] = dataRx;
           dataCounter++;

           // is the packet completed?
           if (bufferRx[0] == dataCounter - 1) {

             // Check received data
             uint8_t calcChecksum = 0;
             for (uint8_t i = 1; i <= dataCounter - 1; i++) {
               calcChecksum = calcChecksum ^ bufferRx[i - 1];
             }
             if (calcChecksum == bufferRx[dataCounter - 1]) {
               bufferTx[0] = dataCounter - 3; //Length
               calcChecksum = bufferTx[0];

               // Calculate Tx checksum
               for (uint8_t i = 4; i <= dataCounter - 1; i++) {
                 bufferTx[i - 3] = bufferRx[i - 1];
                 calcChecksum = calcChecksum ^ bufferRx[i - 1];
               }

               bufferTx[dataCounter - 3] = calcChecksum;
               Serial.write(0x4A);
               Serial.write(bufferTx, dataCounter - 2);
               timerOld = millis();
               state = state_t::WAIT_ACK;
             }
             else {
               Serial.write(0x3F);
               dataCounter = 0;
               timerOld = millis();
               state = state_t::WAIT_PACKET;
             }
           }
         }
       }

       break;

     case state_t::WAIT_ACK:
       if ( (millis() - timerOld) > 1000 ) {
         timerOld = millis();
         Serial.write(bufferTx, dataCounter - 2);
       } else if (Serial.available()) {
         if (Serial.read() == 0x4A) {
           state = state_t::WAIT_INIT;
         }
       }

       break;
   }
 }


 void loop() {
   taskCom();
 }

Ejercicio 4: un escenario de prueba

Un ejemplo de una escenario de prueba:

../_images/scenario1.jpg

Sesión 2

En este enlace está la evaluación sumativa número 4.