Sei sulla pagina 1di 8

ArduinoLcdSensorIR - Karl Heinz Benz

ArduinoLcdSensorIR

Projeto: ArduinoLcdSensorIR

Objetivo: Construir um protótipo em protoboard que meça a distância utilizando um sensor


InfraVermelho e a informe em um LCD.

Componentes: Placa Arduino Duemilanove com ATmega328


Sensor IR GP2Y0A02 (Sharp)
Display LCD 2x16 LCM1602B

Referências: 1. Site do Arduino


2. Arduino x LCD
3. Eu e o Robô (HD44780 Character LCD)
4. Sharp GP2Y0A02 Long Distance Measuring Sensor
5. Arduino: Using a Sharp IR Sensor for Distance Calculation (Lucky Larry)
6. Acroname Robotics
7. The Robotics Primer Workbook

O primeiro passo do protótipo foi a montagem do LCD LCM1602B de 2 linhas de 16


caracteres junto ao Arduino (ver referência 2 acima), e fazer o LCD mostrar a famigerada frase
“hello, world!”, tudo em letras minúsculas, tão ao gosto dos programadores C. Não resisti, e mudei
o h inicial, minúsculo, para um adequado H MAIÚSCULO.

A única dificuldade encontrada foi a curiosa pinagem do LCD, que reproduzo abaixo
(observe as posições anômalas dos pinos 15 e 16); a seqüência é 16 – 15 – 1 – 2 – 3 – 4 – 5 – 6 –
7 – 8 – 9 – 10 – 11 – 12 – 13 – 14. Não sei se é uma regra geral para este tipo de LCD ou se
depende do fabricante, mas tome cuidado!

Os pinos são:

Pino Descrição
1 Ground
2 VCC (+5V)
3 Contrast adjustment
4 Register Select (R/S)
5 Read/Write (R/W)

1
ArduinoLcdSensorIR - Karl Heinz Benz

6 Clock (Enable)
7 Data 0
8 Data 1
9 Data 2
10 Data 3
11 Data 4
12 Data 5
13 Data 6
14 Data 7
15 Backlight Anode (+)
16 Backlight Cathode (-)

As conexões do LCD são as seguintes:

LCD (pino) Conexão


1 GND GND
2 VCC + 5V
3 Contrast adjustment Pino central do potenciômetro de 10K
4 RS Arduino I/O Digital pino 12
5 RW GND
6 Enable Arduino I/O Digital pino 11
7 D0 N/C (não conectado)
8 D1 N/C
9 D2 N/C
10 D3 N/C
11 D4 Arduino I/O Digital pino 5
12 D5 Arduino I/O Digital pino 4
13 D6 Arduino I/O Digital pino 3
14 D7 Arduino I/O Digital pino 2
15 Backlight Anode (+) N/C
16 Backlight Cathode (-) N/C

O potenciômetro ao qual é conectado o pino 3 do LCD serve para ajuste de luminosidade;


seus outros pinos são ligados em GND e +5V, respectivamente.

O programa (sketch) para testar a montagem, conforme referência 1 acima, é:

