#include <Wire.h>
#include <LiquidCrystal_I2C.h> //Biblioteca LCD
// Criação do objeto do display LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ------------------------- Definição dos pinos -------------------------
#define CAR_VERDE 17 // LED verde dos carros
#define CAR_AMARELO 18 // LED amarelo dos carros
#define CAR_VERMELHO 19 // LED vermelho dos carros
#define PED_VERDE 5 // LED verde pedestre
#define PED_VERMELHO 4 // LED vermelho pedestre
#define BOTAO 16 // Botão pedestre
#define BUZZER 15 // Buzzer
#define LDR 33 // Sensor de luminosidade
#define POT 26 // Potenciômetro para ajuste de tempo
#define TRIGGER 14 // Sensor ultrassônico trigger
#define ECHO 27 // Sensor ultrassônico echo
#define LEDBR 25 // LED branco para sinalizar multa
// ------------------------- Variáveis de tempo -------------------------
unsigned long T_AMARELO = 30000; // Tempo do sinal amarelo
unsigned long T_VERMELHO; // Tempo do sinal vermelho (modo 3)
unsigned long T_Atual; // Tempo atual do loop
unsigned long Tempo = 0; // Variável auxiliar de tempo
unsigned long tchico = 0; // Auxiliar para atualização do LCD
// ------------------------- Controle de modos -------------------------
int modo = 0; // Modos do semáforo: 0=default, 1=aguarde, 2=amarelo, 3=pedestre
int i = 0; // Contagem de acionamentos do botão
// ------------------------- Modo 3 - Pedestres -------------------------
unsigned long T_Modo_3 = 40000; // Tempo fixo para atravessar
unsigned long iniciomodo3 = 0; // Momento em que o modo 3 inicia
unsigned long ultimosom = 0; // Auxiliar para beeps progressivos
bool buzzerligado = false; // Estado do buzzer
// ------------------------- Flags de inicialização -------------------------
bool iniciou0 = false; // Flag para iniciar modo 0
bool iniciou1 = false; // Flag para iniciar modo 2
bool iniciou2 = false; // Flag para iniciar modo 3
// ------------------------- Lógica de multas -------------------------
int CONTADOR_MULTAS = 0; // Contador de multas
bool MULTA = false; // Flag indicando se já multou
bool FLASH_ATIVO = false; // Flag do flash do LED branco
const unsigned long DURACAO_FLASH = 500; // Tempo de flash em ms
unsigned long TEMPO_FLASH = 0; // Marca o momento do flash
unsigned long T_Resto; // Tempo restante do modo
// ------------------------- Controle de contagem regressiva -------------------------
//int T_Resto = 0; // Segundos restantes para pedestres
unsigned long utss = 0; // Última atualização do contador de segundos
void setup() {
Serial.begin(115200);
//------------------------- Configuração de pinos -------------------------
pinMode(CAR_VERMELHO, OUTPUT);
pinMode(CAR_AMARELO, OUTPUT);
pinMode(CAR_VERDE, OUTPUT);
pinMode(PED_VERDE, OUTPUT);
pinMode(PED_VERMELHO, OUTPUT);
pinMode(BOTAO, INPUT_PULLUP); // Botão com pull-up interno
pinMode(BUZZER, OUTPUT);
pinMode(LDR, INPUT);
pinMode(TRIGGER, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(LEDBR, OUTPUT);
randomSeed(analogRead(LDR)); // Usa Variacoes de luminosidade do ldr para gerar numeros aleatorios
//------------------------- Inicialização do LCD -------------------------
lcd.init(); //Inicia LCD
lcd.backlight(); // Liga luz LCD
}
void loop() {
float d; // Distância do sensor ultrassônico
float tchegada; // Tempo do pulso do sensor ultrassônico
static unsigned long tpulso = 0; // Auxiliar para pulso do sensor
static int passoupelosinal = 0; // Flag para detectar passagem do pedestre
static int passoupelosinall = 0; // Contagem auxiliar para evitar loop
delay(10); // Pequeno delay para estabilidade
//------------------------- Leitura do LDR -------------------------
int leituraLDR = analogRead(LDR);
int brilho = map(leituraLDR, 32, 4095, 50, 255); // Ajusta brilho dos LEDs
// -------------------- MODO 0: Default --------------------
if (modo == 0) {
analogWrite(CAR_VERDE, brilho); // Carros verdes
analogWrite(CAR_AMARELO, 0); // Carros amarelos desligados
analogWrite(CAR_VERMELHO, 0); // Carros vermelhos desligados
analogWrite(PED_VERDE, 0); // Pedestres verdes desligados
analogWrite(PED_VERMELHO, brilho); // Pedestres vermelhos ligados
analogWrite(LEDBR, 0); // LED branco desligado
// Mensagem inicial no LCD
if (!iniciou0) {
lcd.clear(); //Limpa LCD
lcd.setCursor(0, 0); //Inicia cursor
lcd.print("Aperte o botao"); //Imprime mensagem
lcd.setCursor(0, 1); //Muda cursor
lcd.print("para atravessar"); //Imprime mensagem
iniciou0 = true; //Marca modo 0 iniciado
}
//-------------------- Leitura do botão --------------------
if (!digitalRead(BOTAO)) { // Se botão pressionado
unsigned long baseTempo = map(analogRead(POT), 32, 4095, 10000, 60000);
int variacao = random(-5000, 5000); // Pequena variação aleatória
T_AMARELO = constrain(baseTempo + variacao, 10000, 60000); // Converte leitura do potenciômetro para tempo entre 10-60 segundos
iniciou0 = false; // Reseta estado do modo 0
T_Atual = millis(); // Armazena tempo tual
Tempo = T_Atual; // Inicia contagem de tempo
tone(BUZZER, 800, 100); // Beep curto
i++; // Contador de cionamentos do botão
Serial.println("Botao acionado " + String(i) + " vezes"); //Imprime quantas vezes o botão foi acionado
modo = 1; // Avança para modo 1
lcd.clear(); // Limpa LCD
lcd.setCursor(0, 0); //Inicia cursor
lcd.print("Aguarde"); //Imprime mensagem
}
}
// -------------------- MODO 1: Aguarde --------------------
else if (modo == 1) {
analogWrite(CAR_VERDE, brilho); //Carros verde
analogWrite(CAR_AMARELO, 0);
analogWrite(CAR_VERMELHO, 0);
analogWrite(PED_VERDE, 0);
analogWrite(PED_VERMELHO, brilho); //Pedestres vermelho
T_Atual = millis(); //Atualiza tempo atual
// Atualiza LCD a cada segundo
if (millis() - tchico > 1000) {
tchico = millis(); //Reseta temporizador do LCD
lcd.setCursor(0, 1); //Muda cursor
lcd.print(String((T_AMARELO - (millis() - Tempo)) / 1000) + "s "); //Imprime contagem regressiva
}
if (T_Atual - Tempo > T_AMARELO) { //Verifica se o tempo acabou
Tempo = T_Atual; //Reseta temporizador
modo = 2; // Avança para modo 2
}
}
// -------------------- MODO 2: Amarelo --------------------
else if (modo == 2) {
//Muda o sinal. Carros no amarelo
analogWrite(CAR_VERDE, 0);
analogWrite(CAR_AMARELO, brilho); //Carros amarelo
analogWrite(CAR_VERMELHO, 0);
analogWrite(PED_VERDE, 0);
analogWrite(PED_VERMELHO, brilho); //Pedestres vermelho
if (!iniciou1) { // Inicia modo 2
iniciou1 = true; //Marca como inicializado
T_Atual = millis(); // Armazena tmepo de inicio no tempo atual
}
// Espera 2 segundos antes de liberar pedestres
if (millis() - T_Atual >= 2000) { // Aguarda 2 segundos no sinal amarelo
Tempo = T_Atual; // Reseta temporizador
iniciomodo3 = T_Atual; // Marca início do modo 3
ultimosom = T_Atual; // Inicia tmeporizador do buzzer
buzzerligado = false; // Sereta estado do buzzer
iniciou1 = false; //Reseta estado do flag do modo 2
modo = 3; // Avança para modo 3
}
}
// -------------------- MODO 3: Pedestres --------------------
else if (modo == 3) {
//Mucança nos sinais. Carros vai para vermelho. Pedestres vai para verde
analogWrite(CAR_VERDE, 0);
analogWrite(CAR_AMARELO, 0);
analogWrite(CAR_VERMELHO, brilho); // Carros vermelho
analogWrite(PED_VERDE, brilho); // Pedestres verde
analogWrite(PED_VERMELHO, 0);
T_Atual = millis(); //Atualiza tempo atual
//-------------------- Inicialização do modo 3 --------------------
if (!iniciou2) { //Executa ao entrar no modo 3
iniciou2 = true; // Marca como inicializado
lcd.clear(); //Limpa LCD
lcd.setCursor(0, 0); //Iniica cursor
lcd.print("Avance"); //Imprime mensagem
T_VERMELHO = map(analogRead(POT), 32, 4095, 40000, 10000); // Definição do tempo do sinal vermelho
int variacao = random(-5000, 5000); //Variação aleatoria
T_VERMELHO = constrain(T_VERMELHO + variacao, 10000, 40000); //Limita sempre entre 10-40 s
T_Resto = T_VERMELHO / 1000; //Converte para segundos
utss = T_Atual; //Atualiza temporizador do LCD
}
//-------------------- Atualização do LCD --------------------
if (T_Atual - utss >= 1000) { //Atualiza a cada 1 segundo
utss = T_Atual; //Reseta temporizador
lcd.clear(); //Limpa LCD
lcd.setCursor(0, 0); //Inicia cursor
lcd.print("Avance"); //Imprime mensagem
if (T_Resto > 0) T_Resto--; //Decremento do tempo
lcd.setCursor(0, 1); //Muda cursor
lcd.print(String(T_Resto) + "s Multas:" + String(CONTADOR_MULTAS)); //Imprime contagem regressiva e contador de multas
}
//-------------------- Sensor Ultrassônico --------------------
digitalWrite(TRIGGER, 1); //Pulso do sensor
if (micros() - tpulso >= 10) { //Aguarda 10 microssegundos
tpulso = micros(); //Atualiza tempo do pulso
digitalWrite(TRIGGER, 0); //Desliga trigger
}
tchegada = pulseIn(ECHO, 1); //Mede tempo do eo
d = (340.0 / 2) * (tchegada / 1000000.0); //Calcula a distancia em metros
//-------------------- Lógica de multas --------------------
if (passoupelosinal == 0 && (d < 2.01)) { //Se o carro entrar na distancia determinada
passoupelosinal = 1; // Marca que ele entrou
if (!FLASH_ATIVO && !MULTA) { // Flash ativa e multas
CONTADOR_MULTAS++; //Soma contador de multas
MULTA = true; //Marca multas aplicada
analogWrite(LEDBR, brilho); //Acende led branco
FLASH_ATIVO = true; //Tiva flash
TEMPO_FLASH = millis(); //Inicia temporizador do flash
Serial.println("Total de multas: " + String(CONTADOR_MULTAS)); //Imprime total de multas
}
passoupelosinall++; //Debug do contador de passagens de carros
} else if (passoupelosinal == 1 && d > 2.1) { //Se carro saiu da distancia
passoupelosinal = 0; //Reseta estado da flag
MULTA = false; //Libera para nova multas
}
if (FLASH_ATIVO && (millis() - TEMPO_FLASH >= DURACAO_FLASH)) { //Conrole de duraçãodo flash
analogWrite(LEDBR, 0); //Desliga o led
FLASH_ATIVO = false; //Desativa flash
}
//-------------------- Beeps progressivos --------------------
unsigned long T_Total = T_Atual - iniciomodo3; //Tempo total no modo 3
unsigned long intersom = map(T_Total, 0, T_VERMELHO, 800, 150); //Intervalo entre os beeps diminui com o tempo. 800s (longo), 150s (curto)
if (!buzzerligado && T_Atual - ultimosom >= intersom) { //Momento de buzzer liga
tone(BUZZER, 1000); //Beep curto
buzzerligado = true; //Marca como ligado
ultimosom = T_Atual; //Atualiza do tempo do ultimo beep
}
if (buzzerligado && T_Atual - ultimosom >= 10) { //Desliga depois de 10ms
noTone(BUZZER); //Para o buzzer
buzzerligado = false; //Marca estado do buzzer como desligado
}
//-------------------- Final do modo 3 --------------------
if (T_Total >= T_VERMELHO) { //Verifica se o tempo acabou
iniciou2 = false; //Reseta flag do modo 3
modo = 0; // Retorna para modo 0 (inicial)
noTone(BUZZER); //Garante que o buzzer esteja desligado
buzzerligado = false; // reseta o estado do buzzer
analogWrite(LEDBR, 0); // Desliga LED branco
}
}
}