// 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};
// Variáveis para controle de tempo:
unsigned long tempoAnterior = 0;
const unsigned long intervalo = 5000; // Atualiza a cada 5 segundos
// 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 (esquerda)
{0b00001, 0b00001, 0b10101, 0b01001, 0b10101, 0b00001, 0b11111, 0b00000}, // Ocupada D (direita)
{0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111, 0b00000}, // Livre E (esquerda)
{0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b11111, 0b00000} // Livre D (direita)
};
// Variáveis que indicam o número de vagas livres e ocupadas, respectivamente:
int somaVagasLivres = 0;
int somaVagasOcupadas = 0;
// Distância:
const long distancia = 0;
void setup() {
// Inicia o monitor serial (opcional):
Serial.begin(115200);
// Configuração de pinos:
for (int i = 0; i < 4; i++) {
pinMode(ledVerde[i], OUTPUT);
pinMode(ledVermelho[i], OUTPUT);
pinMode(trigPins[i], OUTPUT);
pinMode(echoPins[i], INPUT);
}
// 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]);
}
}
void loop() {
//Reseta os valores das quantidades de vagas livres e ocupadas:
somaVagasLivres = 0;
somaVagasOcupadas = 0;
if (millis() - tempoAnterior >= intervalo) {
tempoAnterior = millis(); // Atualiza o tempo
// Medindo e calculando média das distâncias
for (int i = 0; i < 4; i ++) {
float soma = 0;
for (int j = 0; j < 10; j ++) {
soma += medirDistancia(trigPins[i], echoPins[i]); // incrementa valores da distância 10 vezes
if(distancia > 180) {
digitalWrite(ledVerde[i], HIGH);
digitalWrite(ledVermelho[i], LOW);
}
delay(50);
}
/* Média das leituras durante um período de 500 milisegundos
(para que movimentações quaisquer nas vagas não indiquem falsamente que estão ocupadas): */
MediaDist[i] = soma / 10;
}
// Exibe os resultados das distâncias das 4 vagas no Serial Monitor (opcional, para melhorar visualização e correção):
for (int i = 0; i < 4; i++) {
Serial.print("Distância Sensor ");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MediaDist[i]);
Serial.println(" cm");
}
// Atualiza LCD:
lcd.clear();
for (int i = 0; i < 4; i++) {
lcd.setCursor(i, 0);
lcd.write(byte(i)); // Ícones de vagas (estes podendo ser 1, 2, 3 ou 4)
// Se vaga ocupada:
if (MediaDist[i] >= 0 && MediaDist[i] <= 180) {
lcd.setCursor(i, 1);
/* Irá mostrar no display o caractere "ocupada E" se a vaga 1 estiver ocupada;
se a vaga 4 estiver ocupada, mostra o caractere "Ocupada D"; caso as vagas 2 e/ou
3 estejam ocupadas será exibido um "x" no LCD. Isto ocorre porque os caracteres
das pontas são personalizados e diferentes do caractere "x" nos "meios": */
lcd.write(i == 0 ? byte(4) : i == 3 ? byte(5) : 'x'); // Ícones no display
digitalWrite(ledVerde[i], LOW);
digitalWrite(ledVermelho[i], HIGH);
somaVagasOcupadas++;
}
// Se vaga livre:
else {
lcd.setCursor(i, 1);
/* Irá mostrar no display o caractere "livre E" se a vaga 1 estiver livre;
se a vaga 4 estiver livre, mostra o caractere "livre D"; caso as vagas 2 e/ou
3 estejam ocupadas será exibido um "_" no LCD: */
lcd.write(i == 0 ? byte(6) : i == 3 ? byte(7) : '_'); // Ícones
digitalWrite(ledVerde[i], HIGH);
digitalWrite(ledVermelho[i], LOW);
somaVagasLivres++;
}
}
// Exibe total de vagas no LCD:
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);
}
}
// Função para medir distância lida no 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;
}