Esse post sobre controle de vagas de estacionamento surgiu da pergunta de um leitor no post Medidor de distância com o sensor ultrassônico HC-SR04. Ele questionou se era possível controlar 2 sensores HC-SR04 usando a biblioteca Ultrasonic.h, uma das mais comuns para quem usa esse tipo de sensor.
Eu tive o mesmo problema ao montar um projeto de faculdade, que consistia em criar um controle de vagas de estacionamento como esses utilizados em shopping center, onde uma luz vermelha indica que a vaga está ocupada, e uma luz verde indica vaga livre.
Embora a tecnologia utilizada nos shoppings seja muito mais complexa, fazendo uso até mesmo de câmeras para controlar as vagas, a ideia é a mesma e não tão difícil de implementar com o Arduino, como vocês poderão ver agora.
Meu (modesto) projeto controla 2 vagas de estacionamento, com os respectivos leds indicando vaga livre/vaga ocupada. Um display LCD mostra as informações sobre as vagas (total livres/ocupadas).
Em primeiro lugar, eu tentei usar a biblioteca Ultrasonic.h, sem sucesso. Talvez alguma alteração na biblioteca ou algum parâmetro que eu desconheço me ajudassem na tarefa, mas optei por procurar outra versão ou alguma outra biblioteca que fosse mais flexível.
Acabei encontrando a biblioteca NewPing, que torna possível o controle de até 15 sensores HC-SR04. Com essa biblioteca, o meu modesto projeto de apenas 2 vagas pode ser expandido. 😉
Circuito controle de estacionamento com Arduino
Utilizei um Arduino Mega para poder ligar todos os componentes, já que o LCD utiliza 6 portas, cada HC-SR04 mais 2 e os leds bicolores, mais 2. Com alguns ajustes, isso pode ser montado tranquilamente com um Arduino Uno.
Para a sinalização das vagas, utilizei no circuito 2 leds bicolores, que podem ser substituídos por 4 leds comuns. A ligação do display 16×2 segue o mesmo esquema deste artigo , que já usei em diversos projetos aqui no Arduino e Cia:
Antes de carregar o programa, não esqueça de baixar a biblioteca NewPing, nesse link. Descompacte e copie a pasta NewPing para dentro da pasta LIBRARIES, dentro da IDE do Arduino.
No início do programa são definidas as variáveis que irão armazenar o número de sensores utilizados (SONAR_NUM), a distância máxima de detecção (MAX_DISTANCE), e o intervalo entre as medições (PING_INTERVAL), que não pode ser muito baixo para que não haja conflito entre os sensores. Para este parâmetro, recomenda-se o valor mínimo de 29 ms.
Para definir os pinos que serão utilizados para cada sensor, utiliza-se o comando NewPing, que tem a seguinte sintaxe :
NewPing(Pino_Trigger, Pino_Echo, Distancia_Maxima)
No meu programa, utilizei apenas 2 sensores, então tenho apenas 2 comandos NewPing. Se você for utilizar mais sensores, inclua mais comandos NewPing. Não se esqueça de setar a variável SONAR_NUM, senão os demais sensores não serão detectados.
O loop do programa efetua a leitura de todos os sensores, e atualiza as variáveis referentes às vagas livres e vagas ocupadas, mostrando as informações no LCD. São utilizadas as subrotinas oneSensorCycle, que efetua a varredura nos sensores, e a echoCheck, que calcula a distância até o objeto detectado.
// Programa : Controle de vagas de estacionamento com o HC-SR04 // Autor : Arduino e Cia //Inicializa as bibliotecas do sensor Ultrasonico e do Display #include <NewPing.h> #include <LiquidCrystal.h> #define SONAR_NUM 2 // Define o numero de sensores #define MAX_DISTANCE 10 // Distancia maxima // Milisegundos de intervalo entre medicoes (29ms e o tempo mínimo para // evitar conflito entre os sensores) #define PING_INTERVAL 33 // Armazena a quantidade de vezes que a medicao deve ocorrer,para cada sensor unsigned long pingTimer[SONAR_NUM]; unsigned int cm[SONAR_NUM]; // Armazena o numero de medicoes uint8_t currentSensor = 0; // Armazena o sensor que esta ativo int Pinoled1Verm = 20; //Pino led1 - Vermelho int Pinoled1Verde = 19; //Pino led1 - Verde int Pinoled2Verm = 18; //Pino led2 - Vermelho int Pinoled2Verde = 17; //Pino led2 - Verde int vagaslivres = 2; //Contador de vagas livres int vagasocupadas = 0; //Contador de vagas ocupadas int sensor1 = 0; //Contador de vagas no sensor1 int sensor2 = 0; //Contador de vagas no sensor2 //Define os pinos que serao ligados ao LCD LiquidCrystal lcd(12, 11, 5, 4, 3, 2); NewPing sonar[SONAR_NUM] = { // Armazena informacoes sobre a pinagem dos sensores // Pino trigger, echo e distancia máxima, para cada sensor NewPing(13, 10, MAX_DISTANCE), NewPing(14, 15, MAX_DISTANCE), }; void setup() { Serial.begin(9600); lcd.begin(16,2); //Inicializa LCD lcd.clear(); //Limpa o LCD pingTimer[0] = millis() + 75; //Primeira medicao começa com 75ms //Define o tempo de inicializacao de cada sensor for (uint8_t i = 1; i < SONAR_NUM; i++) pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; pinMode(Pinoled1Verm, OUTPUT); //Define o Pino vermelho do led1 como saida pinMode(Pinoled1Verde, OUTPUT); //Define o Pino verde do led1 como saida pinMode(Pinoled2Verm, OUTPUT); //Define o Pino vermelho do led2 como saida pinMode(Pinoled2Verde, OUTPUT); //Define o Pino verde do led2 como saida } void loop() { // Loop entre todos os sensores for (uint8_t i = 0; i < SONAR_NUM; i++) { if (millis() >= pingTimer[i]) { //Define o tempo que o proximo sensor sera acionado pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Ciclo do sensor completo if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Reseta o timer antes de ler o proximo sensor sonar[currentSensor].timer_stop(); // Número do sensor sendo acionado currentSensor = i; // Se nao houver eco do sensor, seta a distância como zero cm[currentSensor] = 0; sonar[currentSensor].ping_timer(echoCheck); } } //Calcula a quantidade de vagas disponiveis e ocupadas, e imprime no display vagasocupadas = sensor1 + sensor2; vagaslivres = 2 - vagasocupadas; lcd.setCursor(0,0); lcd.print("Vagas livres = "); lcd.print(vagaslivres); lcd.setCursor(0,1); lcd.print("Vagas ocup. = "); lcd.print(vagasocupadas); } void echoCheck() { //Se receber um sinal (eco), calcula a distancia if (sonar[currentSensor].check_timer()) cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM; } void oneSensorCycle() { // Ciclo de leitura do sensor for (uint8_t i = 0; i < SONAR_NUM; i++) { //Se for detectado objeto entre 0 e 50 cm do sensor1, acende o led1 vermelho if (cm[0] > 1 && cm[0] < 50) { digitalWrite(Pinoled1Verm, 1); digitalWrite(Pinoled1Verde, 0); sensor1 = 1; //Incrementa o número de vagas ocupadas na vaga1 } else //Se não for detectado objeto no sensor 1, mantém o led1 verde aceso { digitalWrite(Pinoled1Verm, 0); digitalWrite(Pinoled1Verde, 1); sensor1 = 0; //Marca a vaga 1 como livre } //Se for detectado objeto entre 0 e 50 cm do sensor2, acende o led2 vermelho if (cm[1] > 1 && cm[1] < 50) { digitalWrite(Pinoled2Verm, 1); digitalWrite(Pinoled2Verde, 0); sensor2 = 1; //Incrementa o número de vagas ocupadas na vaga2 } else //Se não for detectado objeto no sensor 2, mantém o led2 verde aceso { digitalWrite(Pinoled2Verm, 0); digitalWrite(Pinoled2Verde, 1); sensor2 = 0; //Marca a vaga 2 como livre } //Imprime os valores lidos no monitor serial, para fins de acompanhamento Serial.print("Sensor : "); Serial.print(i); Serial.print(" = "); Serial.print(cm[i]); Serial.print(" cm - "); } Serial.println(); }
No vídeo abaixo você confere este projeto em funcionamento.
A biblioteca NewPing tem vários recursos e é relativamente fácil de usar. Consulte a documentação nesse link (em inglês) para obter maiores informações.
Atualizado: Veja também como montar um pequeno sensor de estacionamento/ré usando o sensor HC-SR04 no post Sensor de estacionamento/ré com o Arduino e sensor HC-SR04.