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.


25 novembro 2013

Gravador AVR USBasp

Hoje vou falar de uma placa para quem gosta de "escovar bits", como se dizia (não tão) antigamente : o Gravador AVR USBasp.

Este gravador, como o próprio nome diz, é utilizado para programar microcontroladores Atmel AVR. É composto por uma pequena placa, com conector USB, um ATMega8 e mais uns poucos componentes, utilizando um driver genérico para comunicação com o computador. Abaixo, o gravador que eu usei para criar este post :


Gravador AVR USBasp


O gravador USBasp permite a programação de microcontroladores em baixo nível, inclusive mexendo na configuração de fuse bits, lock bits, clock e outras configurações que podem otimizar o desempenho do seu microcontrolador... ou travá-lo. Sim, nos testes eu consegui "travar" uns 2 microcontroladores, mas pretendo recuperá-los em breve. Portanto, tenha cuidado ao mexer nas configurações mais avançadas. :-)

Hoje, vou utilizar o USBasp para programar o ATmega328P. Existem vários tutoriais na internet sobre como utilizar o USBasp para programar esse microcontrolador usando o próprio Arduino Uno, mas o que este tutorial vai mostrar é como programar diretamente o microcontrolador, utilizando um programa gerado na IDE do Arduino.

Como esse tutorial é um pouco extenso, vou separá-lo em seções. Vamos aos passos :
  1. - Instalação do USBasp e seus drivers
  2. - Criação do programa na IDE do Arduino
  3. - Geração do arquivo HEX à partir do programa criado na IDE
  4. - Instalação do programa Extreme Burner AVR para gravação do Microcontrolador
  5. - Ligação do USBAsp no ATMEGA328P
  6. - Gravar no ATMEGA328P o programa HEX gerado no passo 3
  7. - Teste do ATMEGA328P no Arduino Uno
Material a ser utilizado :

  • 3 leds, de preferência de cores diferentes
  • 3 Resistores de 330 ohms ou valores compatíveis com os leds
  • 1 Chip ATmega328P
  • 1 Módulo Gravador AVR USBasp

1 - Instalação do gravador USBasp e seus drivers

O procedimento abaixo foi testado no Windows 7 (64 bits) com Service Pack 1, e também no Windows XP, logo não deve apresentar problemas nas demais versões do Windows. Para Linux e MacOS, não há necessidade de drivers.

O gravador USBasp pode ser conectado diretamente na porta USB do computador, porém, antes de plugar o dispositivo, recomendo o download do driver , nesse link :

http://www.fischl.de/usbasp/usbasp-windriver.2011-05-28.zip

Descompacte o arquivo e será gerada uma pasta chamada usbasp-windriver.2011-05-28. Plugue o USBasp e, após o dispositivo ser detectado pelo Windows, escolha "PROCURAR SOFTWARE DE DRIVER NO COMPUTADOR". Indique a pasta que foi descompactada e o driver será instalado automaticamente. No painel de controle do seu computador, em GERENCIADOR DE DISPOSITIVOS, será mostrado um novo dispositivo chamado USBasp :

Gerenciador de dispositivos - USBasp

2 - Criação do programa na IDE do Arduino

Carregue este programa exemplo no Arduino, que acende e apaga 3 leds em sequencia, com intervalos de 1 segundo :

 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
// Programa : Teste USBasp  
// Autor : Arduino e Cia  
   
int pinoledvermelho =3;  
int pinoledverde = 4;  
int pinoledamarelo = 5;  
   
void setup()  
{  
  pinMode(pinoledvermelho, OUTPUT);  
  pinMode(pinoledverde, OUTPUT);  
  pinMode(pinoledamarelo, OUTPUT);  
}  
   
void loop()  
{  
  digitalWrite(pinoledvermelho, HIGH);  
  delay(1000);  
  digitalWrite(pinoledvermelho, LOW);  
  digitalWrite(pinoledverde, HIGH);  
  delay(1000);  
  digitalWrite(pinoledverde, LOW);  
  digitalWrite(pinoledamarelo, HIGH);  
  delay(1000);  
  digitalWrite(pinoledamarelo, LOW);  
  delay(1000);  
}  

3 - Geração do arquivo HEX à partir do programa criado na IDE

O programa que vamos utilizar para gravar o microcontrolador, o Extreme Burner AVR, não aceita, por exemplo, que um arquivo .INO seja carregado diretamente e  gravado no microcontrolador. Para isso, será necessário gerar um arquivo com extensão HEX (formato hexadecimal). Esse arquivo HEX, por sua vez, será convertido pelo Extreme Burner para 0s e 1s, ou seja, o formato que o microcontrolador "entende".

Por padrão, esse arquivo HEX não é criado quando você compila um programa na IDE, mas com uma pequena mudança na configuração da IDE, podemos gerar esse arquivo no computador.

Entre na IDE do Arduino, em ARQUIVO, depois em PREFERÊNCIAS :

IDE Arduino - Preferencias

 Escolha EXIBIR MODO VERBOSO, conforme destacado :

