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:
- La AI inicia una transacción enviando el byte 3E.
- El controlador deberá responder con el byte 4A.
- 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 | ^
|
- 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
|
- 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 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();
}
|

