Índice:

Monitor de temperatura e nível de luz com exibição no LCD NOKIA 5110: 4 etapas
Monitor de temperatura e nível de luz com exibição no LCD NOKIA 5110: 4 etapas

Vídeo: Monitor de temperatura e nível de luz com exibição no LCD NOKIA 5110: 4 etapas

Vídeo: Monitor de temperatura e nível de luz com exibição no LCD NOKIA 5110: 4 etapas
Vídeo: Touchscreen based temperature monitoring and controlling with set limit 2024, Julho
Anonim
Image
Image

Olá pessoal!

Nesta seção, fazemos um dispositivo eletrônico simples para monitorar a temperatura e o nível de luz. As medições desses parâmetros são exibidas no LCD NOKIA 5110. O dispositivo é baseado no microcontrolador AVR ATMEGA328P. O dispositivo de monitoramento é equipado com termômetro digital DS18B20 e fotoresistor para medir o nível de luz.

Etapa 1: Descrição dos componentes

Componentes de descrição
Componentes de descrição
Componentes de descrição
Componentes de descrição

Componentes básicos do dispositivo de monitoramento:

  • Microcontrolador AVR «ATMEGA328P»
  • LCD gráfico monocromático «NOKIA 5110»
  • Termômetro digital de 1 fio de resolução programável «DS18B20»
  • Resistor dependente de luz
  • Fios

Microcontrolador AVR «ATMEGA328P»

O dispositivo de monitoramento usa os seguintes recursos periféricos do microcontrolador:

  1. Interrupção do temporizador / contador de 16 bits
  2. ADC de 8 canais e 10 bits
  3. Interface serial SPI mestre / escravo

LCD gráfico monocromático «NOKIA 5110»

Especificações:

  1. Tela LCD de 48 x 84 pontos
  2. Interface de barramento serial com alta velocidade máxima de 4 Mbits / S
  3. Controlador / driver interno «PCD8544»
  4. Retroiluminação LED
  5. Funciona com tensão 2,7-5 volts
  6. Baixo consumo de energia; é adequado para aplicações de bateria
  7. Faixa de temperatura de -25˚C a + 70˚C
  8. Entrada de sinal CMOS de suporte

Tratamento do endereço LCD (endereçamento):

O arranjo de endereço da memória que é mostrado no display LCD (DDRAM) é a matriz que consiste em 6 linhas (endereço Y) do endereço Y 0 ao endereço Y 5 e 84 colunas (endereço X) do endereço X 0 ao X- Endereço 83. Se o usuário deseja acessar a posição de exibição do resultado no visor LCD, deve consultar a relação entre o endereço X e o endereço Y.

Os dados que serão enviados ao display são de 8 bits (1 Byte) e serão organizados como uma linha vertical; neste caso, o Bit MSB será inferior e o Bit LSB será superior, conforme mostrado na figura.

Termômetro digital de resolução programável com 1 fio DALLAS «DS18B20»

Recursos:

  1. Interface única de 1 fio® requer apenas um pino de porta para comunicação
  2. Reduza a contagem de componentes com sensor de temperatura integrado e EEPROM
  3. Mede temperaturas de -55 ° C a + 125 ° C (-67 ° F a + 257 ° F)
  4. ± 0,5 ° C Precisão de -10 ° C a + 85 ° C
  5. Resolução programável de 9 bits a 12 bits
  6. Nenhum componente externo necessário
  7. O modo de energia parasita requer apenas 2 pinos para operação (DQ e GND)
  8. Simplifica as aplicações distribuídas de detecção de temperatura com capacidade multiponto
  9. Cada dispositivo possui um código serial exclusivo de 64 bits armazenado na ROM on-board
  10. Configurações flexíveis de alarme não volátil (NV) definidas pelo usuário com o comando de pesquisa de alarme identifica dispositivos com temperaturas fora dos limites programados

Formulários:

  1. Controles termostáticos
  2. Sistemas Industriais
  3. Produtos de consumo
  4. Termômetros
  5. Sistemas termicamente sensíveis

Resistor dependente de luz

O Resistor Dependente de Luz (LDR) é um transdutor que muda sua resistência quando a luz incide em sua superfície.

Normalmente, um LDR terá de um megaOhms a dois megaOhms na escuridão total, de dez a vinte kiloOhms a dez LUX, de dois a cinco quiloohms a 100 LUX. A resistência entre os dois contatos do sensor diminui com a intensidade da luz ou a condutância entre os dois contatos do sensor aumenta.