IDE Arduino - Modo verboso selecionado

Clique em OK e volte para a IDE, compilando o programa. Na parte inferior da janela, serão exibidas várias informações, e nas últimas linhas, o local em que o programa gerou o arquivo HEX. Note que no seu computador esse caminho provavelmente será diferente :

IDE - Compilacao caminho arquivo HEX

Anote/copie essa informação sobre o local do arquivo, pois ela será utilizada daqui a pouco.

4 - Instalação do programa Extreme Burner AVR para gravação do microcontrolador

Essa parte vai dar um pouco mais de trabalho, pois exige a mudança de alguns arquivos de configuração, já que o programa Extreme Burner AVR não possui o microcontrolador ATmega328P em sua lista de chips, e precisaremos inserí-lo manualmente. O programa pode ser baixado nesse link  e tem versões para Windows e Linux. Nos meus testes usei a versão 1.4.2 do programa.

A instalação é bem simples. Execute o arquivo extreme_burner_avr_v1.4.2_setup.exe (ou a versão que você baixou), confira as informações sobre a pasta de instalação e criação de ícones no desktop, e o programa será instalado. Ignore a instalação do driver no final do processo, mantendo o driver do USBasp que você instalou no passo 1.

Depois de instalado, precisamos adicionar o chip ATmega328P à lista de chips suportados pelo Exreme Burner. Para isso, vá até a pasta de instalação, normalmente em C:\Program Files\Extreme Burner -AVR\Data, e abra o arquivo chips.xml. Pode ser usado o próprio notepad para isso, mas certifique-se que você tem as permissões de administrador para abrir o arquivo.

No final do arquivo chips.xml, insira as seguintes linhas :

 <CHIP>
      <NAME>ATmega328P</NAME>
      <FLASH>32768</FLASH>
      <EEPROM>1024</EEPROM>
      <SIG>0x000F951E</SIG>
      <PAGE>128</PAGE>
      <LFUSE layout="2">YES</LFUSE>
      <HFUSE layout="5">YES</HFUSE>
      <EFUSE layout="4">YES</EFUSE>
      <LOCK>YES</LOCK>
      <CALIB>YES</CALIB>
      <PLACEMENT>.\Images\Placements\ZIF_DIP_40.bmp</PLACEMENT>
   </CHIP>

Seu arquivo chips.xml deve ficar mais ou menos assim, com a alteração em destaque :

Chips.xml alterado

Salve o arquivo e abra o Extreme Burner. Na aba CHIP, certifique-se que o controlador ATmega328P aparece no final da lista :

Extreme Burner - Chip ATmega328P adicionado

5 - Ligação do USBasp no microcontrolador

Hora de ligarmos o USBasp no microcontrolador que será programado. Com o USBasp desplugado da USB, efetue as seguintes conexões, seguindo o esquema de ligação :

Ligação USBasp - ATmega328p

Pinagem ATmega328p

Esta configuração está de acordo com a pinagem da placa que estou usando, e o seu módulo pode ser um pouco diferente, mas basta seguir o esquema de ligação acima. Fique atento à tensão de alimentação do microcontrolador (pino VCC do USBasp), que no meu caso é 5v, mas em outros módulos USBasp pode ser configurado para 3.3 ou 5v.

6 - Gravar no ATmega o programa HEX gerado no passo 3

Com o programa HEX gerado, o caminho do arquivo anotado e as ligações ao microcontrolador conferidas e reconferidas, vamos à gravação. Conecte o USBasp na porta USB do seu computador, abra o Extreme Burner, e clique em OPEN, no lado esquerdo da tela....

Extreme Burner - Tela Principal

... e vá até a pasta que você anotou no passo 3, abrindo o arquivo HEX :

Extreme Burner - Selecionando arquivo

Clique em OPEN e, na parte superior da janela do programa, será mostrado o caminho do arquivo HEX que foi carregado :

Extreme Burner - Arquivo HEX carregado

Para finalizar, no menu WRITE, escolha FLASH, e aguarde o final do processo de gravação, que deve mostrar uma tela como essa :

Extreme Burner - Gravação finalizada

7 - Teste do ATmega328P gravado

Para testar o ATmega328P que foi gravado, simplesmente coloque o chip no Arduino UNO, montando o seguinte circuito :

Circuito teste ATmega328P


Desta maneira, o programa que foi criado no passo 1 será executado continuamente. Você não precisa necessariamente de uma placa do Arduino para testar. Também é possível montar o circuito externamente, com alguns componentes como cristal, capacitores e resistores.

Note que o chip que foi gravado contém apenas o programa do Arduino, sem o bootloader. Ou seja, se você tentar programar o Arduino UNO com este chip que foi gravado pelo Extreme Burner, não vai conseguir. Outro detalhe é que você pode apagar e reprogramar o chip quantas vezes quiser, usando as funções do Extreme Burner.

