// Exercício 5
// Rodrigo Francisco Pettinati Mikaro
/* Descrição do Circuito:
Um estacionamento com 4 vagas. Cada uma das vagas possui um sensor
e dois LEDs: um verde, indicando vaga livre e um vermelho indicando
vaga ocupada. No LCD, é mostrada a quantidade de vagas disponíveis
e ocupadas com um desenho especificando quais vagas estão ou não.
Após 5 segundos do carro ocupar a vaga, esta deve indicar que está
ocupada. Quando o carro sair, ela deve indicar desocupada imediatamente.
*/
/*Nota: no display, o caractere "x" não pôde ser "enquadrado", pois
o número máximo de caracteres personalizados é 8. Por isso, para se
enquadrar o "vazio", foi utilizado o caractere já existente "_".
*/
// Declaração da Biblioteca LCD e da comunicação I2C:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
// Endereço do Display LCD:
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Definição dos pinos dos sensores e LEDs usando arrays:
const int trigPins[4] = {13, 9, 5, 3};
const int echoPins[4] = {12, 8, 4, 2};
const int ledVerde[4] = {10, 6, A1, A3};
const int ledVermelho[4] = {11, 7, A0, A2};
// Variáveis para leitura das distâncias:
float MediaDist[4] = {0, 0, 0, 0};
unsigned long tempoOcupado[4] = {0, 0, 0, 0}; // Guarda o tempo de ocupação
bool vagaOcupada[4] = {false, false, false, false}; // Estado da vaga
// Variáveis para controle de tempo:
const unsigned long intervalo = 5000; // 5 segundos para confirmar ocupação
// Definição de caracteres personalizados:
byte caracteres[8][8] = {
{0b11111, 0b10000, 0b10010, 0b10110, 0b10010, 0b10010, 0b10111, 0b10000}, // 1
{0b11111, 0b00000, 0b00100, 0b01010, 0b00010, 0b00100, 0b01110, 0b00000}, // 2
{0b11111, 0b00000, 0b01110, 0b00010, 0b00110, 0b00010, 0b01110, 0b00000}, // 3
{0b11111, 0b00001, 0b10101, 0b10101, 0b11101, 0b00101, 0b00101, 0b00001}, // 4
{0b10000, 0b10000, 0b10101, 0b10010, 0b10101, 0b10000, 0b11111, 0b00000}, // Ocupada E
{0b00001, 0b00001, 0b10101, 0b01001, 0b10101, 0b00001, 0b11111, 0b00000}, // Ocupada D
{0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111, 0b00000}, // Livre E
{0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b11111, 0b00000} // Livre D
};
void setup() {
// Inicia o monitor serial (opcional):
Serial.begin(115200);
// Inicialização do LCD:
lcd.init();
lcd.setBacklight(HIGH);
// Carregamento dos caracteres personalizados no LCD:
for (int i = 0; i < 8; i++) {
lcd.createChar(i, caracteres[i]);
}
// Configuração dos pinos:
for (int i = 0; i < 4; i++) {
pinMode(ledVerde[i], OUTPUT);
pinMode(ledVermelho[i], OUTPUT);
pinMode(trigPins[i], OUTPUT);
pinMode(echoPins[i], INPUT);
}
}
void loop() {
//Reseta os valores das quantidades de vagas livres e ocupadas:
int somaVagasLivres = 0;
int somaVagasOcupadas = 0;
// Medindo e calculando média das distâncias:
for (int i = 0; i < 4; i++) {
float distancia = medirDistancia(trigPins[i], echoPins[i]);
// Se detectar carro:
if (distancia >= 0 && distancia <= 180) {
if (!vagaOcupada[i]) {
if (tempoOcupado[i] == 0) {
tempoOcupado[i] = millis(); // Inicia contagem
}
else if (millis() - tempoOcupado[i] >= intervalo) {
vagaOcupada[i] = true; // Confirma ocupação após 5s
}
}
}
// Se a vaga estiver livre:
else {
vagaOcupada[i] = false;
tempoOcupado[i] = 0; // Reseta contagem
}
// Atualiza LEDs:
if (vagaOcupada[i]) {
digitalWrite(ledVerde[i], LOW);
digitalWrite(ledVermelho[i], HIGH);
somaVagasOcupadas++;
}
else {
digitalWrite(ledVerde[i], HIGH);
digitalWrite(ledVermelho[i], LOW);
somaVagasLivres++;
}
}
// Atualiza LCD:
lcd.clear();
// Exibe números das vagas:
for (int i = 0; i < 4; i++) {
lcd.setCursor(i, 0);
lcd.write(byte(i));
lcd.setCursor(i, 1);
// Se a vaga estiver ocupada:
if (vagaOcupada[i]) {
lcd.write(i == 0 ? byte(4) : i == 3 ? byte(5) : 'x'); // Ocupado
}
// Se a vaga estiver livre:
else {
lcd.write(i == 0 ? byte(6) : i == 3 ? byte(7) : '_'); // Livre
}
}
// Exibe contagem de vagas:
lcd.setCursor(7, 0);
lcd.print("LIVRES: ");
lcd.setCursor(15, 0);
lcd.print(somaVagasLivres);
lcd.setCursor(5, 1);
lcd.print("OCUPADAS: ");
lcd.setCursor(15, 1);
lcd.print(somaVagasOcupadas);
// Pequeno atraso para evitar atualização muito rápida
delay(500);
}
// Função para medir a distância do sensor ultrassônico:
float medirDistancia(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duracao = pulseIn(echoPin, HIGH);
long distancia = duracao * 0.034 / 2; // Conversão para cm
return distancia;
}