Use o circuito divisor de tensão para converter a mudança na resistência em mudança na tensão.

Etapa 2: Código de firmware do microcontrolador

#ifndef F_CPU # define F_CPU 16000000UL // informando a frequência do cristal do controlador (16 MHz AVR ATMega328P) #endif

// INTERFACE SPI DEFINA # define MOSI 3 // MOSI é PORTA B, PIN 3 # define MISO 4 // MISO é PORTA B, PIN 4 # define SCK 5 // SCK é PORTA B, PIN 5 # define SS 2 // SS é PORTA B, PIN 2

// RESET O DISPLAY #define RST 0 // RESET é PORTA B, PIN 0

// DISPLAY MODE SELECT - Entrada para selecionar comando / endereço ou entrada de dados. # define DC 1 // DC é PORTA B, PIN 1

// array de códigos de signstatic negativo const unsigned char neg [4] = {0x30, 0x30, 0x30, 0x30};

// codes array of digits [0..9] static const unsigned char font6x8 [10] [16] = {{0xFC, 0xFE, 0xFE, 0x06, 0x06, 0xFE, 0xFE, 0xFC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 0 {0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00}, // 1 { 0x0C, 0x8E, 0xCE, 0xE6, 0xE6, 0xBE, 0x9E, 0x0C, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 2 {0x00, 0x04, 0x06, 0x26, 0x76, 0xFE, 0xDE, 0x8C, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 3 {0x3C, 0x3E, 0x7C, 0x60, 0x60, 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01}, // 4 {0x1C, 0x3E, 0x3E, 0x36, 0x36, 0xF6, 0xF6, 0xE4, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 5 {0xFC, 0xFE, 0xFE, 0x36, 0x36, 0xF6, 0xF6, 0xE4, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 6 {0x04, 0x06, 0x06, 0x86, 0xE6, 0xFE, 0x7E, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00}, // 7 {0xCC, 0xFE, 0xFE, 0x36, 0x36, 0xFE, 0xFE, 0xCC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0 3, 0x01}, // 8 {0x3C, 0x7E, 0x7E, 0x66, 0x66, 0xFE, 0xFE, 0xFC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01} // 9};

// codifica a matriz da palavra "TEMP:" static const unsigned char TEMP_1 [165] = {0x02, 0x06, 0x06, 0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x02, 0x00, 0xFC, 0xFE, 0xFE, 0x26, 0x26, 0x24, 0x00, 0xFC, 0xFE, 0xFE, 0x1C, 0x38, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0xFC, 0x00, 0xFC, 0xFE, 0xFE, 0x66, 0x66, 0x7E, 0x7E, 0x3C, 0x00, 0x8C, 0x8C, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0C, 0x1E, 0x33, 0x33, 0x1E, 0x0C, 0x00, 0xF8, 0xFC, 0x0C, 0x9C, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01,};

// codifica a matriz da palavra "LUX:" const unsigned char TEMP_2 [60] = {0xFC, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0xFC, 0xFE, 0xFC, 0x00, 0x04, 0x8E, 0xDE, 0xFC, 0xF8, 0xFC, 0xDE, 0x8E, 0x04, 0x00, 0x8C, 0x8C, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x01};

#incluir

#include #include

// Inicialização da porta evita Port_Init () {DDRB = (1 << MOSI) | (1 << SCK) | (1 << SS) | (1 << RST) | (1 << DC); // Definir MOSI, SCK, SS, RST, DC como saída, todas as outras entradas PORTB | = (1 << RST); // Definir pino RST como alto PORTB | = (1 << SS); // Definir pino SS como alto - Display é Desative DDRC = 0xFFu; // Defina todos os pinos do PORTC como saída. DDRC & = ~ (1 << 0); // Faz o primeiro pino de PORTC como Entrada PORTC = 0x00u; // Defina todos os pinos de PORTC para baixo, o que o desliga. }

// Inicialização ADC void ADC_init () {// Habilitar ADC, amostragem freq = osc_freq / 128 definir prescaler para valor máximo, 128 ADCSRA | = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); ADMUX = (1 << REFS0); // Selecione a referência de tensão para o ADC // Selecione o canal zero por padrão usando o registro ADC Multiplexer Select (ADC0). }

// Função para ler o resultado da conversão de analógico para digital uint16_t get_LightLevel () {_delay_ms (10); // Aguarde algum tempo até que o canal seja selecionado ADCSRA | = (1 << ADSC); // Inicie a conversão ADC definindo o bit ADSC. escreva 1 para ADSC enquanto (ADCSRA & (1 << ADSC)); // espera que a conversão seja concluída // ADSC torna-se 0 novamente até então, execute o loop continuamente _delay_ms (10); retorno (ADC); // Retorna o resultado de 10 bits}