Isso é útil quando você precisa de um chip dedicado para o seu projeto, ou então existe a necessidade de gravar microcontroladores em série. Inclusive o USBasp funciona com uma grande variedade de controladores, como você pode ver na tabela abaixo :

USBasp - Microcontroladores suportados


Este foi apenas um exemplo de utilização, pois como comentei no início do post as opções de programação são as mais variadas possíveis. Reforço que deve-se tomar cuidado nas configurações avançadas, evitando danificar/travar o microcontrolador, ok ?

Até a próxima !

20 novembro 2013

Sensor de som Arduino - Vídeo

Vídeo mostrando o funcionando do Sensor de Som no Arduino, abordado no artigo anterior :


11 novembro 2013

Sensor de som Arduino

O assunto hoje do Arduino e Cia é som. Mais precisamente, Sensor de Som.

Já vimos aqui no site como gerar sons a partir do Arduino usando o comando tone. O que eu vou utilizar hoje é esta pequena mas eficiente placa com microfone embutido, que você encontra na FILIPEFLOP, o Sensor de Som Arduino. Com ela, vou mostrar como detectar o som ambiente e como tratar o sinal gerado por esse módulo.

Esta placa, além do microfone, tem um pequeno amplificador embutido (o circuito integrado LM386), pois apenas o microfone não seria capaz de enviar os dados para o Arduino. O esquema de conexão é bem enxuto, composto por apenas 3 pinos : Vcc, GND e S (sinal). No meio da placa, há um potenciômetro para ajuste da sensibilidade.

Sensor de Som Arduino

A placa trabalha com tensão de 5v, e o pino de sinal deve ser ligado de preferência à uma porta analógica do Arduino, já que o sinal gerado é variável, e com isso podemos observar os diferentes níveis de ruído captados pelo microfone.

O circuito de testes será composto pelo módulo Sensor de Som, mais o display LCD Winstar WH1602A, que já abordamos aqui no site, neste artigo. Se você não tem esse display, não se preocupe, pois o programa é facilmente adaptável à outros modelos de displays LCD.

O display, na sua parte superior, vai mostrar o nível do som (Baixo, Médio e Alto), e na parte inferior, será mostrada uma barra que vai acompanhar em tempo real o nível do som detectado pelo microfone :

Sensor de Som - Circuito em funcionamento

O circuito :

Sensor de Som Arduino - Circuito
O programa não utiliza nenhuma biblioteca própria para o módulo sensor de som, já que vamos apenas efetuar a leitura do sinal variável recebido pelo Arduino na porta analógica. Para o display LCD, é utilizada a já conhecida LiquidCrystal.

Para melhorar a precisão do programa, optei por fazer a leitura do sinal 128 vezes, utilizando a variável NUM_LEITURA. Depois, calculo o valor médio e uso este valor para gerar no LCD a indicação de nível de som. O gráfico na linha inferior do display utiliza as informações do sinal em tempo real. Caso você opte por não utilizar o display, os dados também são mostrados no Serial Monitor.

 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
// Programa : Niveis de ruido com Sensor de Som  
// Autor : Arduino e Cia  
   
int num_leitura = 128; //Define o numero de medicoes  
int pinosinal = A0; //Pino ligado ao pino S do modulo sensor de som  
long sinal;   //Armazena o valor lido do Sensor de Som  
long soma = 0; //Armazena o valor total das n medicoes  
long nivel =0; //Armazena o valor medio  
int mostranivel = 0; //Utilizado para gerar o grafico inferior  
int apaga = 0; //Variavel auxiliar para gerar o grafico inferior  
   
#include <LiquidCrystal.h> //Carrega a biblioteca LCD  
   
//Define os pinos que serao ligados ao LCD  
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 
   
//Array para montar o simbolo grafico  
byte a[8]=   
{B10000, B11000, B11100, B11110, B11110, B11100, B11000, B10000,};   
   
void setup()  
{   
  pinMode(pinosinal, INPUT); //Define o pino de sinal como Entrada  
  Serial.begin(9600);  
  lcd.begin(16,2); //Inicializa LCD  
  lcd.clear();   //Limpa o LCD  
  lcd.setCursor(0,0); //Posiciona o cursor na coluna 0, linha 0  
  lcd.print("Nivel : ");  
  lcd.createChar(1, a); //Atribui a "1" o valor do array "A",   
                        //que desenha o simbolo grafico  
}  
   
