Termômetro de dois dígitos



O autor fez este termômetro LED de dois dígitos como presente de aniversário para o filho de seu amigo. Ele tem apenas dois anos e já está lendo os números, mas as letras não. Agora ele pode descobrir a temperatura do lado de fora da janela por conta própria. O sensor no termômetro é um chip DS18B20 operando de acordo com o protocolo 1-Wire, e o microcontrolador é do tipo ATtiny84. O tabuleiro é quadrado com um lado de 25 mm, em tamanho comparável a uma moeda de 50 centavos. O autor planeja colocar o quadro em uma caixa estanque e colocá-lo fora da janela. A indicação liga brevemente a cada 24 segundos e as pilhas CR2032 duram cerca de um ano.
O termômetro opera na faixa de -19 a +99 ° C. Se necessário, o menos e um são exibidos simultaneamente na ordem alta. Fora do intervalo, as letras Lo ou Hi são exibidas. Você pode "ensinar" o dispositivo a exibir temperaturas abaixo de -19 ° C usando um segmento com um ponto como menos.

De acordo com esse esquema, o dispositivo foi montado anteriormente em uma placa de ensaio:



Todas as saídas do microcontrolador estão envolvidas, o gerador de clock de 8 MHz incorporado é usado. O protótipo foi o seguinte:



O protótipo usou DS18B20 no pacote TO-92, ATtiny84 no pacote PDIP e um indicador 3621AS de 3,6 polegadas. Em seguida, o autor desenvolveu o quadro em Eagle e o encomendou no PCBway. Aqui, o microcontrolador já está no gabinete SOIC, o sensor está no gabinete µSOP e os resistores, capacitores e display são do tamanho 0805. Tudo, exceto o display, é soldado por um secador de cabelo Youyue 858D + a uma temperatura de 250 ° C.

Tanto o protótipo quanto a placa de circuito impresso possuem indicadores com um ânodo comum. O dispositivo é fabricado em duas versões, com indicadores de vermelho e amarelo. Vermelho - no KDPV, amarelo - aqui:



Um suporte para uma célula de lítio de 20 mm (qualquer um com uma designação que começa com 20, isto é, 2016, 2025 ou 2032) é soldado na parte de trás:



O firmware é escrito para que o microcontrolador fique no modo de suspensão na maioria das vezes e acorde após a interrupção do timer do watchdog. Na implementação da interface 1-Wire, esse tempo de operação do mesmo autor está envolvido. O contador de timer de 16 bits do microcontrolador operando na frequência de 1 MHz consome tempo:

