[LinuxFocus-icon]
<--  | Plan  | Index  | Suchen

Nachrichten | Archiv | Links | Über uns
Dieses Dokument ist verfübar auf: English  Castellano  ChineseGB  Deutsch  Francais  

[Photo of the Author]
von Guido Socher (homepage)

Über den Autor:

Guido mag Linux weil es ein wirklich gutes System ist um eigene Hardware zu entwickeln



Übersetzt ins Deutsche von:
Guido Socher (homepage)

Inhalt:

 
PDF

Ein digitales Thermometer oder rede I2C mit deinem Microcontroller

[Illustration]

Zusammenfassung:

Der Atmega8 Microcontroller von Atmel hat jede Menge digitale und analoge Ein-/Ausgänge. Es ist das ideale Bauteil um Meßelektronik zu entwickeln.

In diesem Artikel werden wir sehen wie man einen Microcontroller mit einem Linux PC über eine physikalische RS232 Schnittstelle verbinden kann, ohne aufwendige Adapterschaltungen wie den MAX232 Chip zu benutzen.

_________________ _________________ _________________

 

Einführung

Eine Voraussetzung für diesen Artikel ist, daß du die GCC AVR Programmierumgebung, wie in den dem Artikel "Programmieren eines AVR Microcontrollers mit GCC, libc 1.0.4" beschrieben, installiert hast. Natürlich kannst du, um Ärger bei der Installation zu vermeiden, auch die "AVR programming CD" von http://shop.tuxgraphics.org/ benutzen.


Wenn man so ein enorm mächtiges Bauteil wie einen Microcontroller benutzt, um analoge oder digitale Signale zu messen, dann möchte man natürlich Schnittstellen zum Auswerten haben und Befehle an den Microcontroller schicken können. In allen vorangegangenen Artikeln haben wir immer die RS232 Schnittstelle mit einem UART zur Kommunikation benutzt. Der Nachteil ist hierbei, daß man einen zusätzlichen MAX232 Chip und 4 Kondensatoren braucht. Atmel schlägt sogar vor, daß man einen externen Quarz für den Oszillator benutzen soll damit die UART Kommunikation zuverlässig funktioniert. In jeden Fall sind das eine Menge extra Bauteile.... und diese kann man vermeiden!

Die Menge an Daten, die zwischen PC und Microcontroller übertragen werden müssen ist normalerweise klein (nur einige Bytes). Die Übertragungsgeschwindigkeit spielt daher praktisch keine Rolle. Das macht den I2C Bus attraktiv für diese Aufgabe.

I2C (ausgesprochen "ei-squär-sie") ist ein bidirektionales Kommunikationssystem mit nur zwei Drähten. Es wurden von Philips entwickelt und sie haben sich den Namen schützen lassen. Daher nennen es andere Hersteller nicht I2C. Bei Atmel heißt es TWI ("two wire interface").

Viele von euch benutzen möglicherweise I2C in ihrem PC ohne es zu wissen. Alle modernen Motherboards haben einen I2C-Bus um Temperatursensoren, Lüftergeschwingigkeit, verfügbaren Speicher... und alle möglichen anderen Daten zu lesen. Dieser I2C-Bus ist leider am normalen PC nicht nach außen geführt (es gibt außen keine physikalischen Anschluß dafür). Wir müssen uns deshalb etwas neues überlegen.

Erst wollen wir aber sehen, wie das "two wire interface" (=TWI = anderer Name für I2C) funktioniert.  

Wie I2C/TWI funktioniert

Das Datenblatt des Atmega8 (siehe unten) hat eine sehr detaillierte Beschreibung, die auf Seite 160 beginnt. Ich werde deshalb hier nur einen Überblick geben. Danach solltest du in der Lage sein, das Datenblatt zu verstehen.

An einem I2C-Bus hat man immer einen "Master" und verschiedene "Slaves". Die Kommunikation findet zu einem Zeitpunkt immer zwischen dem Master und genau einem Slave statt. Der Master ist das Gerät, das die Kommunikation beginnt und und den Bit-Takt (clock) kontrolliert. Die zwei Drähte des I2C-Bus nennen sich SDA (Datenleitung) und SCL (Clock line, Taktleitung). Jedes der Geräte muß von einer separaten Stromversorgung (genau wie bei normaler rs232 Kommunikation) gespeist werden. Die zwei Drähte des Busses sind normalerweise über 4.7K Widerstände mit der logischen Eins (+5V für 5V ICs) verbunden. Das ergibt eine elektrische Veroderung zwischen den Geräten. Ein Gerät braucht dann nur die Leitung auf GND ziehen, wenn es eine 0 übertragen will oder nichts machen, wenn es eine 1 senden will.