void loop()  
{  
  //Efetua 128 leituras do sinal  
  for (int i=0; i<num_leitura ; i++)  
  {  
    sinal = analogRead(pinosinal);  
    soma = soma + sinal;  
  }  

  nivel = soma/num_leitura; //Calcula o valor medio  
  //Converte o valor lido para um valor entre 0 e 15  
  mostranivel = map(sinal, 0, 500, 0, 15);    
    
  //Gera o grafico inferior  
  for (int i = 0; i<mostranivel; i++)  
  {  
    lcd.setCursor(i,1);  
    lcd.write(1);  
    apaga = 15 - i;  
    for (int x = i; x<15;x++)  
    {  
      lcd.setCursor(x+1,1);  
      lcd.write(" ");  
    }  
  }  
     
  //Verifica o nivel de sinal e exibe na tela    
  if (nivel >0 && nivel < 100)  
  {  
    lcd.setCursor(8,0);  
    lcd.print("Baixo");  
    Serial.print("Nivel Baixo");  
    Serial.print(" - Media : ");  
    Serial.println(nivel);  
  }  

  if (nivel >100 && nivel < 200)  
  {  
    lcd.setCursor(8,0);  
    lcd.print("Medio ");  
    Serial.print("Nivel Medio");  
    Serial.print(" - Media : ");  
    Serial.println(nivel);  
  }  

  if (nivel > 200)  
  {  
    lcd.setCursor(8,0);  
    lcd.print("Alto  ");  
    Serial.print("Nivel alto");  
    Serial.print(" - Media : ");  
    Serial.println(nivel);  
  }  

  soma = 0; //Reinicia a soma dos valores das medicoes  
}  

Lembrando que os valores utilizados como comparação  podem ser ajustados de acordo com o nível de sensibilidade definido pelo potenciômetro.

01 novembro 2013

Ligando motor de passo 28BYJ-48 e ULN2003

Hoje o assunto é o Motor de Passo 28BYJ-48. Já fazia um tempo que eu queria escrever sobre motores de passo, que é um item quase que obrigatório na montagem de robôs. Outros usos incluem relógios, mostradores, painéis ou outros dispositivos que exijam algum tipo de deslocamento.

Atualizado : Veja também o artigo Controlando motor de passo 28BYJ-48 utilizando CustomStepper, onde mostro as funções da biblioteca CustomStepper para controle de ângulo e rotação do motor.

Vamos utilizar este conjunto Motor de passo 28BYJ-48 com driver ULN2003 ,que contém tudo o que você precisa para dar os primeiros passos (ops !) no assunto "motores".

Conjunto motor passo 28BYJ-48 e ULN2003

Um motor de passo funciona aplicando-se tensões específicas a cada uma das bobinas do motor, o que faz com que ele rode no sentido horário ou anti-horário, com maior ou menor velocidade, etc. No datasheet do motor você tem (quase) todas as informações sobre o componente, como por exemplo a disposição das bobinas :
Motor de passo 28BYJ-48 - Bobinas
Imagem : Modmypi

Esse experimento utiliza o módulo controlador com o chip ULN2003 (datasheet), um CI Driver de corrente que permite que, com o Arduino (que suporta corrente máxima de 50 mA por porta), sejam controlados motores que exijam correntes maiores, de até 500 mA. Este módulo aceita alimentação de 5 a 12 volts e possui leds indicadores que mostram o acionamento das bobinas.

Note que o ULN2003 somente auxilia no gerenciamento da tensão e corrente para as portas. Assim, toda a lógica de programação e sequência de bobinas que devem ser acionadas, é controlada pelo Arduino (ou outro microcontrolador que você esteja usando).

Para testes, montei um circuito utilizando dois push-buttons para controlar a rotação do motor. O botão da esquerda move o motor no sentido anti-horário, e o botão da direita, no sentido horário, sem alterar a velocidade:

Circuito motor de passo 28BYJ-48 e ULN2003 Arduino

E finalmente o programa, utilizando como base o exemplo da biblioteca Stepper com algumas alterações para tratamento das funções dos botões :

 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
// Programa : Controle de sentido de rotacao de motor de passo  
// Autor : Arduino e Cia  
   
#include <Stepper.h>  
int pinobotao_ah = 3; //Porta botao sentido anti-horario  
int pinobotao_h = 2;  //Porta botao sentido horario  
int passos = 50;      //Passos a cada acionamento do botao  
int leitura = 0;      //Armazena o valor lido do botao horario  
int leitura2 = 0;   //Armazena o valor lido do botao anti-horario  
   
const int stepsPerRevolution = 500;   
 
// Inicializa a biblioteca utilizando as portas de 8 a 11 para  
// ligacao ao motor  
Stepper myStepper(stepsPerRevolution, 8,9,10,11);        
   
void setup()   
{  
  pinMode(pinobotao_h, INPUT);  
  pinMode(pinobotao_ah, INPUT);  
  myStepper.setSpeed(60); //Determina a velocidade do motor  
}  
   
void loop()  
{  
  //Gira o motor no sentido horario  
  leitura = digitalRead(pinobotao_h);   
  if (leitura != 0)
  {
    myStepper.step(-passos);   
  }  

  //Gira o motor no sentido anti-horario  
  leitura2 = digitalRead(pinobotao_ah);  
  if (leitura2 != 0)  
  {  
    myStepper.step(passos);   
  }   
}  

Por último uma observação : este motor possui uma caixa de redução embutida (daí o eixo aparente do motor não estar no centro do mesmo). A falta de algumas especificações das engrenagens da redução geram uma certa confusão na definição dos parâmetros, principalmente no número de passos para uma volta completa, o que exige atenção se você for utilizar este motor em tarefas mais precisas.

