24 dezembro 2013

Display LCD 16x2 Arduino HD44780

Post "light" para (quase) encerrar o ano, vamos mostrar a ligação do LCD 16x2 com backlight azul, que utiliza o chip de controle HD44780.

A ligação é praticamente a mesma do display WH1602A, com a diferença que, no LCD que vamos utilizar agora, os pinos são numerados de 1 a 16 continuamente, e estão no topo do LCD.

Dependendo do modelo, a função dos pinos vem marcada na própria placa :


Pinagem LCD 16 x 2 HD44780
  • Pino 1 - Vss  (Terra - 0v)
  • Pino 2 - Vdd (Vcc - 5v)
  • Pino 3 - V0 - Ajuste de contraste
  • Pino 4 - RS - Register Selec
  • Pino 5 - RW - Read / Write - Leitura / Escrita
  • Pino 6 - E - Enable
  • Pino 7 à 14 - D0, D1, D2, D3, D4, D5, D6, D7 (Dados)
  • Pino 15 - A - Anode Backlight (Anodo luz de fundo)
  • Pino 16 - K - Negativo Backlight

O esquema de ligação do display LCD 16x2 ao Arduino e ao potenciômetro utilizado para ajuste do contraste:

Tabela pinos HD44780 lcd 16x2
  

Ligacao LCD 16x2 HD44780 Arduino Uno

Para finalizar, use este programa para escrever no LCD 16x2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Programa : Teste de Display LCD 16x2 Arduino
// Alteração / revisão : Arduino & Cia  
   
#include <LiquidCrystal.h> //Carrega a biblioteca LiquidCrystal  
   
//Define os pinos que serão utilizados para ligação ao display  
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   
  
void setup() 
{  
 //Define o número de colunas e linhas do LCD:  
 lcd.begin(16, 2);  

 //Envia o texto entre aspas para o LCD :  
 lcd.print("Arduino e Cia");  
}  
  
void loop()  
{  
   //Insira aqui o código para alterar o texto, gerar 
   //efeito "blink" (piscar), etc.  
} 

Um datasheet bem completo sobre o controlador HD44780, utilizado por vários fabricantes de displays, você encontra nesse link.


Motor Shield Arduino e motor DC 12 volts

Veja no blog FILIPEFLOP como utilizar o Motor Shield Arduino L293D para controle de um motor DC 12 volts, como no vídeo abaixo.

Acesse também o artigo Controlando motores DC com o Arduino Motor Shield L293D aqui mesmo no Arduino e Cia  :


06 dezembro 2013

Controle de vagas de estacionamento com o sensor HC-SR04

Esse post 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.

Controle de vagas - Shopping

Claro que a tecnologia utilizada nos shoppings é muito mais complexa, fazendo uso até mesmo de câmeras para controlar as vagas, mas 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, e um display LCD que 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. ;-)

Utilizei um Arduino Mega para poder ligar todos os componentes, já que o LCD utiliza 6 portas, cada HC-SR04 mais 2 portas cada, e os leds bicolores, mais 2 portas cada. 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 16x2 segue o mesmo esquema deste artigo , que já usei em diversos projetos aqui no Arduino e Cia :

Circuito Controle de vagas sensor ultrasonico HC-SR04


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 e 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.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 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();  
}  

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.

Por enquanto é isso. Espero que tenham gostado, e em breve vou publicar um vídeo com este experimento. Até lá !


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.