Der Master beginnt einen Dialog indem er ein Bitmuster, das als "start condition" gefolgt von der Adresse des Gerätes das er ansprechen möchte, schickt. Jedes Gerät an dem Bus hat eine eindeutige 7 Bit Adresse. Danach schickt der Master ein Bit das anzeigt ob er lesen oder schreiben möchte. Der Slave (das angesprochene Gerät) wird nun bestätigen, daß es den Master verstanden hat und schickt ein ack-bit (ack wie acknowledge). Mit anderen Worten wir haben jetzt 9 Datenbits auf dem Bus gesehen (7 Adressbits + read_bit + ack-bit):
| start | 7-bit slave adr | read_data bit | wait for ack | ... data comes here
Was kommt danach?

Als nächstes können wir Daten senden oder empfangen. Die Daten sind immer ein Vielfaches von 8 Bit (1 Byte) und müssen durch ein Ack-Bit bestätigt werden. Es werden also immer 9 Bit über den Bus geschickt. Wenn die Kommunikation zu ende ist, schickt der Master ein Bitmuster namens "stop condition". Mit anderen Worten der Master muß wissen, wie viele Daten der Slave schicken möchte. Das ist aber kein Problem, denn man kann diese Information immer in den Dialog zwischen Master und Slave mit den Daten übertragen. In unserem Fall werden wir z.B. das Null-Byte am Ende eines Strings benutzen um anzuzeigen, daß der übertragene String zu ende ist.

Die Daten auf dem SDA Draht sind immer solange gültig wie SCL 1 ist. SDA darf sich also nicht ändern während SCL 1 ist:
SDA H -\       /---\     /---\          /---\
    L   \-----/     \---/     \--------/     \------....

SCL H ----\     /-\       /-\     /-\    /-\    /-\
    L      \---/   \-----/   \---/   \--/   \--/   \-....


  | START |      1 |       1 |     0 |    1 |    0 |
Das Beste an diesem Protokoll ist, daß man kein genaues synchrones Taktsignal braucht. Das Protokoll wird immer noch funktionieren wenn der Takt etwas wackelt (Jitter).

Genau diese Eigenschaft macht es möglich, I2C in einer ganz normalen Benutzerapplikation zu implementieren. Man braucht kein Kernelmodul oder spezielle Hardware (wie UART). Genial oder?  

Die Idee

Wie schon gesagt können wir den PC internen I2C Bus nicht benutzen. Stattdessen benutzen wir einfach einige Leitungen der RS232 Schnittstelle. Unsere Kommunikationsschnittstelle ist also immer noch RS232 aber wir brauchen keine MAX232 Hardware, keine Kondensatoren, .... etc

Der schwierige Teil ist nun das I2C Protokoll neu in einer Linuxapplikation zu implementieren und zu testen. Ich habe dafür 5 Wochen gebraucht bis es 100%ig funktionierte und du kannst es einfach kopieren :-). Ich hoffe du erkennst den Wert dieses Programms, wenn du es benutzt.
Als Anwendung für unser neues I2C Protokoll werden wir ein Thermometer bauen. Du kannst natürlich auch irgend etwas anderes messen oder einfach Lichter ein/aus-schalten. Es ist deine Entscheidung.

In einem zweiten Artikel werden wir ein LCD-Display hinzufügen. Mit anderen Worten es wird ein Thermometer bei dem man die Temperatur über den Linux PC oder direkt über eine Anzeige ablesen kann. Das Display kommt in einem zweiten Artikel um diesen hier nicht zu überladen.
ntc
NTCs sind klein, billig und ausreichend genau
 

Der Temperatursensor

Es gibt schon fertig kalibrierte Temperatursensoren (einige von ihnen reden sogar I2C ;-) aber diese sind recht teuer. NTCs sind viel billiger und fast genauso gut selbst ohne Kalibrierung. Wenn man sie kalibriert kann man Genauigkeiten bis hinter dem Dezimalpunkt erreichen.

Ein Problem von NTCs ist ihre Nichtlinearität. Es ist aber eigentlich nur eine Frage der Halbleiterphysik hier die richtige Formel zu finden und diese nicht lineare Kurve zu korrigieren. Der Microcontroller ist ein kleiner Computer und mathematische Operationen sind überhaupt kein Problem. NTCs sind temperaturabhängige Widerstände. Der Widerstandswert R eines NTCs bei einer gegebenen Temperatur ist:
ntc formula
T oder Tc ist die Temperatur, die wir suchen. Rn ist der Widerstandswert bei 25'C. Man kann NTCs mit 4.7K, 10K, ... kaufen. Rn ist dieser Wert.
 

Die Schaltung

circuit diagram
Schaltplan. Klick auf den Plan um eine genauere Ansicht zu erhalten.
Nun haben wir alles um das digitale Thermometer zu bauen. Wir nehmen zwei NTCs. Einen für innen und einen für die Außentemperatur. Du kannst noch mehr Sensoren anschließen. (conn3, Pin PC2 ist z.B frei). In dem Schaltbild sieht man schon das LCD-Display. Ich wollte vermeiden, daß für den nächsten Artikel wieder eine neue Schaltung gebaut werden muß.

In der Schaltung findet sich eine ein LED. Das kostet nicht viel und ist sehr nützlich zum debuggen. Ich habe es oft benutzt als ich die I2C State-machine für die Kommunikation zwischen PC und Microcontroller entwickelt habe. Im normalen Betrieb lassen wir die LED einfach blinken um zu zeigen, daß Messwerte genommen werden.

Die Schaltung ist ansonsten ganz einfach. Der Analogdigitalwandler in dem Microcontroller wird benutzt um den Spannungsabfall an einem NTC zu messen. Dieser wird dann in einen Temperaturwert übersetzt.

Der Atmega8 hat verschiedene Möglichkeiten die Referenzspannung des Analogdigitalwandlers zu wählen. Man kann entweder 5V (AVcc) oder einen interen 2.56V Referenz benutzen. Für die Innentemperatur brauchen wir einen viel kleineren Bereich. +10'C bis +40'C sollten ausreichen. Wir nehmen daher hier die 2.56V Referenz und erhalten die doppelte Genauigkeit, da jetzt 1024 mögliche digitale Werte auf 0-2.56V verteilt sind. Das ergibt eine Genauigkeit von 2.5mV (genauer als die meisten digitalen Voltmeter!).

Der CD Anschluß an der RS232 Schnittstelle ist ein Eingang und wir schließen ihn daher an die SDA Leitung des I2C Bus an. DTR und RTS sind Ausgänge. Wenn der PC Daten-bits auf den Bus gibt, dann ändert er einfach DTR. Der I2C Master, hier der Linux PC, kontrolliert die SCL (Takt) Leitung. Mit anderen Worten SCL ist ein Ausgang an dem RS232 Anschluß.

Der 78L05 wird benutzt um eine stabile Stromversorgung und eine Referenzspannung zu erhalten. Du kannst daher fast jede Art von Stromversorgung benutzen. DC oder AC zwischen 7.5V ond 12V. 9V ist eine gute Wahl.  

Die Platine erstellen

get this kit from the tuxgraphics shop
tuxgraphics.org verkauft alle nötigen Bauteile zusammen mir einer geätzten Platine.
Man kann natürlich auch die Lochrasterplatine aus dem vorangegangenen Artikel benutzen. Dazu muß man die LED auf Pin 11 umlöten und die neuen Bauteile hinzufügen.

Wenn du jedoch eine Schaltung bauen möchtest, die auch gut aussieht, dann macht es mehr Sinn eine neue Platine zu ätzen, denn diese Schaltung ist einfach viel komplexer als die Testschaltung aus dem ersten Artikel. Nachdem ich Iznogood's Linuxfocus Artikel über gEDA gelesen hatte, beschloss ich dieses Mal gEDA anstelle von Eagel zu benutzen. gschem, das Schaltplanzeichenprogramm von gEDA ist sehr gut. Die Bibliothek der vorhandenen Symbole ist wesentlich kleiner als bei Eagle und so mußte ich mein eigenes Symbol für den Atmega8 entwerfen, aber ging erstaunlich einfach. Viel problematischer ist pcb, das Programm zum Zeichnen der Platine. Wenn man vorher Eagle benutzt hat wird man zunächst irritiert sein, daß sich die Gummibandverbindungen von den Bauteilen entfernen lassen. Um sicher zu sein, daß das richtige Gummiband an dem richtigen Bauteil hängt muß man sie von Zeit zu Zeit neu erzeugen (Connects->Optimize rats-nest). Man sollte sich auch sehr sicher sein, daß der Schaltplan komplett ist, denn nachträglich Änderungen werden nur halb manuell übertragen und es einfach dabei Fehler zu machen. top view, position of components

Ich benutzte den orangen Layer zum zeichnen. Irgendwie erzeugten die anderen verfügbaren Farben einfach keine Ausgabe beim Drucken. Das Problem ist jedoch, das dieser orange Layer offenbar auf der Seite liegt, wo die Bauteile sind. Man muß das Ergebnis also spiegeln. Letztendlich entschloss ich mich, die wesentlichen Teile des Layout mit pcb und den Rest mit gimp zu zeichnen.