Se você tem ou pretende adquirir um motor shield, veja no artigo Controlando motores de passo 28BYJ-48 com o Arduino Motor Shield L293D como controlar 2 motores de passo de uma maneira muito simples.


28 outubro 2013

Módulo RF Transmissor + Receptor 433 Mhz

Fui convidado a escrever um artigo para o blog do site FILIPEFLOP, mostrando a utilização de módulos RF 433 Mhz.

Montei um circuito para transmissão de dados, com os módulos RF 433 Mhz (Transmissor e Receptor), e também o LCD Nokia 5110. O resultado você confere no vídeo abaixo :




Gostou ? Então veja todos os detalhes, circuito e programa neste link :


Leia lá, comente lá ou aqui, que eu respondo do mesmo jeito. Abraço !


19 outubro 2013

Contador Display 7 segmentos - Video

Olá ! Conforme comentei, segue abaixo vídeo demonstrando o funcionamento do contador com display 7 segmentos de 3 dígitos, que abordei no artigo anterior :



15 outubro 2013

Contador Display 7 segmentos - 3 dígitos

Quem quer iniciar com o Arduino geralmente fica em dúvida sobre quais componentes comprar. Eu mesmo comprei algumas coisas que não usei até hoje... :-)

Pensando nisso, a FILIPEFLOP , parceira aqui do site, criou kits de componentes com tudo o que você precisa para montar seus primeiros experimentos. O kit básico, por exemplo, vem com o Arduino Uno, sensor ultrasonico, relé, push-button, leds, protoboard, jumpers, display LCD, fonte, potenciômetro, display 7 segmentos...e muito mais. Dê uma olhada nesse link e veja todos os kits disponíveis.

E falando em kit, no último artigo eu abordei o sensor óptico TCRT5000, mostrando o acionamento de um led com a aproximação de um objeto do sensor óptico, e hoje vou usar esse mesmo sensor óptico, mas juntamente com o display 7 segmentos 3 dígitos, que também vem no kit básico, para criar um contador.

O display 7 segmentos - 3 dígitos CPS03631BR é um display de anodo comum com 12 pinos, conforme mostrado no esquema abaixo (6 pinos na parte superior, 5 pinos na parte inferior, o pino 6 não é utilizado), e que você pode conferir no datasheet. São sete pinos para os segmentos A, B, C, D, E, F, G, um pino para o ponto decimal (DP), e um pino para cada dígito :

contador display 7 segmentos

Em um display 7 segmentos de apenas um dígito, é possível deixar o anodo sempre em estado alto, e ir acionando os segmentos conforme a necessidade, formando os  números. Nesse display de 3 dígitos, se eu deixar todos os anodos em estado alto, vou mostrar os mesmo números em todos os dígitos.

Como eu evito isso ? Usando um procedimento chamado multiplexação, que consiste no seguinte : aciono o anodo do dígito 1, e ligo os segmentos desejados, desligo o anodo do digito 1, ligo o anodo do digito 2 e aciono os segmentos desejados, e faço o mesmo procedimento com o digito 3, e depois repito o processo. Desta forma, uso os mesmo pinos do Arduino para a ativação dos segmentos de todos os dígitos. Dê uma olhada nessa animação abaixo, que mostra como isso acontece :

Animação multiplexação display 7 segmentos
Mostrando assim, parece que o display vai "piscar", não é mesmo ? Mas o segredo é fazer isso numa frequencia tão alta que o olho humano nem vai perceber, devido à um fenômeno conhecido como persistência da visão.

Antes de entrar na parte do circuito e do programa, gostaria de fazer um parênteses sobre a parte eletrônica. Eu verifiquei vários tutoriais e artigos diferentes, que mostram displays com 2 ou mais dígitos. Em alguns deles , são usadas resistências para ligar os pinos do Arduino diretamente ao anodo dos dígitos. Outros utilizam transistores, para não sobrecarregar e/ou ultrapassar a corrente máxima suportada pelo Arduino. Eu utilizei apenas um resistor de 1K em cada ligação dos anodos. Também liguei diretamente os pinos do Arduino aos pinos dos segmentos do display. Isso talvez reduza a vida útil do display, então recomendo que, dependendo da aplicação, esse procedimento seja revisto.

Vamos então à lista de materiais que utilizei :
  • 3 resistores de 1 K (um para cada dígito/anodo)
  • 1 resistor de 220 ohms (led IR do sensor óptico)
  • 1 resistor de 10 k (ligado ao sensor óptico - receptor)
  • Display 7 segmentos de 3 dígitos CPS03631BR
  • Sensor óptico reflexivo TCRT5000
Circuito contador com sensor óptico

Achei na internet vários exemplos de códigos usando multiplexação, e até criei um próprio (que não funcionou muito bem, diga-se de passagem), mas no final acabei utilizando a biblioteca SevSeg , que faz todo o serviço pesado : basta definir qual informação você quer mandar para o display (nesse programa exemplo, a varíavel CONTADOR), e a biblioteca faz o resto :

 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