void OneWireSetup () { TCCR1A = 0<<WGM10; // Normal mode TCCR1B = 0<<WGM12 | 2<<CS10; // Normal mode, divide clock by 8 } 

A sub-rotina DelayMicros () fornece um atraso de um número especificado de microssegundos, com base no registro de comparação de saída OCR0A:

 void DelayMicros (unsigned int micro) { TCNT1 = 0; TIFR1 = 1<<OCF1A; OCR1A = micro; while ((TIFR1 & 1<<OCF1A) == 0); } 

A rotina DisplayTemperature () lê o valor da temperatura do sensor e o exibe. Como existe apenas um sensor no barramento, você pode ignorar o número de série e fornecer o comando Ignorar ROM, após o qual todos os seguintes comandos são enviados para qualquer dispositivo:

 void DisplayTemperature () { cli(); // No interrupts if (OneWireReset() != 0) { sei(); DisplayError(0); // Device not found } else { OneWireWrite(SkipROM); OneWireWrite(ConvertT); while (OneWireRead() != 0xFF); OneWireReset(); OneWireWrite(SkipROM); OneWireWrite(ReadScratchpad); OneWireReadBytes(9); sei(); // Interrupts if (OneWireCRC(9) == 0) { int temp = DataWords[0]; Display((temp+8)>>4); // Round to nearest degree } else DisplayError(1); // CRC error } } 

Em resposta à solicitação, o sensor retorna o valor da temperatura na forma de um número inteiro assinado de 16 bits em unidades iguais a 1/16 graus. O número é arredondado para o grau inteiro mais próximo e exibido chamando a rotina Display ().

A sub-rotina DisplayError () exibe erros na interação do microcontrolador com o sensor no barramento de 1 fio:

 void DisplayError (int no) { Buffer[0] = Error; Buffer[1] = no; } 

E0 - sensor não detectado, erro E1 - CRC.

Os dados para indicação dinâmica são obtidos da matriz Buffer []. Por exemplo, para exibir o número 20, você deve fazer:

 Buffer[0]=2; Buffer[1]=0; 

O contador do temporizador 0 gera interrupções na frequência de 125 Hz, o que é suficiente para eliminar a cintilação. Primeiro, o timer está configurado em setup () "

 TCCR0A = 2<<WGM00; // CTC mode; count up to OCR0A TCCR0B = 0<<WGM02 | 4<<CS00; // Divide by 256 OCR0A = 250-1; // Compare match at 125Hz TIMSK0 = 0; // Interrupts initially off 

A rotina de manipulação de interrupção correspondente durante a comparação chama a rotina DisplayNextDigit () e conta na direção oposta:

 ISR(TIM0_COMPA_vect) { DisplayNextDigit(); Ticks--; } 

A sub-rotina DisplayNextDigit () lê dados da célula correspondente na matriz Buffer [] e inclui os segmentos desejados no bit de exibição correspondente. O programa usa #define para escolher entre um indicador com um cátodo ou ânodo comum. Se todos os segmentos estiverem acesos imediatamente após a inicialização, o tipo de exibição não corresponde ao especificado no firmware. Para um cátodo comum, a sub-rotina deve ser substituída pelo seguinte:

 void DisplayNextDigit () { PORTB = PORTB | 1<<digit; // Turn old digit off digit = digit ^ 1; // Toggle between 0 and 1 char segs = charArray[Buffer[digit]]; PORTA = segs; // Lit segments high PORTB = PORTB & ~(1<<digit); // Turn new digit on } 

Finalmente, a rotina Display () produz um número de dois dígitos para gravar na matriz Buffer []:

 void Display (int n) { int units = n % 10; int tens = n / 10; int temp0 = tens; int temp1 = abs(units); if (tens < -1) {temp0 = Lo; temp1 = Lo+1; } else if (tens > 9) {temp0 = Hi; temp1 = Hi+1; } else if (tens == -1) temp0 = Minus1; else if ((tens == 0) && (units >= 0)) temp0 = Blank; else if ((tens == 0) && (units < 0)) temp0 = Minus; Buffer[0] = temp0; Buffer[1] = temp1; } 

Também leva em consideração os casos de exibição de menos junto com a unidade na ordem alta, bem como mensagens sobre a temperatura fora da faixa.

Para a máxima economia de energia possível, os geradores de relógio ADC, USI e ADC são desativados e o modo de suspensão PWR_DOWN é ativado:

  ADCSRA &= ~(1<<ADEN); // Disable ADC to save power PRR = 1<<PRUSI | 1<<PRADC; // Turn off clocks to USI & ADC to save power set_sleep_mode(SLEEP_MODE_PWR_DOWN); 

O programa principal exibe a temperatura por décimos de segundo e depois ativa o modo de suspensão. Verificou-se que este é o tempo mínimo de indicação, conveniente para a leitura. Dois segundos antes da temperatura ser exibida, o ponto pisca brevemente:

 void loop () { Buffer[0] = DP; Buffer[1] = Blank; DisplayOn(12); WDDelay(6); // Sleep for 1 second Buffer[0] = Blank; Buffer[1] = DP; DisplayOn(12); WDDelay(6); // Sleep for 1 second DisplayTemperature(); DisplayOn(12); WDDelay(9); // Sleep for 8 seconds WDDelay(9); // Sleep for 16 seconds WDDelay(9); // Sleep for 24 seconds } 

O visor permanece desligado por 24 segundos devido a três chamadas de vigilância por 8 segundos cada. Com o indicador em funcionamento, o consumo atual é de 6,6 mA, no modo de suspensão - 4,7 μA, o consumo médio de corrente é de 1/240 * 6,6 mA. A capacidade típica da célula CR2032 é de 225 mAh, portanto é suficiente para (225 / 6,6) x 240/24 = 340 dias - um pouco menos de um ano.

As faixas de temperatura dos componentes são as seguintes: microcontrolador e indicador - de -40 a + 85 ° C, resistores e capacitores - de -55 a +125 ° C, baterias - de -20 a +70 ° C. Um elemento com uma faixa de temperatura estendida BR2032 operará na faixa de -30 a +85 ° C.

O microcontrolador é compatível com Arduino com este desenvolvimento Spence Konde. No IDE, selecione ATtiny24 / 44/84 na seção ATTinyCore do menu Board. Então você precisa definir as seguintes opções, sem prestar atenção ao resto:

 Chip: "ATtiny84" Clock: "8 MHz (internal)" BOD: "BOD Disabled" Pin Mapping: "Clockwise (like damellis core)" 

O programa é carregado usando o clipe de teste Pomona, colocado na parte superior do microcontrolador e conectado ao programador SparkFun Tiny AVR. Primeiro você precisa selecionar Burn Bootloader, depois Upload.

Links: o texto completo do programa , o quadro e o programa no GitHub , o quadro no OSHpark .

Source: https://habr.com/ru/post/pt454220/


All Articles