Teil 2 -- Ein digitales Thermomether order rede I2C mit deinem Microcontroller
ArticleCategory: [Choose a category, do not translate
this]
Hardware
AuthorImage:[Here we need a little image from you]
TranslationInfo:[Author + translation history. mailto: or
http://homepage]
original in en Guido
Socher
en to de Guido
Socher
AboutTheAuthor:[A small biography about the author]
Guido mag Linux weil es ein wirklich gutes System ist, um eigene Hardware
zu entwickeln.
Abstract:[Here you write a little summary]
In diesem zweiten Teil werden wir ein LCD display in unser Thermomether einbauen
und ich werde erkl�ren wie die Software funktioniert.
Die Leser, die neu hinzugekommen sind, sollten zuerst
den ersten Teil (Februar 2005
Artikel 365) lesen.
ArticleIllustration:[This is the title picture for your
article]
ArticleBody:[The article body]
Die neuen Teile
In dem
vorrangegangenen Artikel
haben wir schon den wichtigsten Teil der Hardware, die n�tig war um
Temperaturen zu messen, aufgebaut. In diesem Artikel gibt es nun ein
sehr einfaches gtk GUI und ein LCD display.
Es ist sehr einfach diese beiden Dinge hinzuzuf�gen, deshalb werde ich den
Rest des Artikels darauf verwenden die I2C Software und die Analogdigitalwandler
Software zu erkl�ren.
Das LCD-Display
Als Display benugtzen wir ein HD44780 kompatibles Display, wie ich es schon in
�lteren Artikeln eingesetzt hatte. Diese Displays sind sehr einfach in Verbindung
mit Microcontrollern zu benutzen, da man einfach ASCII Zeichen an das Display
schicken kann.
Wie f�r alle anderen Artikel in dieser Serie gibt es auch hier wieder die Bauteile
bei shop.tuxgraphics.org
Ich benutze den gleichen LCD-Treiber wie in den �lteren Artikeln. Die Dateien,
die den Treiber implementieren sind lcd.c, lcd.h und lcd_hw.h. Sie sind Teil
des Paketes, welches sich am Ende des Artikels herrunterladen l��t.
Das Interface f�r diesen Code ist wirklich einfach zu benutzen:
// call this once:
// initialize LCD display, cursor off
lcd_init(LCD_DISP_ON);
// to write some text we first clear
// the display:
lcd_clrscr();
lcd_puts("Hello");
// go to the second line:
lcd_gotoxy(0,1);
lcd_puts("LCD");
Wie diese HD44780 Displays genau funktionieren ist in
dem linuxfocus
September2002 Artikel "HD44780 kompatible LCD-Displays verstehen"
erkl�rt.
Die Software ist so geschrieben, da� sie mit 16x2 und 20x2 Zeichen Displays
funktioniert.
Es gibt leider im Schaltbild ein �nderung. Ich habe entdeckt, da� einige LCD Displays
einen h�heren kapazitiven Innenwiderstand haben als andere. Das ist vermutlich so, weil
sie einen besseren ESD Schutz haben. Diese h�here Last kann Bit-Errors beim
Programmieren des Microcontrollers verursachen, wenn das Display an die SCK und MOSI
Leitungen des Microcontrollers angschlossen ist.
Als erste L�sung f�r dieses Problem habe ich einfach ein paar Widerst�nde
in die Leitungen zum Display eingel�tet. Das funktionierte problemlos bei mir,
aber einige Leser, speziell Leute mit Laptops hatten immer noch Probleme.
Um das Problem vollst�ndig zu vermeiden habe ich dann das Schaltungsdiagramm
ge�ndert und die D7 und RS Pins des Display an PD7 und PD6 angeschlossen.
Es ist kein Problem das auf der Platine zu �ndern. Dazu ist lediglich ein
kurzes St�ck Draht unter der Platine n�tig und die Verbindung zu PB3 mu� mit einem Messer
unterbrochen werden.
Ein einfaches GUI
F�r die Leser, die gerne ein GUI auf Ihrem Desktop haben, habe ich ein
wirklich einfaches GUI entwickelt. Es besteht aus 2 Textzeilen die die Ausgabe
es Befehls i2ctemp_linux wiedergeben (das GUI ruft einfach den Befehl i2ctemp_linux
auf und dieser liest die Temperatur via I2C).
Jetzt haben wir ein richtig cooles Thermomether:
- Man kann die Temperatur lokal am Display ablesen.
- Man kann ein kleines GUI auf seinem Desktop haben.
- Man kann die Temperaturwerte �ber einen cron-job in eine Datei schreiben
und damit Statistiken �ber l�ngere Zeit haben.
Den Rest des Artikels werde ich jetzt damit verwenden die Interna der Software
zu erkl�ren.
Wie es funktioniert: Analogdigitalwandler
Der Atmega8 hat zwei Modi. Einen in dem er permanent analog zu digital
wandelt und immer einen Interrupt ausl�st, wenn ein Konvertierung fertig
ist. Die Applikation kann dann dem Interrupt benutzen um schnell des Ergebnis
aus den Registern in Variablen zu kopieren.
In dem anderen Modus, der sich "single shot mode" nennt wird nur ein Konvertierung
durchgef�hrt. Dieser Mode ist immer noch recht schnell. Mit der Zeit, die man
braucht um alle Voreinstellungen richtig zu setzen kann man immer noch 100 Konvertierungen pro Sekunde erreichen. Das ist mehr als schnell genug f�r unsere Zwecke.
Wir nehmen deshalb diesen Modus.
Als Eing�nge kann der Atmega8 die Pins ADC0 bis ADC3 benutzen. Daneben gibt es
noch die Pins AGND
(analog ground, Verbunden mit der normalen Masse),
AREF (reference voltage) und AVCC (verbunden mit +5V).
W�hrend der AD-Wandlung wird das analoge Signal mit AREF verglichen. Ein analoges
Signal das gleich mit AREF ist, entspricht einem digitalen Wert von 1023. AREF kann
eine externe Referenz zwischen 0 und 5V sein. Ohne externe Referenz kann man immer
noch exakte Messungen machen, indem man entweder die interne Referenzspannung (2.56V), oder AVCC benutzt. Welche dieser Optionen benutzt werden soll, l��t sich �ber die
REFS0 und REFS1 Bits im ADMUX Register einstellen.
Der Analogdigitalwandler kann zu einem Zeitpunkt nur einen der Eing�nge ADC0-ADC3
konvertieren. Bevor die Konvertierung beginnt mu� man festlegen, welcher Eingang
benutzt werden soll und das geht auch �ber Bits im ADMUX Register.
Eine einfache AD-Wandlung w�rde dann so aussehen:
volatile static int analog_result;
volatile static unsigned char analog_busy;
analog_busy=1; // busy mark the ADC function
channel=0; // measure ADC0
// use internal 2.56V ref
outp((1<<REFS1)|(1<<REFS0)|(channel & 0x07),ADMUX);
outp((1<<ADEN)|(1<<ADIE)|(1<<ADIF)|(1<<ADPS2),ADCSR);
sbi(ADCSR,ADSC); // start conversion
Jetzt wird der Microcontroller die AD-Wandlung durchf�hren und dann die
Funktion SIGNAL(SIG_ADC) aufrufen sobald die AD-Wandlung fertig ist.
Als Programmierer mu� man darauf achten, da� man die unteren 8 Bits der Ergebisregister
immer zuerst lesen mu�.
SIGNAL(SIG_ADC) {
unsigned char adlow,adhigh;
adlow=inp(ADCL); /* read low first, two lines. Do not combine
the two lines into one C statement */
adhigh=inp(ADCH);
analog_result=(adhigh<<8)|(adlow & 0xFF);
analog_busy=0;
}
Jetzt haben wir das Ergebnis in der Variablen analog_result. Dieser Wert kann
nun anderswo im Programm benutzt werden. Ganz einfach.
Wie bei allen Interrupts mu� man einmal global sei(); aufrufen um Interrupts einzuschalten. Das wird im Haupprogramm gemacht und ist deshalb hier nicht aufgef�hrt.
Es gibt eine Menge Bits und Flags, die ich kurz erkl�ren werde:
- ADEN: Analog Digital Converter Enable, mu� vor ADSC gesetzt werden
- ADIE: Enable ADC Interrupt (=schaltet Interrupts ein, daruch wird der Aufruf von SIGNAL(SIG_ADC) m�glich)
- ADIF: ADC Interrupt Flag (mu� auf 1 vor der Konvertierung gesetzt werden)
- ADPS: ADC clock pre-scaler bits:
Mu� so eingestellt werden, das die Taktfrequenz geteilt durch den
pre-scale Faktor einen Wert zwischen 50 und 200 kHz ergibt.
Der pre-scale Faktor ist 2^ADPS (zwei hoch ADPS Bits Wert).
Die oben benutzte Einstellung (ADPS2=1, ADPS1=0, ADPS0=0 = dezimal 4 -> 2^4 = 16 -> Teilerfaktor = 16) ist gut f�r eine Taktfrequenz von
1MHz.
Der Atmega8 hat verschiedene M�glichkeiten was die Referenzspannung betrifft:
REFS0=0, REFS1=0 | benutze eine externe AREF Spannung, die interne Vref ist aus |
REFS0=0, REFS1=1 | AVCC mit optionalen Kondensator an dem AREF Pin |
REFS0=1, REFS1=1 | interne 2.56V Referenz with (optionalem)
externem Kondensator an dem AREF Pin |
Der optionale externe Kondensator am AREF Pin kann rauschen unterdr�chen und
die AREF Spannung stabilisieren.
Wie es funktioniert: I2C Kommunikation, Atmega8 Teil
Im Teil I
(Februar 2005 Artikel365)
habe ich schon erkl�rt wie das I2C Protokoll funktioniert. Jetzt wollen wir
uns die Software etwas n�her ansehen. Der Atmega8 hat Hardwareunterst�tzung f�r
I2C Kommunikation. Man mu� deshalb das I2C Protokoll garnicht implementieren.
Stattdessen schreibt man eine Zustandsmaschine, die dem Atmega8 sagt was
als n�chstes getan werden soll. Hier ein Beispiel:
Ein I2C Paket mit unser eigenen Slave-Adresse ist angekommen.
Der Atmega8 wird nun die Funktion
SIGNAL(SIG_2WIRE_SERIAL) mit dem
Statuscode 0x60 (f�r andere Ereignisse gibt es andere Codes) aufrufen.
--> Jetzt m�ssen wir einige Register setzen, um dem Atmega8 zu sagen, was
als n�chstes zutun ist. In diesem Fall sagen wir ihm: Empfange den Datenteil und
best�tige mit einem ack-Bit.
Wenn die eigentlichen Daten empfangen wurden, werden wir mit dem
Statuscode 0x80 aufgerufen.
--> Nun lesen wir das Datenbyte und sagen dem Atmega8, da� er auch das n�chste
empfangen und best�tigen soll.
Wenn die Kommunikation zuende ist, erhalten wir den Statuscode 0xA0 (stop condition)
und wir k�nnen unser Applikation sagen, da� eine vollst�ndige Nachricht empfangen
wurde.
Die gesamte Zustandsmaschine f�r den I2C Slave und alle m�glichen Statuscodes
sind im Datenblatt Seite 183 erkl�rt (siehe Link unter Referenzen am Ende des
Artikels).
Das Senden von Daten funktioniert ganz �nlich. Schau einfach mal in den Code
rein!
Wie es funktioniert: I2C Kommunikation, Linux Seite
Zun�chst einige Worte zur Hardware. Obwohl I2C ein Bus ist, benutzen wir
nur Punkt zu Punkt Kommunikation zwischen einem Slave und dem Linux PC als
Master. Wir k�nnen uns deshalb die "pullup" Widerst�nde sparen, solange
der Slave die Leitung gegen Masse ziehen kann, ohne eine Kurzschlu� zu verursachen.
Wir setzen deshalb die 4.7K Widerst�nde in serie in die Leitung.
Die Spannungspegle m�ssen angepasst werden. Das machen wir mit Z-Dioden, die
negative Spannungen auf -0.7V und positive auf max. +5.1V begrenzen.
Nachdem ich inzwischen mehr �ber die Internas des Atmeag8 gelesen habe, denke
ich da� man sich eigentlich die Z-Dioden sparen k�nnte, da der Strom �ber die
4.7K klein genug ist, damit auch die internen Schutzvorrichtungen des Atmeag8
gegen �berspannung ausreichen m��ten. Die Z-Dioden schaden aber
auch nicht. In der n�chsten Schaltung nehme ich sie vielleicht raus.
Die Linux I2C Software implementiert einen kompletten I2C Stack. Dadurch
ist die Linux-Seite unabh�ngig von irgenwelchen Kernelmodulen und Bibliotheken.
Es ist einfach ein kleines Programm das unabh�ngig und problemlos funktioniert.
Wenn man sich die Datei i2c_m.c ansiehst (siehe Download) dann stellt man fest, da�
wirklich jede I2C Nachricht Bit f�r Bit zusammengebaut wird.
Um die "Bits" zu erzeugen m�ssen wir die physikalischen Leitungen der
RC232 Schnittstelle setzen. Das geht �ber ioctl Aufrufe:
// set RTS pin:
int arg=TIOCM_RTS;
ioctl(fd, TIOCMBIS, &arg);
... oder um eine "Null" zu erzeugen:
// clear RTS pin:
int arg=TIOCM_RTS;
ioctl(fd, TIOCMBIC, &arg);
Falls man diesen Code auf ein anderes Betriebsystem portieren m�chte, braucht
man lediglich diese Zeilen zu �ndern. Der Rest ist ganz normaler ANSI C-Code.
USB zu RS232
Bei Laptops, die m�glicherwiese heute keine RS232 Schnittstelle mehr haben, kann
man einfach einen USB zu RS232 Adapter nehmen. Ich benutze, z.B eine No-name Adapter
der einen Prolific 2303 Chip enth�lt. In
/proc/bus/usb/devices sieht das bei mir so aus:
Vendor=067b ProdID=2303 Rev= 2.02. N�heres zu solchen Adaptern findet sich auch in "Einen ATEN
UC-232A USB Adapter unter Linux nutzen (Linuxfocus, November 2001, Artikel 223)".
Zusammenfassung
Ich benutze das Thermometer nun seit 2 Monaten und es gef�llt mir wirklich gut.
Ich kann die Temperatur direkt ablesen und die Daten �ber den PC auswerten.
Der Au�ensensor mu� gut gegen Regen und Sonne gesch�tzt sein. Man kann versuchen
ihn in irgendwelches Plastik einzuwickeln, aber ich empfehle das nicht. Egal wie
dicht man es verpackt, eines Tages kommt etwas Wasser hinein und kann dann nicht
mehr raus. Der NTC ist recht robust und es macht ihm eigentlich nichts aus, wenn
er mal f�r kurze Zeit feucht wird, solange er dann auch wieder trocknen kann.
Eine umgedrehte Tablettendose eigent sich ganz gut. Ich habe sie unten offen gelassen
und so kann das Wasser auch wieder raus.
Auch f�r diesen Artikel bekommt man wieder alle Teile (LCD Display, Platine, Microcontroller, ...) �ber den
tuxgraphics Online-shop: shop.tuxgraphics.org.
Viel Spa�!
Referenzen