// SPI Initialization void SPI_Init () {SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); // Habilitar SPI, definir como mestre, definir pré-escalador como Fosc / 16 no controle SPI registro }

// inicializa o Timer1 de 16 bits, interrupção e variável void TIMER1_init () {// configura o timer com prescaler = 256 e modo CTC TCCR1B | = (1 << WGM12) | (1 << CS12); // inicializa o contador TCNT1 = 0; // inicializa o valor de comparação - 1 s OCR1A = 62500; // habilita a interrupção de comparação TIMSK1 | = (1 << OCIE1A); // habilita interrupções globais sei (); }

// Exibir habilitar void SPI_SS_Enable () {PORTB & = ~ (1 << SS); // Habilite o pino SS para o lógico 0}

// Exibir Desabilitar void SPI_SS_Disable () {PORTB | = (1 << SS); // Desative o pino SS para lógica 1}

// Função para enviar dados para o buffer de exibição void SPI_Tranceiver (unsigned char data) {SPDR = data; // Carrega dados no buffer while (! (SPSR & (1 << SPIF))); // Espere até a transmissão terminar}

// Reinicia o display no início da inicialização void Display_Reset () {PORTB & = ~ (1 << RST); _delay_ms (100); PORTB | = (1 << RST); }

// Função de escrita do comando void Display_Cmnd (unsigned char data) {PORTB & = ~ (1 << DC); // torna o pino DC para o lógico 0 para operação de comando SPI_Tranceiver (dados); // envia dados no registro de dados PORTB | = (1 << DC); // torna o pino DC para a lógica alta para operação de dados}

// Inicialização do Display void Display_init () {Display_Reset (); // redefine o display Display_Cmnd (0x21); // comando definido no modo de adição Display_Cmnd (0xC0); // define a tensão enviando C0 significa VOP = 5V Display_Cmnd (0x07); // definir a temperatura. coeficiente para 3 Display_Cmnd (0x13); // definir o valor do sistema de polarização de tensão Display_Cmnd (0x20); // comando definido no modo básico Display_Cmnd (0x0C); // exibe o resultado no modo normal}

// Limpa a exibição void Display_Clear () {PORTB | = (1 << DC); // torna DC pin para lógica alta para operação de dados para (int k = 0; k <= 503; k ++) {SPI_Tranceiver (0x00);} PORTB & = ~ (1 << DC); // faz DC pin para lógica zero para operação de comando}

// define a coluna e linha para a posição de exibição do resultado no visor LCD void Display_SetXY (unsigned char x, unsigned char y) {Display_Cmnd (0x80 | x); // coluna (0-83) Display_Cmnd (0x40 | y); // linha (0-5)}

// Função para exibir o sinal negativo void Display_Neg (unsigned char neg) {Display_SetXY (41, 0); // Define o endereço da posição no display para (int index = 0; index0) {SPDR = 0x30;} // Carrega os dados no buffer do display (mostra o sinal negativo) else {SPDR = 0x00;} // Carrega os dados no o buffer de exibição (limpar o sinal negativo) enquanto (! (SPSR & (1 << SPIF))); // Espere até a transmissão terminar _delay_ms (100); }}

// Função para limpar o sinal digital void Off_Dig (unsigned char x, unsigned char y) {Display_SetXY (x, y); // Defina o endereço da posição no visor (linha superior) para (int índice = 0; índice <8; índice ++) {SPI_Tranceiver (0);} // Carregar dados no buffer do visor (limpar a parte superior do sinal digital) y ++; Display_SetXY (x, y); // Definir o endereço da posição no display (linha inferior) para (int índice = 0; índice <8; índice ++) {SPI_Tranceiver (0);} // Carregar dados no buffer do display (limpar a parte inferior do sinal digital)}

// Função para exibir o sinal digital void Display_Dig (int dig, unsigned char x, unsigned char y) {Display_SetXY (x, y); // Definir o endereço da posição no display (linha superior) para (int índice = 0; índice <16; índice ++) {if (índice == 8) {y ++; Display_SetXY (x, y);} // Define o endereço da posição no display (linha inferior) SPI_Tranceiver (font6x8 [dig] [índice]); // Carrega array de códigos de dados de dígitos no buffer de display _delay_ms (10); }}