/*
LiquidCrystal Library - Hello World

Demonstrates the use a 16x2 LCD display. The LiquidCrystal


library works with all LCD displays that are compatible with the
Hitachi HD44780 driver. There are many of them out there, and you
can usually tell them by the 16-pin interface.

This sketch prints "Hello World!" to the LCD


and shows the time.

The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)

Library originally added 18 Apr 2008


by David A. Mellis
library modified 5 Jul 2009

2
ArduinoLcdSensorIR - Karl Heinz Benz

by Limor Fried (http://www.ladyada.net)


example added 9 Jul 2009
by Tom Igoe
modified 8 Feb 2010
by Tom Igoe

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/

// include the library code:


#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("hello, world!");
}

void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis()/1000);
}

O resultado, conforme a mesma referência, deve ser (1 hora e pouco, ou 5.171 segundos
após ser ligado):

Se não funcionar, verifique as conexões; se você estiver usando outro modelo de LCD, a
pinagem poderá ser diferente. Ajuste o potenciômetro para a luminosidade ideal. Experimente
outros textos, na primeira e segunda linhas, sempre lembrando da limitação de 16 letras por linha
(com este modelo de LCD, claro).

Importante: não continue a montagem se você não conseguiu obter sucesso com o display
LCD. Aumentar a complexidade do problema não irá aumentar suas chances de sucesso, muito
pelo contrário.

3
ArduinoLcdSensorIR - Karl Heinz Benz

O sensor IR GP2Y0A02

Depois de o circuito estar funcionando corretamente, chegou a hora de conectar o sensor


IR (infravermelho) GP2Y0A02 (Sharp). A referência 4, de autoria de Lucky Larry, dá maiores
detalhes sobre a montagem.

As principais características do sensor GP2Y0A02 são:


 voltagem operacional: 4,5 a 5,5V
 consumo médio de corrente: 33mA (típico)
 faixa de distância operacional: 20 a 150 cm (8" a 60")
 tipo de saída: voltagem analógica
 tempo de resposta: 38 ± 10 ms
 tamanho da peça: 29.5x13.0x21.5 mm (1.16x0.5x0.85")
 peso: 4.8g

A conexão do sensor GP2Y0A02 é simples:

GP2Y0A02 (pino) Conexão


1 Saída analógica Arduino Analogic IN Pino 1
2 GND GND
3 VCC + 5V

Um detalhe relevante é que este sensor retorna uma informação ambígua em certas
condições, conforme o gráfico 1 - ou seja, abaixo de aproximadamente 20 cm de distância, suas
leituras não são confiáveis. Em outras palavras, o sensor mede, de forma confiável, distâncias
entre 20 e 150 cm. Isto deve ser levado em conta na hora de montar o sensor em algum
dispositivo robótico.

Gráfico 1

4
ArduinoLcdSensorIR - Karl Heinz Benz

Pode-se também trabalhar com o inverso da distância (gráfico 2):

Gráfico 2

Na experiência do autor supra referido (Lucky Larry), a distância é determinada p/ fórmula:


1 / Volts * 65, mas o próprio autor reclama de problemas de precisão. O sketch do Arduino é:

int IRpin = 1; // analog pin for reading the IR sensor


void setup() {
Serial.begin(9600); // start the serial port
}
void loop() {
float volts = analogRead(IRpin)*0.0048828125; // value from sensor * (5/1024) - if
running 3.3.volts then change 5 to 3.3
float distance = 65*pow(volts, -1.10); // worked out from graph 65 = theoretical
distance / (1/Volts)S - luckylarry.co.uk
Serial.println(distance); // print the distance
delay(100); // arbitary wait time.
}

O resultado, neste caso, não é enviado ao LCD, mas sim ao computador, via interface
serial (comando Serial.println(distance);). Você pode fazer as adaptações necessárias.

Medições mais precisas

Os problemas de precisão se devem à fórmula utilizada, que considera que a tensão de


saída é uma função linear da distância, o que na realidade não ocorre, como se pode observar nos
gráficos (embora deva ser considerado que com a utilização do inverso da distância, como mostra
o gráfico 2, a precisão é boa entre 30 e 150 cm - quase uma linha reta).

5
ArduinoLcdSensorIR - Karl Heinz Benz

Em minha opinião, a abordagem mais correta seria dividir a curva de resposta em


segmentos (aproximados) de reta, conforme é demonstrado no gráfico 1, onde a curva de resposta
é dividida em segmentos que correspondem a cada 10 cm, dos 20 cm aos 150 cm. Deste gráfico
podemos deduzir a seguinte tabela de correspondências (aproximadamente):

Tensão (V) Distância (cm)


2,8 15
2,52 20
2,0 30
1,52 40
1,25 50
1,07 60
0,9 70
0,8 80
0,73 90
0,6 100
0,55 110
0,52 120
0,5 130
0,49 140
0,48 150

Observa-se facilmente que, após os 150 cm, a medição se torna completamente imprecisa,
pois praticamente não há mais variação da tensão de entrada em função da distância.

A partir desta tabela, o cálculo da distância obedecerá a uma regra de 3 simples,


considerando o segmento de reta que abrange a tensão de entrada. Assim, supondo que a tensão
de entrada seja representada por VLido:

Gráfico 3

A fórmula para descobrir o valor de X (distância em função de VLido) é:

X = DInf - (((DInf - DSup) * (VSup - VLido)) / (VSup - VInf))

6
ArduinoLcdSensorIR - Karl Heinz Benz

O programa que implementa esta solução é o seguinte:

/*
Projeto: ArduinoLcdSensorIR

Objetivo: Construir um protótipo em protoboard que meça a distância utilizando um


sensor InfraVermelho e a informe em um LCD

Componentes: Placa Arduino Duemilanove com ATmega328


Sensor IR GP2Y0A02 (Sharp)
Display LCD 2x16 LCM1602B

Autor: Karl Heinz Benz

Data: 27/06/2010

Correções, sugestões e nova documentação devem ser enviadas a karlbenz@terra.com.br

Licenciamento: Atribuição-Uso não-comercial-Compartilhamento pela mesma licença 3.0 Brasil

http://creativecommons.org/licenses/by-nc-sa/3.0/br/

Biblioteca utilizada: LiquidCrystal Library - Hello World


library originally added 18 Apr 2008 by David A. Mellis
library modified 5 Jul 2009 by Limor Fried (http://www.ladyada.net)
example added 9 Jul 2009 by Tom Igoe
modified 25 July 2009 by David A. Mellis

http://www.arduino.cc/en/Tutorial/LiquidCrystal

The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)

*/

