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