// Inicialização do DS18B20 unsigned char DS18B20_init () {DDRD | = (1 << 2); // Define o pino PD2 do PORTD como saída PORTD & = ~ (1 << 2); // Defina o pino PD2 como baixo _delay_us (490); // Tempo de inicialização DDRD & = ~ (1 << 2); // Define o pino PD2 do PORTD como input _delay_us (68); // Tempo OK_Flag = (PIND & (1 << 2)); // obtém pulso do sensor _delay_us (422); return OK_Flag; // return 0-ok sensor is plug, 1-error sensor is unplug}

// Função para ler byte de DS18B20 unsigned char read_18b20 () {unsigned char i, data = 0; para (i = 0; i <8; i ++) {DDRD | = (1 << 2); // Define o pino PD2 do PORTD como output _delay_us (2); // Timing DDRD & = ~ (1 1; // Próximo bit if (PIND & (1 << 2)) data | = 0x80; // coloca o bit no byte _delay_us (62);} dados de retorno;}

// Função para escrever byte para DS18B20 void write_18b20 (unsigned char data) {unsigned char i; para (i = 0; i <8; i ++) {DDRD | = (1 << 2); // Define o pino PD2 do PORTD como output _delay_us (2); // Tempo se (dados & 0x01) DDRD & = ~ (1 << 2); // se quisermos escrever 1, libere a linha else DDRD | = (1 1; // Próximo bit _delay_us (62); // Timing DDRD & = ~ (1 << 2); // Defina o pino PD2 do PORTD como entrada _delay_us (2);}}

// Função para exibir o nível de luz void Read_Lux () {uint16_t buffer; sem sinal int temp_int_1, temp_int_2, temp_int_3, temp_int_0; // dígitos únicos, dígitos duplos, dígitos triplos, dígitos de um quarto buffer = get_LightLevel (); // lê o resultado do nível de luz de conversão de analógico para digital temp_int_0 = buffer% 10000/1000; // temp_int_1 de um quarto de dígito = buffer% 1000/100; // temp_int_2 de três dígitos = buffer% 100/10; // dois dígitos temp_int_3 = buffer% 10; // dígito único if (temp_int_0> 0) // se o resultado for um número de um quarto de dígito {Display_Dig (temp_int_0, 32, 2); // exibe 1 dígito do nível de luz Display_Dig (temp_int_1, 41, 2); // exibe 2 dígitos do nível de luz Display_Dig (temp_int_2, 50, 2); // exibe 3 dígitos do nível de luz Display_Dig (temp_int_3, 59, 2); // exibe 4 dígitos do nível de luz} else {if (temp_int_1> 0) // se o resultado é um número de três dígitos {Off_Dig (32, 2); // limpa 1 sinal de número Display_Dig (temp_int_1, 41, 2); // exibe 1 dígito do nível de luz Display_Dig (temp_int_2, 50, 2); // exibe 2 dígitos do nível de luz Display_Dig (temp_int_3, 59, 2); // exibe 3 dígitos do nível de luz} else {if (temp_int_2> 0) // se o resultado for um número de dois dígitos {Off_Dig (32, 2); // limpa 1 sinal do número Off_Dig (41, 2); // limpar 2 sinais de número Display_Dig (temp_int_2, 50, 2); // exibe 1 dígito do nível de luz Display_Dig (temp_int_3, 59, 2); // exibe 2 dígitos do nível de luz} else // se o resultado for um número de um dígito {Off_Dig (32, 2); // limpa 1 sinal do número Off_Dig (41, 2); // limpa o sinal 2 do número Off_Dig (50, 2); // limpar 3 sinais de número Display_Dig (temp_int_3, 59, 2); // exibe 1 dígito do nível de luz}}}}

// Função para exibir a temperatura void Read_Temp () {unsigned int buffer; sem sinal int temp_int_1, temp_int_2, temp_int_3; // dígitos únicos, dígitos duplos, dígitos triplos, dígitos sem sinal char Temp_H, Temp_L, OK_Flag, temp_flag; DS18B20_init (); // Inicialização do DS18B20 write_18b20 (0xCC); // Verificação do código do sensor write_18b20 (0x44); // Iniciar conversão de temperatura _delay_ms (1000); // Atraso na pesquisa do sensor DS18B20_init (); // Inicialização do DS18B20 write_18b20 (0xCC); // Verificação do código do sensor write_18b20 (0xBE); // Comando para ler o conteúdo do Sensor RAM Temp_L = read_18b20 (); // Lê os primeiros dois bytes Temp_H = read_18b20 (); temp_flag = 1; // temperatura 1-positiva, temperatura 0-negativa // Obtém temperatura negativa if (Temp_H & (1 << 3)) // Verificação do Bit de Sinal (se o bit está definido - temperatura negativa) {assinado int temp; temp_flag = 0; // sinalizador é definido como 0 - temperatura negativa temp = (Temp_H << 8) | Temp_L; temp = -temp; // Converta o código adicional em direto Temp_L = temp; Temp_H = temp >> 8; } buffer = ((Temp_H 4); temp_int_1 = buffer% 1000/100; // dígito triplo temp_int_2 = buffer% 100/10; // dígito duplo temp_int_3 = buffer% 10; // dígito único