// Programa : Contador utilizando display 7 segmentos e TCRT5000  
// Alterações e adaptações : Arduino e Cia  
//  
// Baseado no exemplo da biblioteca SevSeg, de Dean Reading  
// deanreading@hotmail.com  
   
#include "SevSeg.h" //Carrega a biblioteca SevSeg  
   
SevSeg sevseg;  
   
//Cria variaveis globais  
int contador = 0;  

//Ligado ao pino "coletor" do sensor óptico - Porta A5 ao Arduino  
int pinosensor = 19; 
int leitura; //Armazena o valor lido pelo sensor  
   
void setup() 
{  
  //Utilizando display de anodo comum, pinos dos digitos : 10 a 13  
  //Pino dos segmentos : 2 a 9  
  sevseg.Begin(1,13,10,11,12,2,3,4,5,6,7,8,9);  
  //Controla a luminosidade - 0 a 100  
  sevseg.Brightness(20);  
  //Define o pino do sensor optico como entrada 
  pinMode(pinosensor, INPUT);  
}  
   
void loop() 
{  
  //Produce an output on the display  
  sevseg.PrintOutput();  
  sevseg.NewNum(contador,(byte) 2);

  //Le as informações do pino do sensor  
  leitura = digitalRead(pinosensor);   
  if (leitura != 1) //Verifica se o objeto foi detectado  
  {  
    contador = contador++; //Incrementa o valor do contador  

    //Loop caso o objeto pare sobre o sensor 
    while(digitalRead(pinosensor) != 1)  
    {  
      sevseg.PrintOutput();  
     sevseg.NewNum(contador,(byte) 2);  
    }  
  }   
}  

Se você precisa de um botão de reset para zerar o contador, veja o artigo Contador com botão de reset, aqui mesmo no Arduino e Cia.

Em breve publicarei um vídeo mostrando o funcionamento desse circuito. Até lá !

Atualizado : Contador Display 7 segmentos - Vídeo


08 outubro 2013

Sensor óptico reflexivo TCRT5000 - Vídeo

Pequeno vídeo mostrando o funcionamento do sensor óptico reflexivo TCRT5000 como um "interruptor óptico", conforme circuito e programa mostrados no post anterior :




07 outubro 2013

Sensor óptico reflexivo TCRT5000

Outro sensor da série "bom e barato" é esse Sensor Óptico Reflexivo TCRT5000 que chegou recentemente da FilipeFlop. É um daqueles sensores que eu considero essenciais na gaveta de qualquer "Arduinomaníaco".

Por menos de 5 reais, ou seja, por menos do que você pagaria por duas xícaras de café, você tem um sensor óptico reflexivo que você pode usar em sensores de movimento, interruptores, alarmes, contadores e robôs, apenas para citar alguns exemplos.

"- Ah, mas eu não sei o que é um sensor óptico reflexivo"

Tudo bem, eu também não sabia, pelo menos não com esse nome. Para entender como ele funciona, vamos dar uma olhada na estrutura do sensor, cujo datasheet você encontra neste link :

Sensor Óptico Reflexivo TCRT5000

Esse sensor tem 2 componentes no mesmo suporte : um led infravermelho (cor azul) e um transistor IR (fototransistor - cor preta), separados por uma pequena "parede". Quando algum objeto se aproxima do sensor, a luz infravermelha é refletida no objeto, "passa" para o outro lado e ativa o transistor :

Sensor Óptico TCRT5000 - Esquema e funcionamento


Perceba que o tipo de objeto que você quer detectar vai influenciar diretamente na operação do sensor, já que, quanto mais reflexivo o material, maior a distância que o sensor vai alcançar. Como exemplo, fiz um teste (sem precisão), onde o sensor foi acionado com um pedaço de papel (branco) à 23 mm, uma régua de metal foi detectada à 30 mm e, com um pedaço de madeira escura, o sensor nem foi acionado.

Para testar esse sensor óptico com o Arduino Uno R3, vamos primeiramente montar este circuito. Utilizei um resistor de 330 ohms para o led infravermelho e de 10K para o transistor :

Circuito teste sensor óptico TCRT5000
Carregue este programa, abra o serial monitor e aproxime objetos do sensor até que o objeto seja detectado. No serial monitor, o status muda de "Ausente" para "Detectado" :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Programa : Teste sensor óptico reflexivo  
// Autor : Arduino e Cia  
   
int objeto = 0;  
   
void setup()  
{  
  pinMode(7, INPUT); //Pino ligado ao coletor do fototransistor  
  Serial.begin(9600);  
}  
   
void loop()  
{  
  objeto = digitalRead(7);  
  if (objeto == 0)  
  {  
    Serial.println("Objeto : Detectado");  
  }  
  else  
  {  
    Serial.println("Objeto : Ausente !");  
  }  
} 

