Como um exercício, vamos criar duas threads adicionais no nosso programa, uma para piscar o LED e outra para ler o sensor inercial. O nosso programa principal receberá pela serial o caracter cujo código será piscado no LED e envirá pela serial os valores lidos do sensor.
Vamos começar vendo como criar uma thread, que é uma rotina que roda em paralelo ("simultaneamente") ao nosso programa principal:
#include <mbed.h> using namespace rtos; Thread thLed; void setup() { Serial.begin (115200); thLed.start(piscaLed); } void loop() { // put your main code here, to run repeatedly: } void piscaLed() { pinMode (LED_BUILTIN, OUTPUT); for (;;) { digitalWrite (LED_BUILTIN, HIGH); delay (300); digitalWrite (LED_BUILTIN, LOW); delay (300); } }
O passo seguinte é fazer a comunicação entre o programa principal e a thread. Para isto vamos usar uma queue (fila):
#include <mbed.h> using namespace rtos; Thread thLed; Queue<int, 20> filaLed; void setup() { Serial.begin (115200); thLed.start(piscaLed); } void loop() { if (Serial.available() > 0) { int c = Serial.read(); filaLed.put((int *) c); } } void piscaLed() { pinMode (LED_BUILTIN, OUTPUT); for (;;) { // Aguarda ter algo na fila osEvent evt = filaLed.get(); if (evt.status == osEventMessage) { // Pisca o valor binário do caracter retirado da fila int c = (int) evt.value.p; for (int i = 0; i < 8; i++) { digitalWrite (LED_BUILTIN, (c & 0x80)? HIGH : LOW); delay (300); digitalWrite (LED_BUILTIN, LOW); delay (200); c = c << 1; } delay (1000); } } }
Aqui o código ficou um pouco mais complicado. Indo por partes:
- Queue<int, 20> indica que estamos criando uma fila com 20 inteiros.
- filaLed.put((int *) c) coloca 'c' na fila. O cast (int *) é necessário porque put espera um ponteiro e estamos colocando um inteiro.
- filaLed.get() aguarda ter algo na fila e o devolve dentro de um objeto osEvent
Estamos usando aqui apenas o básico do objeto Queue, Ele suporta prioridades e timeouts para aplicações mais sofisticadas.
Agora já podemos montar o código completo, usando a classe MemoryPool do Mbed para gerencias as áreas onde colocaremos as leituras:
#include <mbed.h> #include <Arduino_LSM9DS1.h> using namespace rtos; typedef struct { float x, y, z; } LEITURA; MemoryPool<LEITURA, 5> mpoolLeit; Thread thLed; Thread thIMU; Queue<int, 20> filaLed; Queue<LEITURA, 5> filaIMU; void setup() { Serial.begin (115200); if (!IMU.begin()) { Serial.println ("Erro ao iniciar IMU"); } thLed.start(piscaLed); thIMU.start(leIMU); } void loop() { if (Serial.available() > 0) { int c = Serial.read(); filaLed.put((int *) c); } osEvent evt = filaIMU.get(0); if (evt.status == osEventMessage) { LEITURA *pLeitura = (LEITURA *) evt.value.p; Serial.print ("Leitura bussola: X="); Serial.print (pLeitura->x); Serial.print (" Y="); Serial.print (pLeitura->y); Serial.print (" Z="); Serial.println (pLeitura->z); mpoolLeit.free (pLeitura); } } void piscaLed() { pinMode (LED_BUILTIN, OUTPUT); for (;;) { // Aguarda ter algo na fila osEvent evt = filaLed.get(); if (evt.status == osEventMessage) { // Pisca o valor binário do caracter retirado da fila int c = (int) evt.value.p; for (int i = 0; i < 8; i++) { digitalWrite (LED_BUILTIN, (c & 0x80)? HIGH : LOW); delay (300); digitalWrite (LED_BUILTIN, LOW); delay (200); c = c << 1; } delay (1000); } } } void leIMU() { for (;;) { if (IMU.magneticFieldAvailable()) { LEITURA *pLeitura = mpoolLeit.alloc(); IMU.readMagneticField(pLeitura->x, pLeitura->y, pLeitura->z); filaIMU.put(pLeitura); delay (1000); } delay (100); } }
Nenhum comentário:
Postar um comentário