// Se a temperatura for negativa, exibirá o sinal de temperatura, caso contrário, limpará

if (temp_flag == 0) {Display_Neg (1);} else {Display_Neg (0);} if (temp_int_1> 0) // se o resultado for um número de três dígitos {Display_Dig (temp_int_1, 45, 0); // exibe 1 dígito de temperatura Display_Dig (temp_int_2, 54, 0); // exibe 2 dígitos da temperatura Display_Dig (temp_int_3, 63, 0); // exibe 3 dígitos da temperatura} else {if (temp_int_2> 0) // se o resultado for um número de dois dígitos {Off_Dig (45, 0); // limpa 1 sinal de número Display_Dig (temp_int_2, 54, 0); // exibe 1 dígito de temperatura Display_Dig (temp_int_3, 63, 0); // exibe 2 dígitos de temperatura} else // se o resultado for um número de um dígito {Off_Dig (45, 0); // limpa 1 sinal do número Off_Dig (54, 0); // limpa 2 sinais de número Display_Dig (temp_int_3, 63, 0); // exibe 1 dígito de temperatura}}}

// Este ISR é disparado sempre que ocorre uma correspondência da contagem do cronômetro com o valor de comparação (a cada 1 segundo) ISR (TIMER1_COMPA_vect) {// Leitura, exibição de temperatura e nível de luz Read_Temp (); Read_Lux (); }

// Função para exibir as palavras "TEMP" e "LUX" void Display_label () {// Palavra "TEMP" Display_SetXY (0, 0); // Define o endereço da posição no display (linha acima) para (int index = 0; index <105; index ++) {if (index == 40) {Display_SetXY (0, 1);} // Define o endereço da posição no display (linha inferior) if (índice == 80) {Display_SetXY (72, 0);} // Define o endereço da posição no display (linha superior) if (índice == 92) {Display_SetXY (72, 1); } // Define o endereço da posição no display (linha inferior) SPDR = TEMP_1 [índice]; // Carrega os dados da matriz de códigos no buffer de exibição while (! (SPSR & (1 << SPIF))); // Espere até a transmissão terminar _delay_ms (10); } // Palavra "LUX" Display_SetXY (0, 2); // Define o endereço da posição no display (linha acima) para (int index = 0; index <60; index ++) {if (index == 30) {Display_SetXY (0, 3);} // Define o endereço da posição no display (linha inferior) SPDR = TEMP_2 [índice]; // Carrega os dados da matriz de códigos no buffer de exibição while (! (SPSR & (1 << SPIF))); // Espere até a transmissão terminar _delay_ms (10); }}

int main (vazio)

{Port_Init (); // Inicialização da porta ADC_init (); // Inicialização ADC SPI_Init (); // Inicialização SPI SPI_SS_Enable (); // Habilitar exibição DS18B20_init (); // Inicialização do DS18B20 Display_init (); // Exibir inicialização Display_Clear (); // Mostra clear Display_label (); // Mostra as palavras "TEMP" e "LUX" TIMER1_init (); // Inicialização Timer1. Comece a monitorar. Obtendo parâmetros a cada segundo. // Loop infinito enquanto (1) {}}

Etapa 3: Flashing Firmware to Microcontrolador

Carregando o arquivo HEX na memória flash do microcontrolador. Assista ao vídeo com uma descrição detalhada da gravação da memória flash do microcontrolador: Gravação da memória flash do microcontrolador…

Etapa 4: Montagem do circuito do dispositivo de monitoramento

Montagem do circuito do dispositivo de monitoramento
Montagem do circuito do dispositivo de monitoramento
Montagem do circuito do dispositivo de monitoramento
Montagem do circuito do dispositivo de monitoramento

Conecte os componentes de acordo com o diagrama esquemático.

Conecte a energia e está funcionando!

Recomendado: