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