Medição da Temperatura
Vou usar o sensor LM35, que eu já descrevi aqui no blog. Este sensor fornece uma tensão de saída igual à temperatura dividida por 100 (quando medida em Volts). Por exemplo, se a temperatura for 25 graus, a saída do LM35 será 0,25V. Neste projeto vamos considerar apenas temperaturas positivas até 99 graus centígrados, o que significa uma tensão de até 0,99V.
A medida desta tensão será feita com o ADC do ATtiny85. Para maior precisão, vamos usar a referência interna de 1.1V. Desta forma a temperatura (em graus) será (teoricamente) igual à leitura do ADC multiplicada por 110 e dividida por 1024.
Um último cuidado é ligar em um pino do Franzininho que não tenha nada ligado. O que nos leva a usar a entrada AN1.
Display LCD
Neste projeto vou usar um display do Nokia 5110, que vimos com muitos detalhes aqui, aqui, aqui e aqui (entre outros posts). Neste caso temos duas mudanças importantes:
- O modelo que eu vou usar tem uma placa azul, com a indicação 3v-5v. Este modelo permite ligar direto a 5V. O modelo que usei antes (placa vermelha) usa 3.3V, exigindo redução das tensões nas ligações.
- Devido ao número limitado de pinos de saída do Franzininho, o pino RST do display será ligado à alimentação através de um resistor de 15K. Desta forma o reset será feito apenas quando o circuito for alimentado, o Franzininho não poderá forçar um reset.
Vamos aproveitar que o display é gráfico e apresentar dígitos grandes.
Um aviso: estes displays são meio temperamentais. Existem vários relatos de problemas com contraste e enfrentei alguns comportamentos estranhos com ele neste projeto.
Um aviso: estes displays são meio temperamentais. Existem vários relatos de problemas com contraste e enfrentei alguns comportamentos estranhos com ele neste projeto.
Circuito
Software
O software foi feito a partir dos meus exemplos anteriores com o display 5110. A principal mudança é a escrita no display, que foi trocada por uma rotina específica para o relógio. Esta rotina permite escrever uma caracter (dígito, vírgula, grau ou C) em uma de seis posições (correspondendo a 99,9oC).
Na leitura do sensor é feita um média de 16 leituras. Um detalhe interessante é que a referência interna é extremamente estável (varia pouco com tempo e temperatura), mas não muito precisa (pode variar entre 1,0 e 1,2). No código abaixo o valor da referência foi "calibrado" usando um multímetro externo para ler a tensão no LM35.
Na leitura do sensor é feita um média de 16 leituras. Um detalhe interessante é que a referência interna é extremamente estável (varia pouco com tempo e temperatura), mas não muito precisa (pode variar entre 1,0 e 1,2). No código abaixo o valor da referência foi "calibrado" usando um multímetro externo para ler a tensão no LM35.
- /*
- * Termômetro
- * DQ - 01/03/18
- */
- // Conexões do display ao Franzininho
- #define PIN_SCE 0
- #define PIN_DC 4
- #define PIN_SDIN 1
- #define PIN_SCLK 3
- // Conexão do sensor (LM35)
- #define PIN_SENSOR A1
- // Seleção de dado ou comando
- #define LCD_CMD LOW
- #define LCD_DAT HIGH
- // Tamanho da tela
- #define LCD_DX 84
- #define LCD_DY 48
- // Envia um byte para o controlador do display
- // dc: LCD_CMD ou LCD_DAT
- // data: byte a enviar
- void LcdWrite(byte dc, byte data)
- {
- digitalWrite(PIN_DC, dc);
- digitalWrite(PIN_SCE, LOW);
- shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
- digitalWrite(PIN_SCE, HIGH);
- }
- // Iniciação do display
- void LcdInitialise(void)
- {
- // define a direção dos pinos de E/S
- pinMode(PIN_SCE, OUTPUT);
- pinMode(PIN_DC, OUTPUT);
- pinMode(PIN_SDIN, OUTPUT);
- pinMode(PIN_SCLK, OUTPUT);
- // envia os comandos de iniciação
- LcdWrite( LCD_CMD, 0x21 ); // LCD Extended Commands.
- LcdWrite( LCD_CMD, 0xB0 ); // Set LCD Vop (Contraste)
- LcdWrite( LCD_CMD, 0x04 ); // Set Temp coefficent
- LcdWrite( LCD_CMD, 0x14 ); // LCD bias mode 1:48
- LcdWrite( LCD_CMD, 0x20 ); // LCD Basic Commands.
- LcdWrite( LCD_CMD, 0x0c ); // LCD no modo normal
- }
- // Limpa a tela
- void LcdClear(void)
- {
- // posiciona ponteiro no inicio da memória
- LcdWrite( LCD_CMD, 0x40);
- LcdWrite( LCD_CMD, 0x80);
- // preenche a memória com zeros
- for (int index = 0; index < LCD_DX * LCD_DY / 8; index++)
- {
- LcdWrite(LCD_DAT, 0x00);
- }
- }
- // Posiciona em uma determina linha e coluna alfanuméricas
- void LcdPos(int lin, int col)
- {
- LcdWrite( LCD_CMD, 0x40 + lin);
- LcdWrite( LCD_CMD, 0x80 + col*7);
- }
- // Tabelas para desenhar os caracteres
- static const int offset_dig[] = {0, 14, 28, 36, 50, 58 };
- static const int larg_dig[] = {14, 14, 8, 14, 8, 14 };
- static const byte gc_dig[][30] =
- {
- { 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00 }, // 0
- { 0x00, 0x00, 0x0C, 0x06, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, // 1
- { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, // 2
- { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00 }, // 3
- { 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03 }, // 4
- { 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00 }, // 5
- { 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00 }, // 6
- { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03 }, //7
- { 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00 }, // 8
- { 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFC,
- 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00 }, // 9
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0x60, 0x1F,
- 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // virgula
- { 0x1E, 0x21, 0x21, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // grau
- { 0xFC, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 } // C
- };
- // Escreve um dígito na tela
- // dig: 0 a 9, 10 (virgula), 11 (grau), 12 (C)
- // pos: 0 a 5
- void LcdWriteDig(int dig, int pos)
- {
- byte *gc = gc_dig[dig];
- int larg = larg_dig[pos] - 4;
- for (byte bloco = 1; bloco <= 3; bloco++)
- {
- LcdWrite(LCD_CMD, 0x40 + bloco);
- LcdWrite(LCD_CMD, 0x80 + offset_dig[pos]);
- LcdWrite(LCD_DAT, 0x00);
- LcdWrite(LCD_DAT, 0x00);
- for (int index = 0; index < larg; index++)
- {
- LcdWrite(LCD_DAT, *gc++);
- }
- LcdWrite(LCD_DAT, 0x00);
- LcdWrite(LCD_DAT, 0x00);
- }
- }
- //=====================================
- // Pontos de entrada padrão do Arduino
- //=====================================
- void setup(void)
- {
- LcdInitialise();
- LcdClear();
- LcdWriteDig (0, 0);
- LcdWriteDig (0, 1);
- LcdWriteDig (10, 2);
- LcdWriteDig (0, 3);
- LcdWriteDig (11, 4);
- LcdWriteDig (12, 5);
- analogReference(INTERNAL);
- analogRead(PIN_SENSOR);
- }
- void loop(void)
- {
- // Faz 16 leituras para maior precisão
- int vSensor = 0;
- for (int i = 0; i < 16; i++)
- {
- vSensor += analogRead(PIN_SENSOR);
- }
- vSensor = vSensor >> 2;
- // 0,01V = 1 grau Celsius
- // Referência interna pode variar entre 1.0 e 1.2 V
- // Valor abaixo baseado em medida feita com multímetro
- long temp = (vSensor*1016L)/(4096L);
- // Mostra a temperatura
- LcdWriteDig ((int)(temp/100), 0);
- LcdWriteDig ((int)((temp/10)%10), 1);
- LcdWriteDig ((int)(temp%10), 3);
- // Tempo entre atualizações
- delay(1000);
- }
Nenhum comentário:
Postar um comentário