#include <Arduino_FreeRTOS.h>
// ------------------------------------------------------------------------------------
// Definição de pinos
// ------------------------------------------------------------------------------------
// PIR de peão (digital)
#define PIR_PEDESTRE_DIR 2 // pir2
#define PIR_PEDESTRE_ESQ 3 // pir1
// PIR de carro (analógico)
#define PIR_VEICULO_DIR A0 // pir4
#define PIR_VEICULO_ESQ A1 // pir3
// Buzzer
#define BUZZER_PIN 4
// LEDs RGB - cada "faixa" (grupo) controla 2 LEDs no circuito, mas aqui tratamos como 1 faixa
// Faixa 1
#define LED1_R 13
#define LED1_G 12
#define LED1_B 11
// Faixa 2
#define LED2_R 10
#define LED2_G 9
#define LED2_B 8
// Faixa 3
#define LED3_R 7
#define LED3_G 6
#define LED3_B 5
// ------------------------------------------------------------------------------------
// Variáveis globais de estado (compartilhadas entre as tasks)
// Utilizamos 'volatile' para que o compilador não otimize de forma indevida
// ------------------------------------------------------------------------------------
volatile bool carroDir = false;
volatile bool carroEsq = false;
volatile bool peaoDir = false;
volatile bool peaoEsq = false;
// ------------------------------------------------------------------------------------
// Protótipos de funções auxiliares para controle de LEDs e buzzer
// ------------------------------------------------------------------------------------
void setFaixaColor(int faixa, int rValue, int gValue, int bValue);
void setAllFaixasColor(int rValue, int gValue, int bValue);
void chaseEffect();
void blinkAllFaixas(int rValue, int gValue, int bValue, int tempoMS);
void buzzerAlerta(bool ligar);
// ------------------------------------------------------------------------------------
// Tarefas (FreeRTOS) - Protótipos
// ------------------------------------------------------------------------------------
void taskLerSensores(void *pvParameters);
void taskControlaPassadeira(void *pvParameters);
// ------------------------------------------------------------------------------------
// Setup
// ------------------------------------------------------------------------------------
void setup() {
// Pinos de entrada - PIR peões
pinMode(PIR_PEDESTRE_DIR, INPUT);
pinMode(PIR_PEDESTRE_ESQ, INPUT);
// Pinos de entrada - PIR carros
pinMode(PIR_VEICULO_DIR, INPUT);
pinMode(PIR_VEICULO_ESQ, INPUT);
// Pino do buzzer
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
// Pinos de saída - LEDs RGB
pinMode(LED1_R, OUTPUT); pinMode(LED1_G, OUTPUT); pinMode(LED1_B, OUTPUT);
pinMode(LED2_R, OUTPUT); pinMode(LED2_G, OUTPUT); pinMode(LED2_B, OUTPUT);
pinMode(LED3_R, OUTPUT); pinMode(LED3_G, OUTPUT); pinMode(LED3_B, OUTPUT);
// Inicializa todos os LEDs apagados
setAllFaixasColor(0, 0, 0);
// Criação das tasks do FreeRTOS
xTaskCreate(
taskLerSensores, // Função que implementa a task
"LerSensores", // Nome (para debug)
128, // Tamanho da stack
NULL, // Parâmetro para a função (não usado aqui)
1, // Prioridade da task
NULL // Handle da task (não precisamos usar)
);
xTaskCreate(
taskControlaPassadeira,
"ControlaPass",
256, // um pouco maior porque controlamos LEDs
NULL,
2, // prioridade maior que a de lerSensores
NULL
);
// Inicia o agendador do FreeRTOS
vTaskStartScheduler();
}
// ------------------------------------------------------------------------------------
// Loop vazio: com FreeRTOS, não usamos mais o loop() para lógica principal
// ------------------------------------------------------------------------------------
void loop() {
// Não precisamos de nada aqui; o FreeRTOS cuida das tasks
}
// ------------------------------------------------------------------------------------
// Task 1: Ler sensoriamento de peões e carros
// - Leitura dos pinos digitais para peões
// - Leitura dos pinos analógicos para carros
// - Armazena em variáveis globais (volatile)
// ------------------------------------------------------------------------------------
void taskLerSensores(void *pvParameters) {
(void) pvParameters;
const int limiarCarro = 400; // Ajustar se necessário
for (;;) {
// Leitura PIR peões (digital)
peaoDir = (digitalRead(PIR_PEDESTRE_DIR) == HIGH);
peaoEsq = (digitalRead(PIR_PEDESTRE_ESQ) == HIGH);
// Leitura PIR carros (analógico)
int leituraCarroDir = analogRead(PIR_VEICULO_DIR);
int leituraCarroEsq = analogRead(PIR_VEICULO_ESQ);
carroDir = (leituraCarroDir > limiarCarro);
carroEsq = (leituraCarroEsq > limiarCarro);
// Task delay (para não ler o tempo todo sem pausa)
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// ------------------------------------------------------------------------------------
// Task 2: Controla a lógica da passadeira
// - Decide qual efeito de LEDs e se buzzer deve tocar
// ------------------------------------------------------------------------------------
void taskControlaPassadeira(void *pvParameters) {
(void) pvParameters;
for (;;) {
// Verifica estados
bool temCarro = (carroDir || carroEsq);
bool temPeao = (peaoDir || peaoEsq );
if (!temCarro && !temPeao) {
// 1) Sem carro e sem peão -> efeito de perseguição lento
chaseEffect();
}
else if (temCarro && !temPeao) {
// 2) Carro se aproxima, mas não há pedestre -> faixa de luzes constante
setAllFaixasColor(255, 180, 0); // Amarelo-alaranjado forte para avisar
buzzerAlerta(false); // sem buzzer
// Segura esse estado por um tempo e then check again
vTaskDelay(pdMS_TO_TICKS(200));
}
else {
// 3) Carro + Peão -> aciona piscada total + buzzer
blinkAllFaixas(255, 0, 0, 300); // Vermelho piscando
buzzerAlerta(true); // Liga buzzer
// Espera um pouco no estado piscando
// (piscadaAllFaixas já tem vTaskDelay interna, mas damos mais um tempo)
vTaskDelay(pdMS_TO_TICKS(200));
// Desliga buzzer para não ficar sempre ligado
buzzerAlerta(false);
}
}
}
// ------------------------------------------------------------------------------------
// Funções Auxiliares
// ------------------------------------------------------------------------------------
// Ajusta cor (R,G,B) de *uma* faixa (1, 2 ou 3)
void setFaixaColor(int faixa, int rValue, int gValue, int bValue) {
switch (faixa) {
case 1:
analogWrite(LED1_R, rValue);
analogWrite(LED1_G, gValue);
analogWrite(LED1_B, bValue);
break;
case 2:
analogWrite(LED2_R, rValue);
analogWrite(LED2_G, gValue);
analogWrite(LED2_B, bValue);
break;
case 3:
analogWrite(LED3_R, rValue);
analogWrite(LED3_G, gValue);
analogWrite(LED3_B, bValue);
break;
}
}
// Ajusta cor (R,G,B) de todas as faixas (3 faixas)
void setAllFaixasColor(int rValue, int gValue, int bValue) {
setFaixaColor(1, rValue, gValue, bValue);
setFaixaColor(2, rValue, gValue, bValue);
setFaixaColor(3, rValue, gValue, bValue);
}
// Efeito perseguição lento (chase) em todas as faixas
// Exemplo simples: acendemos cada faixa numa cor, uma de cada vez, depois apagamos
void chaseEffect() {
// Podemos brincar com cores suaves para não ficar muito forte
// Aqui, acende uma faixa de cada vez em azul-claro, por exemplo
for (int faixa = 1; faixa <= 3; faixa++) {
// Primeiro, apaga tudo
setAllFaixasColor(0, 0, 0);
// Acende a faixa atual
setFaixaColor(faixa, 0, 50, 255); // azul-claro
// Espera um pouco
vTaskDelay(pdMS_TO_TICKS(400));
}
}
// Pisca (liga/desliga) todas as faixas numa cor, pelo tempo indicado
void blinkAllFaixas(int rValue, int gValue, int bValue, int tempoMS) {
// Liga
setAllFaixasColor(rValue, gValue, bValue);
vTaskDelay(pdMS_TO_TICKS(tempoMS));
// Desliga
setAllFaixasColor(0, 0, 0);
vTaskDelay(pdMS_TO_TICKS(tempoMS));
}
// Liga ou desliga o buzzer
void buzzerAlerta(bool ligar) {
if (ligar) {
digitalWrite(BUZZER_PIN, HIGH);
} else {
digitalWrite(BUZZER_PIN, LOW);
}
}