Com o sensor devidamente testado e funcionando, vamos acrescentar um led ao circuito, e teremos um "interruptor óptico", que altera o estado do led (ligado/desligado), cada vez que um objeto é detectado :

Circuito interruptor óptico com TCRT5000 Arduino



 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
// Programa : Acionamento de led utilizando sensor óptico reflexivo  
// Autor : Arduino e Cia  
   
int sinalparaoled = 8; //Pino do led  
int pinosensor = 7;   //Ligado ao pino "coletor" do sensor óptico  
int leitura;      //Armazena informações sobre a leitura do sensor  
int estadoled = 0;   //Armazena o estado do led (ligado/desligado)  
   
void setup()  
{  
  pinMode(sinalparaoled, OUTPUT); //Define o pino do led como saida   
  pinMode(pinosensor, INPUT);   //Define o pino do sensor como entrada
}  
   
void loop()  
{  
  //Le as informações do pino do sensor
  leitura = digitalRead(pinosensor);   
  if (leitura != 1) //Verifica se o objeto foi detectado  
  {  
    while(digitalRead(pinosensor) != 1)  
    {  
     delay(100);  
    }  

    //Inverte o estado do led (ligado / desligado) 
    estadoled = !estadoled; 

    //Liga ou desliga o led conforme "estadoled" 
    digitalWrite(sinalparaoled, estadoled); 
  }   
}  
     

Como você pôde ver, este é um sensor barato e que pode ser usado nas mais variadas aplicações. Em um dos próximos artigos, vou utilizar este sensor juntamente com um display 7 segmentos para construir um contador.

Até lá !

04 outubro 2013

Módulo relé 4 canais e controle remoto IR

Dias atrás um colega leitor do blog escreveu, com dúvidas sobre como programar o Arduino para utilizar um controle remoto IR e acionar relés.

O projeto dele consiste em utilizar o Arduino Uno, uma placa com 4 relés e um controle remoto IR da marca/fornecedor Open Jumper, para o controle de 4 lâmpadas. São lâmpadas de cores diferentes : vermelha, amarela, verde e azul, que devem ser acionadas ao apertar o botão correspondente no controle remoto. Por fim, a tecla ON acende todas as lâmpadas de uma vez, e a tecla OFF apaga todas, como mostrado nesse vídeo, utilizando leds no lugar das lâmpadas :


Na foto abaixo, a placa de relés utilizada :

Módulo relé 4 canais Arduino



Eu já havia escrito um artigo sobre Controle Remoto IR aqui no site, e apesar do controle IR da Open Jumper ser um pouco diferente, podemos usar a mesma biblioteca IRremote que usamos no outro artigo. O que muda são apenas alguns códigos hexadecimais das teclas. Montei uma tabela mostrando o controle remoto utilizado, e seus respectivos códigos :

Tabela codigos controle remoto IR
Para testar o programa, montei um circuito com leds no lugar das lâmpadas. O comum de cada relé (pino central) eu liguei em 5 Volts, e o contato NO (Normal Open/Normal Aberto) de cada relê, eu liguei no anodo do led correspondente. Note que na placa há um jumper entre o pino JD-Vcc e Vcc. O JD-Vcc é utilizado quando há necessidade de uma fonte externa para ativar os relés. Como vamos utilizar os 5 volts do próprio Arduino, mantenha o jumper na placa.

Circuito modulo rele 4 canais e controle remoto IR
Por fim, o programa, que eu tentei manter o mais simples possível, não só para facilitar o entendimento, mas também tornar qualquer modificação mais tranquila. Se necessário, troque algumas definições e acionamento de portas por rotinas utilizando FOR, por exemplo, ou use o comando IF no lugar de SWITCH. São várias as opções.

  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
// Programa : Relé 4 Canais com controle IR  
// Autor : Arduino e Cia  
  
#include <IRremote.h>  
   
int RECV_PIN = 11; //Ligado ao pino do receptor IR (pino S)  
int armazenavalor = 0;  
int pinorele1 = 2; //Pino do Arduino ligado ao IN1 da placa de relés  
int pinorele2 = 3; //Pino do Arduino ligado ao IN2 da placa de relés  
int pinorele3 = 4; //Pino do Arduino ligado ao IN3 da placa de relés  
int pinorele4 = 5; //Pino do Arduino ligado ao IN4 da placa de relés  
int estadorele1 = HIGH; //Armazena o estado do relé 1  
int estadorele2 = HIGH; //Armazena o estado do relé 2  
int estadorele3 = HIGH; //Armazena o estado do relé 3  
int estadorele4 = HIGH; //Armazena o estado do relé 4  
  
IRrecv irrecv(RECV_PIN);  
decode_results results;  
  
void setup()  
{  
  pinMode(pinorele1, OUTPUT);  //Define os pino dos reles como saída  
  pinMode(pinorele2, OUTPUT);    
  pinMode(pinorele3, OUTPUT);  
  pinMode(pinorele4, OUTPUT);  
  digitalWrite(pinorele1, estadorele1); //Coloca os pinos dos reles em
  digitalWrite(pinorele2, estadorele2); //estado alto (rele desligado)  
  digitalWrite(pinorele3, estadorele3);  
  digitalWrite(pinorele4, estadorele4);  
    
  Serial.begin(9600); //Inicializa a serial  
  irrecv.enableIRIn(); // Inicializa o receptor IR  
}  
   
void loop()  
{  
  //Verifica se o sensor IR recebeu algum sinal
  if (irrecv.decode(&results))   
  {  
    //Mostra na serial o valor lido pelo sensor IR
    Serial.print("Valor lido : "); 
    Serial.println(results.value, HEX);
    //Armazena o sinal recebido pelo sensor IR  
    armazenavalor = (results.value);   
    switch (armazenavalor)  
    {  
     case 0xFF22DD: //Verifica se a tecla vermelha foi acionada  
      estadorele1 = !estadorele1;  
      //Aciona rele 1 e liga led vermelho
      digitalWrite(pinorele1, estadorele1);   
      break;  
      
     case 0xFFE01F: //Verifica se a tecla amarela foi acionada  
      estadorele2 = !estadorele2;  
      //Aciona rele 2 e liga led amarelo  
      digitalWrite(pinorele2, estadorele2); 
      break;  
      
     case 0xFF02FD: //Verifica se a tecla verde foi acionada  
      estadorele3 = !estadorele3;  
      //Aciona rele 3 e liga led Verde  
      digitalWrite(pinorele3, estadorele3); 
      break;  
      
     case 0xFF906F: //Verifica se a tecla azul foi acionada  
      estadorele4 = !estadorele4;  
      //Aciona rele 4 e liga led azul  
      digitalWrite(pinorele4, estadorele4); 
      break;  
      
     case 0xFFE21D: //Verifica se a tecla OFF foi acionada  
      //Desliga todos os reles, colocando as portas em nivel alto  
      digitalWrite(pinorele1, HIGH);   
      digitalWrite(pinorele2, HIGH);  
      digitalWrite(pinorele3, HIGH);  
      digitalWrite(pinorele4, HIGH);  
      //Seta o estado de todos os reles para alto (desligados)  
      estadorele1 = HIGH;  
      estadorele2 = HIGH;  
      estadorele3 = HIGH;  
      estadorele4 = HIGH;  
      break;  
     
     case 0xFFA25D: //Verifica se a tecla ON foi acionada  
      //Liga todos os reles, colocando as portas em nivel baixo  
      digitalWrite(pinorele1, LOW);  
      digitalWrite(pinorele2, LOW);  
      digitalWrite(pinorele3, LOW);  
      digitalWrite(pinorele4, LOW);  
      //Seta o estado de todos os reles para baixo (ligados)  
      estadorele1 = LOW;  
      estadorele2 = LOW;  
      estadorele3 = LOW;  
      estadorele4 = LOW;  
      break;  

     case 0xFF42BD: //Verifica se a tecla 7 foi acionada  
      //Desliga todos os reles, colocando as portas em nivel alto  
      digitalWrite(pinorele1, HIGH);  
      digitalWrite(pinorele2, HIGH);  
      digitalWrite(pinorele3, HIGH);  
      digitalWrite(pinorele4, HIGH);  
      delay(1000); //Aguarda 1 segundo   
      digitalWrite(pinorele1, LOW); //Aciona o rele 1   
      delay(500); //Aguarda 500 ms   
      digitalWrite(pinorele2, LOW); //Aciona o rele 2  
      delay(500); //Aguarda 500 ms  
      digitalWrite(pinorele3, LOW); //Aciona o rele 3  
      delay(500); //Aguarda 500 ms   
      digitalWrite(pinorele4, LOW); //Aciona o rele 4  
      delay(2000); //Aguarda 2 segundos  
      //Desliga todos os reles, colocando as portas em nivel alto  
      digitalWrite(pinorele1, HIGH);  
      digitalWrite(pinorele2, HIGH);  
      digitalWrite(pinorele3, HIGH);  
      digitalWrite(pinorele4, HIGH);  
      //Seta o estado de todos os reles para alto (desligados)   
      estadorele1 = HIGH;  
      estadorele2 = HIGH;  
      estadorele3 = HIGH;  
      estadorele4 = HIGH;  
      break;  
    }  
  irrecv.resume(); //Le o próximo valor  
  }  
} 

Como mostrado no vídeo no início deste artigo, teste o programa acionando o botão vermelho do controle remoto para acender o led vermelho, amarelo para o amarelo e assim por diante. Para acender todos os leds de uma vez utilize a tecla ON, e para desligar, a tecla OFF.  A tecla com o número 7 do controle remoto apaga todos os leds, depois os acende em sequencia.

O programa ainda exibe no Serial Monitor o valor em hexadecimal das teclas que foram acionadas. Desta forma, você consegue adaptar o programa ao seu controle remoto (dependendo do modelo), apenas alterando esses valores.