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