Thermometer
von Inox5
In diesem Artikel geht es um ein Thermometer, das die Temperatur über den ADC mit einem Temperaturwiderstand auf einer LED-Skala anzeigt. Je eine LED-Spalte entspricht 2°C. Controller ist der AVR ATMega16.
Info
Eigenschaft | Wert |
---|---|
Spannung | 9-35V (Vorwiderstände der LEDs selber berechnen) |
Messbereich | -10°C...+38°C |
Strom (alle LEDs an) | 0,6A @12V |
Controller | ATMEGA16 |
Sprache | C |
Schaltplan und Layout
Der 100nF Kondensator für Aref ist mit Kabeln angeschlossen (rote Linien). Er ist also direkt an den PINs anzuschließen. Die PNGs sind 150DPI. Das Bauteil 25 Widerstände sind wie gesagt einfach 25 Widerstände mit je 1k. An die LED-Anschlussleiste werden nicht direkt die LEDs angeschlossen (außer man nimmt nur eine) sondern die Transistorverstärker der jeweiligen LED-Spalte. Die LED-Anschlussleiste beherrbergt also die Steuerleitungen. Die LED Vorwiderstände sollte jeder selbst für seine Betriebsspannung ausrechnen.
Kalibrierung
Sie gestaltet sich recht simpel. Man muss lediglich einmal den Wert des ADC in den EEPROM schreiben, wenn der Temperaturwiderstand in Eiswasser ist und einmal in kochenden Wasser. Mit diesen Werten kann man sich dann ausrechnen, wieviel sich der ADC-Wert verändert damit eine Veränderung der Temperatur um 1°C gemessen wird.
Beispiel: Die beiden Werte sind 300 (Eiswasser) und 700 (Kochendes Wasser). Die Differenz beträgt 700-300=400. D.h. der ADC verändert seinen Wert über 100°C Temperaturdifferenz um 400. Nun kann man die Auflösung des ADC ausrechnen: 100°C/400=0,25°C. Jetzt kann man den Schluss ziehen, dass eine Veränderung des ADC um 4 eine Veränderung der Temperatur um 1°C bedeutet. Dadurch wird es auch möglich den ADC-Wert direkt in Temperatur umzurechnen, wäre da nicht noch der Offset, der durch den Spannungsteiler bedingt ist. Man kann ihn aber leicht bestimmen: 300(Eiswasser)*0,25°C=75°C. Da man ja weiß, dass Eiswasser genau 0°C hat, weiß man nun, dass der Offset 75°C beträgt.
Also muss der AVR folgendes rechnen um auf die Temperatur zu kommen: ADC * 0,25°C - 75°C = Temperatur
Source
#include <avr/io.h> //Grundfunktionen
#ifndef F_CPU //Vordefinieren für delay.h
#define F_CPU 1000000UL //Definition von F_CPU in Hertz
#endif
#include <util/delay.h> //Warteschleifen
#include <stdint.h> //Variablen
#include <avr/eeprom.h> //EEPROM Funktionen
//Globale Variablen
int32_t Temperatur=-10; //ist die Temperaturvariable, wird mit -10 initialisert, weil meine LED-Skala bei -10 anfängt
void Temperaturbildung (void) //bildet die Temperatur
{
ADCSRA |= (1<<ADSC); //Messung starten, kann nicht schaden, auch wenn der ADC eh schon im freerunning Mode ist
loop_until_bit_is_clear (ADCSRA , 6); //Warten bis Messung vorbei ist
Temperatur = ADCW;
Temperatur = Temperatur * 1000;
Temperatur = Temperatur / 1755; //entspricht einer Division mit 1,755 (ich hätte auch multiplizieren können mit 0,57)
Temperatur = Temperatur - 273; //Abziehen des Offset (am besten mit Referenzthermometer abgleichen)
}
void Anzeige (void) //wandelt Temperatur in LED-Signale um
{
if (Temperatur==-10)
{
PORTA=0b00000000;
PORTB=0b01000001;
PORTC=0b00000000;
PORTD=0b00000000;
}
if (Temperatur==-9)
{
PORTA=0b00000000;
PORTB=0b01000001;
PORTC=0b00000000;
PORTD=0b00000000;
}
if (Temperatur==-8)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000000;
}
if (Temperatur==-7)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000000;
}
if (Temperatur==-6)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000001;
}
if (Temperatur==-5)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000001;
}
if (Temperatur==-4)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000011;
}
if (Temperatur==-3)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000011;
}
if (Temperatur==-2)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000111;
}
if (Temperatur==-1)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00000111;
}
if (Temperatur==0)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00001111;
}
if (Temperatur==1)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00001111;
}
if (Temperatur==2)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00011111;
}
if (Temperatur==3)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00011111;
}
if (Temperatur==4)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00111111;
}
if (Temperatur==5)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b00111111;
}
if (Temperatur==6)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b01111111;
}
if (Temperatur==7)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b01111111;
}
if (Temperatur==8)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b11111111;
}
if (Temperatur==9)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000000;
PORTD=0b11111111;
}
if (Temperatur==10)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000001;
PORTD=0b11111111;
}
if (Temperatur==11)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000001;
PORTD=0b11111111;
}
if (Temperatur==12)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000011;
PORTD=0b11111111;
}
if (Temperatur==13)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000011;
PORTD=0b11111111;
}
if (Temperatur==14)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000111;
PORTD=0b11111111;
}
if (Temperatur==15)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00000111;
PORTD=0b11111111;
}
if (Temperatur==16)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00001111;
PORTD=0b11111111;
}
if (Temperatur==17)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00001111;
PORTD=0b11111111;
}
if (Temperatur==18)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00011111;
PORTD=0b11111111;
}
if (Temperatur==19)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00011111;
PORTD=0b11111111;
}
if (Temperatur==20)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00111111;
PORTD=0b11111111;
}
if (Temperatur==21)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b00111111;
PORTD=0b11111111;
}
if (Temperatur==22)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b01111111;
PORTD=0b11111111;
}
if (Temperatur==23)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b01111111;
PORTD=0b11111111;
}
if (Temperatur==24)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==25)
{
PORTA=0b00000000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==26)
{
PORTA=0b01000000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==27)
{
PORTA=0b01000000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==28)
{
PORTA=0b01100000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==29)
{
PORTA=0b01100000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==30)
{
PORTA=0b01110000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==31)
{
PORTA=0b01110000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==32)
{
PORTA=0b01111000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==33)
{
PORTA=0b01111000;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==34)
{
PORTA=0b01111100;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==35)
{
PORTA=0b01111100;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==36)
{
PORTA=0b01111110;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==37)
{
PORTA=0b01111110;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==38)
{
PORTA=0b01111111;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
if (Temperatur==39)
{
PORTA=0b01111111;
PORTB=0b11000001;
PORTC=0b11111111;
PORTD=0b11111111;
}
}
int main (void)
{
//PORTKONFIGURATION
DDRA=0b01111111; //PA7 ist vom ADC belegt
PORTA=0b00000000;
DDRB=0b11111110; //PB0 ist ein Schalter
PORTB=0b00000001; //Pullup für PB0
DDRC=0b11111111;
PORTC=0b00000000;
DDRD=0b11111111;
PORTD=0b00000000;
//-----------------
//ADC
ADMUX=0b01000111; //Referenz=VCC ; rightadjusted ; ADC7 selected
ADCSRA=0b11000011; //ADC on ; free-running ; no interrupts ; ADC-Clock: 1MHz/8
//-----------------
//PROGRAMMSCHLEIFE
while(1)
{
Temperaturbildung(); //Diese Funktion wandelt den ADC-Wert in Temperatur
Anzeige(); //Hier wird die Variable Temperatur in konkrete Zeichen auf einer LED-Skala umgesetzt
}
//-----------------
return(0);
}