#include <LiquidCrystal.h>

int IRpin = 1; // analog pin for reading the IR sensor

// Tabelas de tensões e distâncias


float VetorTensao[16] = {2.8, 2.52, 2.0, 1.52, 1.25, 1.07, 0.9, 0.8, 0.73, 0.6, 0.55, 0.52,
0.5, 0.49, 0.48, 0.48};
int VetorDist[16] = {15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150,
150};

float VLido;
float Distancia;
float DInf;
float DSup;
float VInf;
float VSup;

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
// configuração inicial do LCD (16 colunas, 2 linhas)
lcd.begin(16, 2);
// posiciona o cursor (coluna 0, linha 0)

7
ArduinoLcdSensorIR - Karl Heinz Benz

lcd.setCursor(0, 0);
// envia mensagem ao LCD
lcd.print("Sharp GP2Y0A02YK");
}

void loop() {
// O valor do sensor deve ser multiplicado pelo valor da tensão de alimentação (3.3 ou 5V)
// e dividido por 1024
float VLido = analogRead(IRpin) * 0.0048828125; // valor do sensor * (5 / 1024)

// O loop abaixo localiza os valores VSup e VInf em função de VLido


for (int i=0; i<=16; i++){
if (VLido <= VetorTensao[i] && VLido > VetorTensao[i+1])
{
DInf = VetorDist[i+1];
DSup = VetorDist[i];
VInf = VetorTensao[i];
VSup = VetorTensao[i+1];
Distancia = DInf - ((DInf - DSup) * (VSup - VLido)) / (VSup - VInf);
}
}
// posiciona o cursor (coluna 0, linha 1)
lcd.setCursor(0, 1);
lcd.print(VLido);
lcd.print(" V ");
if (VLido < 0.48)
{ lcd.print("> 150");
}
else
{ lcd.print(Distancia);
}
lcd.print(" cm ");
delay(200);
}

O resultado é razoavelmente preciso. Claro que a Sharp, poderosa multinacional, poderia


se esforçar um pouco para melhorar a linearidade da resposta, mas o resultado final é
suficientemente bom para o objetivo que nos propusemos.