Dank shop.tuxgraphics.org brauchst du nicht mit gefährlichen Chemikalien zu hantieren oder in verschiedenen Geschäften nach den richtigen Komponenten suchen. tuxgraphics verkauft alle Teile, die man für diesen Artikel braucht.  

Der Aufbau

Beim Zusammenbau sollte man auf die Teile achten, bei denen die Polarität wichtig ist: Elektrolytkoindenstoren, Dioden, Z-Dioden, 78L05, LED und Microcontroller.

Bevor man den Microcontroller in den Sockel steckt sollte man die Stromversorgung mit einem Meßgerät testen. Falls diese nicht funktioniert bekommt man nicht nur falsche Werte, sondern zerstört möglicherweise auch den Microcontroller. Als nächstes kann man die Schaltung an den RS232 Anschluß des Linux PCs anschließen un mit dem i2c_rs232_pintest Programm die verschiedenen Signalkombinationen auf den SDA und SCL Anschlüssen zu testen.
i2c_rs232_pintest -d 1 -c 1
i2c_rs232_pintest -d 0 -c 1
i2c_rs232_pintest -d 1 -c 0
Dieses Programm setzt die Spannungspegel auf den RTS (als SCL genutzt, Option -c) und DTR (als SDA genutzt, Optio -d) an der RS232 Schnittstelle. RS232 hat Spannungen von +/- 10V. Hinter den Z-Dioden sollte man jedoch nur -0.7 für eine logische Null und +4-5V für eine logische Eins messen.

Erst wenn diese Tests bestanden sind, sollte man den Microcontroller in den Sockel setzen.  

I2C Kommunikation nutzen.

Lade das linuxI2Ctemp tar.gz File herunter (siehe Referenzen) und entpacke es. Die I2C Kommunikation ist in 2 Dateien implementiert:
i2c_avr.c -- die i2c Zustandsmaschine für den atmega8
i2c_m.c   -- das komplette i2c Protokoll für die Linuxseite.
Ich habe dem atmega8 die Slave Adresse "3" gegeben. Um den String "hello" and den atmega8 zu senden würde man folgende C Funktionen ausführen:
address_slave(3,0); // tell the slave that we will send something
i2c_tx_string("hello");
i2cstop(); // release the i2c bus

Auf der Microcontrollerseite würde man den String mit
der folgenden Funktion empfangen:
i2c_get_received_data(rec_buf);
Ganz einfach. Das lesen von Daten aus dem Microcontroller geht ähnlich.  

Wie warm ist es?

Um den Code für den Microcontroller zu kompilieren und zu laden, sind die folgenden Befehle nötig:
make
make load
Um die Programme i2c_rs232_pintest und i2ctemp_linux zu compilieren tippt man:
make i2c_rs232_pintest
make i2ctemp_linux
... oder man kann die vorkompilierten Versionen aus dem "bin" Verzeichnis benutzen.

Um Temperaturwerte zu lesen nimmt man einfach:
i2ctemp_linux
... und die Werte für Innen- und Außentemperatur werden auf den Bildschirm gedruckt. Um diese Daten über einen Webserver zur Verfügung zu stellen empfehle ich nicht das i2ctemp_linux Programm direkt vom Webserver aus laufen zu lassen, da es recht langsam ist. Besser ist es einen cron-Job zu schreiben, der regelmäßig eine html-Datei erzeugt. Ein Beispiel dafür findet sich in der README Datei des linuxI2Ctemp Paketes.  

Zusammenfassung

Das I2C Protokoll braucht sehr wenig extra Hardware und ist optimiert für kleine Datenmengen. Das ist genau das, was wir brauchen, wenn wir Meßdaten von dem Microcontroller lesen. Eine elegante Lösung.

In diesem Artikel lag der Schwerpunkt auf der Hardware. Wenn dir dieser Artikel gefallen hat, dann schreibe ich noch einen zweiten Artikel, in dem die Software beschrieben wird. Speziell wie die Analogdigitalwandlung und die Implementation des I2C Protokolls funktionieren. In diesem zweiten Artikel kommen auch das LCD Display und Celsius nach Fahrenheit Konvertierung hinzu.  

Referenzen

 

Talkback für diesen Artikel

Jeder Artikel hat seine eigene Seite für Kommentare und Rückmeldungen. Auf dieser Seite kann jeder eigene Kommentare abgeben und die Kommentare anderer Leser sehen:




Der LinuxFocus Redaktion schreiben
© Guido Socher
"some rights reserved" see linuxfocus.org/license/
http://www.LinuxFocus.org
Autoren und Übersetzer:
en --> -- : Guido Socher (homepage)
en --> de: Guido Socher (homepage)

2005-03-25, generated by lfparser version 2.52