Sie sind auf Seite 1von 6

Sensibelchen Mikrocontroller-Programmierung: Timer, Sensoren und Drehgeber Der c't-Mikrocontroller-im-LAN kann verschiedenste Sensoren abfragen, um Temperaturen, Lichtintensitten und

andere physikalische Gren zu messen. Wenige Zeilen Programmcode fragen dazu Sensoren ab oder ermglichen es, den Controller mit einem inkrementellen Drehgeber bequem zu bedienen. Das c't-Projekt MikrocontrollerimLAN aus den Artikeln [1, 2] soll nun praktische Aufgaben bernehmen und Temperaturen und andere physikalische Gren messen. Die ntigen Messschaltungen fr eine Vielzahl von Sensoren befinden sich schon auf dem B-Modul, wurden aber noch nicht detailliert besprochen. Bislang konnte der Controller (ATMega 8535) schon testweise Daten an PCs im Netzwerk bermitteln oder diese auf dem Display anzeigen. Die Benutzerfhrung auf dem LCD gestaltete sich mit den bislang verwendeten Komponenten etwas schwierig. Hier sorgt ein inkrementeller Drehgeber, wie man ihn aus vielen modernen Gerten kennt, fr Abhilfe. Bevor sich eine physikalische Gre mit einem Mikrocontroller messen lsst, muss ein geeigneter Sensor die Ursprungsgre in eine elektrisch messbare verwandeln zum Beispiel eine Temperatur in einen Widerstandswert. Im zweiten Schritt fllt ber diesem Widerstand eine Spannung ab, die dann schlielich ein Analog-DigitalUmsetzer (ADU) in einen digitalen Wert verwandelt. Andere ebenfalls nutzbare Zwischengren sind Kapazitts- (Kondensator) und Induktivittsnderungen (Spule), die man beispielsweise in einen Schwingkreis einbauen kann. Gemessen wird dann die vernderte Frequenz des Schwingers. Edelmetall Zur Temperaturmessung bieten sich Messwiderstnde wie der PT100 an. Diese sind in internationalen (IEC 751 und EN 60751) und einer deutschen Norm (DIN 60751) genau spezifiziert. Als Material kommt Platin (Pt) zum Einsatz, das in weiten Bereichen seinen Widerstand annhernd linear mit der Temperatur verndert. Die Zahl hinter dem Elementzeichen gibt den Widerstandswert (100 [OMEGA]) bei 0 C an. Da die Widerstandsnderung jedoch nicht ber den gesamten Temperaturbereich konstant ist, muss man fr eine korrekte Umrechnung der gemessenen Ohm-Werte in Temperaturen zwei Abschnitte getrennt betrachten. Zwischen 0 C und 180 C gilt folgender Zusammenhang: R(T) = R0(1 + AT + BT2) A=3,908310-3C-1; B=-5,77510-7 C-2 im Bereich von -200 C bis 0 C kommt noch ein Term dritter Potenz hinzu: R(T) = R0(1 + AT + BT2 + CT3) C=-4,18310-12C-3 Das B-Modul besitzt zwei komplette analoge Messschaltungen fr Temperatursensoren, die versuchen, mglichst viele Streinflsse zu vermeiden. Dazu betreibt es den Sensor an einer Konstantstromquelle, die ungefhr 1 mA durch den Sensor flieen lsst. Diese Aufgabe bernimmt etwas zweckentfremdet der einstellbare Spannungsregler LM317L (IC6). Er regelt seine Ausgangsspannung so, dass zwischen dem Justiereingang ADJ und dem Ausgang VO immer 1,25 V anliegen. Da der Widerstand R1 mit 1,3 k[OMEGA] deutlich grer als der PT100 ist, fliet durch beide nherungsweise konstant 1 mA. R38 dient nur dazu, den Spannungsregler ein wenig zu belasten, damit die Regelung einwandfrei arbeitet. Stufen zum Erfolg Nach dem Ohmschen Gesetz(U = RI) fllt bei einem Messstrom von 1 mA am PT100 bei 0 C 100 mV Spannung ab, bei 100 C entsp rechend 137,6 mV. Diese relativ kleinen Spannungswerte sind empfindlich gegenber Strungen oder Belastungen, wie sie eine direkte Analog-nach-Digital-Umsetung mit sich bringen wrde. Daher entkoppelt zunchst ein Verstrker mit dem Verstrkungsfaktor eins (IC4A) den Eingang von der folgenden Schaltung. Archiv-Suche Newsletter News mobil RSS

weitere Angebote Mikrocontroller-Programmierung: Timer, Sensoren und Drehgeber | c't Seite 1 von 6 http://www.heise.de/ct/artikel/Sensibelchen-289608.html 23.04.2012 Der PT100-Sensor ist ber eine Dreileiterschaltung mit dem Eingang verbunden, bei der die Adern erst am Messpunkt miteinander verbunden sind. So fliet auf der Signalleitung nur ein sehr kleiner Strom und der Leitungswiderstand beeinflusst die Messung kaum. Diese subtrahiert zunchst den Offset von 100 mV, damit der Messbereich bei 0 C beginnt. Dazu erzeugt der Spannungsteiler R2/R3 eine Spannung von ebenfalls 100 mV, die IC4C wieder entkoppelt und IC4B als Subtraktor vom Messsignal abzieht. Zuletzt verstrkt IC4D das Signal so weit, dass es den Messbereich des A/DUmsetzer s voll ausnutzt. Die Verstrkung kann man mit dem Spindelpotentiometer TR1 relativ genau einstellen. Mchte man den Messbereich verschieben, um beispielsweise Temperaturen unter 0 Grad zu messen, muss man die Offset-Spannung (Spannungsteiler R2/R3) anpassen. Die Schaltung ist ziemlich universell - die Subtraktionsstufe (R2, R3, IC4C) verschiebt die Eingangsspannung um beliebige Offsets und legt damit das untere Ende des Messbereiches fest, der nachgeschaltete Verstrker (TR1, IC4D) das obere Ende. So lassen sich auch alle anderen Sensoren anschlieen, die eine Ausgangsspannung oder eine Widerstandsnderung erzeugen. Verwandlungsknstler Bevor der Mikrocontroller den Messwert weiter verarbeiten kann, muss er das analoge Signal in digitaler Form erhalten. Dazu besitzt der ATMega 8535 acht Eingnge (PA0 bis PA7), die ber einen Multiplexer an einem einzigen 10-Bit-D/AUmset zer hngen. Dieser teilt den Eingangsbereich durch sukzessive Approximation in 1024 (210) gleich groe Stufen ein. Als Referenzspannung und Obergrenze des Messbereichs dient entweder die analoge Versorgungsspannung (im vorgestellten Modul AVCC mit 5 Volt), der Eingang AREF oder eine interne Referenzspannung von 2,56 Volt. Welche der drei Varianten zum Einsatz kommt, legt die Firmware ber die obersten beiden Bits im ADMUX-Register fest. Um die beiden PT100-Sensoren auszuwerten, nutzt unser Beispiel-code die interne Referenz und richtet die zehn Daten-Bits rechtsbndig im 16-Bit-Ergebnis aus (ADLAR=0): #include <avr/io.h> ... ADMUX=(1<<REFS1)+(1<<REFS0)+(0<<ADLAR); Die ADMUX-Bits null bis zwei whlen den Eingang aus, der mit dem Umsetzer verbunden werden soll. Die brigen Bits (drei und vier) sind nur in speziellen Betriebsarten ntig und aktivieren unter anderem die differenziellen Eingnge und den internen Verstrker. Genaue Informationen dazu liefert das Datenblatt (SoftLink). Beim Eintragen der gewnschten Kanalnummern in die zustndigen Bits mssen alle anderen unverndert bleiben, was man durch das logische Oder (|Operator) und die Maskierung (&-Operator) erreicht: ADMUX = ADMUX | (channel &; 0x07); Die Verknpfung einzelner Bits kann man in C auch krzer schreiben, wie die folgenden Zeilen mit dem logischen Und-Gleich (&=-Operator) zeigen. Sie schalten den ausgewhlten Kanal als Input-Pin und deaktivieren den internen PullupWiderstand, der nur fr die Nutzung als digitaler Eingang bentigt wird: DDRA &= ~(1<<(channel & 0x07)); PORTA &= ~(1<<(channel & 0x07)); Fr die Approximation eines Signals bentigt der Umsetzer ein Taktsignal, das ungefhr zehn- bis fnfzehnmal hher liegt als die erwnschte Abtastrate. Diese sollte, sofern die maximale Auflsung erwnscht ist, 15 kHz nicht berschreiten.

Daraus ergibt sich ein sinnvoller Umsetzertakt von maximal 200 kHz, den ein Teil er aus dem Chiptakt (14,7456 MHz) erzeugt. Wir haben uns fr ein Teilerverhltnis von 128 (die drei untersten Bits im Register ADCSRA) beziehungsweise eine Frequenz von 115 kHz entschieden. ADCSRA=(1<<ADPS2)+(1<<ADPS1)+(1<<ADPS0); Das Setzen zweier weiterer Bits leitet die Konvertierung schlielich ein: ADCSRA|=(1<<ADEN)+(1<<ADSC); Sobald das Ergebnis bereit- liegt, steht das ADSC-Flag im ADCSRA-Register wieder auf null. Darauf wartet die Firmware in einer Warteschleife und setzt danach das Ergebnis aus den zwei 8-Bit-Registern in einer 16-Bit-Variablen (adc) zusammen: while ((ADCSRA&(1<<ADSC))!=0){} adc = ADCL + (ADCH<<8); Mikrocontroller-Programmierung: Timer, Sensoren und Drehgeber | c't Seite 2 von 6 Der Magnetfeldsensor KMZ10B besitzt eine interne Messbrcke und kann direkt an einen der analogen Differenzeingnge des ATMega angeschlossen werden. Um aus dem ADC-Wert eine Temperatur zu berechnen, msste man eigentlich die weiter oben gennanten Formeln genau auflsen. Da die Faktoren B und C aber relativ klein sind und im Temperaturbereich zwischen 0 und 100 C daher nur wenig ins Gewicht fallen, darf man sie im Regelfall vernachlssigen. Es ergibt sich dann eine einfache Geradengleichung: T = dadc + e, deren Koeffizienten d und e sich anhand von zwei Sttzstellen bestimmen lassen. Dazu misst man zwei mglichst weit auseinander liegende Temperaturen (zum Beispiel Zimmer- und Heizungstemperatur) jeweils mit dem PT100 (adc) und mit einem normalen Thermometer (T). Die Faktoren errechnen sich dann wie folgt: d = (T1-T2)/(adc1-a dc2) und e = T1-dadc. Im Beispiel-Quelltext (Soft-Link) kann man am Anfang der Datei adc.c die zwei Messpaare eintragen und die Temperaturen mit der Funktion pt100_read(kanal) in Hundertstel-Grad auslesen. Genau wie die Temperaturfhler kann man auch alle anderen Sensoren, ber denen eine Spannung zwischen 0 und 2,56 V abfllt, auslesen. Ein Licht-Sensor (LDR) ndert seinen Widerstandswert zwischen 100 [OMEGA] und 20 k[OMEGA] und so reicht ein einfacher Spannungsteiler (R19) aus, um ihn direkt an den ADU anzuschlieen (P9 auf dem B-Modul). Fr empfindlichere Sensoren bietet sich eine Anpassung der oben beschriebenen PT100-Schaltung an. Wer Sensoren mit integrierter Messbrcke wie einen Magnetfeldsensor (zum Beispiel KMZ10B von Philips) verwenden will, kann einen der Differenz-Eingnge mit internem Verstrker des ATMega nutzen. 1, 2, 3 ... Unterbrechung Fr regelmige Messungen lassen sich die Sensoren in einer Endlosschleife stndig abfragen, aber damit blockiert man den Mikrocontroller vllig. Viel eleganter ist es, einen der eingebauten Timer zu benutzen. Diese generieren in einstellbaren Intervallen Interrupt-Signale. Der Prozessor unterbricht daraufhin seine aktuelle Arbeit und verzweigt in die zugehrige InterruptService-Routine (ISR). Diese liest die Sensoren aus, speichert das Ergebnis ab und kehrt dann zum eigentlichen Code zurck. Aus dem Chiptakt von 14 MHz generiert der Teiler vier verschiedene Takte, die fr

die Timer als Referenz zur Verfgung stehen. Der ATMega8535 bringt gleich drei solcher Timer mit (zwei mit 8- und einen mit 1 6Bit-Zhler), von denen jeder mehrere Interrupts auslsen kann. Wir betrachten hier einen der 8-Bit-Timer, da er fr das periodische Auslesen der Sensoren ausreicht. Der Timer zhlt ein 8-Bit-Register (TCNT0) mit jedem Clock-Signal um eins hoch, vergleicht es dann mit dem Compare-Register (OCR0) und lst wenn ntig einen Interrupt aus (OCF0 bei OCR0 gleich TCNT0, TOV0 bei Zhlerberlauf). Wie schnell dies geschieht, entscheidet der verwendete Zhlertakt. Ein Vorteiler stellt verschiedene Frequenzen zur Verfgung, die er durch Teilen au s dem Systemtakt (14,7456 MHz) erzeugt. Im Timer-Control-Register (TCCR0) legen drei Bits (CS00 bis CS01) fest, welchen Takt der Zhler verwendet (Tabelle im Datenblatt). Temperaturen ndern sich vergleichsweise langsam - eine Messung alle 3 ms reicht fr viele Zwecke aus. Der Acht-Bit-Timer kann nur bis 255 zhlen und so fllt die Wahl auf den hchstmglichen Teiler (1024) und somit einen Takt von 14,4 kHz. Der Vergleichswert ergibt sich dann zu (14,400 kHz x 3 ms -1 = 42): Mikrocontroller-Programmierung: Timer, Sensoren und Drehgeber | c't Seite 3 von 6 http://www.heise.de/ct/artikel/Sensibelchen-289608.html 23.04.2012 Ein Drehgeber erzeugt einen Graycode, bei dem zwei aufeinander folgende Werte sich immer in genau einem Bit unterscheiden. Die Drehrichtung liest man dann aus der Zustandstabelle aus. Das B-Modul besitzt schon einen Anschluss fr den Drehgeber. Vertauscht man Pin eins und zwei, dann ndert sich auch die Zhlrichtung der Geberauswertung. #define XTAL 14745600 #define clock 333 // 3 ms --> 333 Hz ... TCCR0 = (1<<CS00) | (1<<CS02) | (1<<WGM01); OCR0 = (XTAL/1024/clock)-1; Das WGM01-Bit sorgt dafr, dass der Zhler nach jedem Erreichen des Vergleichswertes wieder bei null anfngt zu zhlen. Den Anfangswert schreibt man direkt in das Timer-Register und aktiviert zuletzt die Interrupts: TCNT0 = 0; TIMSK |= (1<<OCIE0); sei(); Das OCIE0-Bit im TIMSK-Register schaltet den Vergleichs-Interrupt ein und das Makro sei(), das in avr/interrupt.h definiert ist, aktiviert systemweit alle Int errupts. Die Interrupt-Service-Routine unterscheidet sich dank weiterer Makros aus avr/signal.h kaum von einer gewhnlichen C-Funktion. Sie beginnt mit dem Schlsselwort SIGNAL, gefolgt vom Namen des zu behandelnden Interrupts: SIGNAL (SIG_OUTPUT_COMPARE0){ Temp[0]=read_adc(0); Temp[1]=read_adc(1); } Whrend der Ausfhrung der Funktion sind alle anderen Interrupts blockiert. Wer das nicht will, nutzt statt SIGNAL das Makro INTERRUPT, muss dann aber selbst dafr sorgen, dass sich Aufrufe nicht gegenseitig berlappen. Grundstzlich gilt, dass ein Programm mglichst wenig Zeit in ISRs verbringen soll. Aufwendige Operationen gehren dort nicht hin, daher rechnet auch erst das Hauptprogramm die Sensorwerte in Grad Celsius um. Rechts - Links In der regelmig aufgerufenen ISR kann man neben Sensoren auch Eingabegerte

wie einen Drehimpulsgeber, kurz Drehgeber, auslesen. Da sich dessen Zustand vergleichsweise langsam ndert, klappt dieses einfache Polling-Verfahren. Bei schnell wechselnden Eingangssignalen bieten sich hingegen die Eingnge an, die bei jeder Pegelnderung einen eigenen Interrupt auslsen. Handelsbliche inkrementelle Drehgeber erzeugen beim Drehen an jedem ihrer zwei Ausgnge ein Rechtecksignal. Beide sind um 90 Grad zueinander phasenverschoben (siehe Grafik). So entsteht ei n 2-Bit-Code, bei dem sich immer nur ein Bit auf einmal ndert (Graycode). Die Drehrichtung kann man dann aus einer Zustandstabelle ablesen. Einen Anschlag zur Winkelbegrenzung, wie bei Potentiometern blich, gibt es nicht. Die aktuelle Position des Gebers kann folglich nur inkrementell durch kontinuierliches Mitrechnen ermittelt werden. Als Zusatzfunktion besitzen viele Drehgeber noch einen Taster, mit dem man beispielsweise in einem Men die Auswahl besttigen kann. Dieser wird wie jeder andere Taster auch ausgelesen [2]. Vor der Auswertung des Graycodes werden die drei Ports (2xGeber und 1xTaster) als Eingnge geschaltet und ihre internen PullupWiderstnde aktiviert. Eine logische Eins am Port-Pin entspricht damit einem geffneten, eine Null dem geschlossenen Schalter. #define DREH_A 0x10 #define DREH_B 0x20 #define DREH_TAST 0x40 DDRC &= ~ (DREH_A + DREH_B + DREH_TAST) PORTC |= (DREH_A + DREH_B + DREH_TAST); Zum Abfragen des Drehgebers muss man der Timer-ISR nur einen Aufruf der im folgenden erklrten Funktion dreh_isr() hinzufgen. Der von uns verwendete Drehgeber erzeugt pro ganzer Drehung 60 Zustandsnderungen (zwei pro Rastung). Fr die Abtastfrequenz von 333 Hz bedeutet dies: Alles unter zweieinhalb Umdrehungen pro Sekunde wird garantiert fehlerfrei abgetastet. Wem das nicht reicht, der kann den Wert im OCR0-Register herabsetzen. Die Abfrageroutine liest bei jedem Aufruf den aktuellen Zustand der beiden Geber-Pins ein und speichert s ie in derselben Variable (Bits zwei und drei), in der auch die des letzten Aufrufes stehen (Bits null und eins): void dreh_isr(void){ graycode >= 2; Mikrocontroller-Programmierung: Timer, Sensoren und Drehgeber | c't Sei if( (PINC & DREH_A) == DREH_A ) graycode |= 0x04; if( (PINC & DREH_B) == DREH_B ) graycode |= 0x08; drehgeber += graytab[graycode]; ... } Dadurch entsteht ein Code, der fr jede der mglichen Zustandsnderungen einen eigenen Wert enthlt. Eine einfache Tabelle (graytab[]) mit 16 Werten verbindet jeden Zustand mit einem Wert fr die Positionsnderung (+1 fr Rechtsdrehung, -1 fr eine Linksdrehung). const int8_t graytab[] = { 0,-1,1,0, 1,0,0,-1,

-1,0,0,+1, 0,1,-1,0 }; Diesen kumuliert die globale Variable drehgeber, die das Hauptprogramm auslesen kann. Es muss dabei nur beachten, dass je nach Bauform der Geber pro Rastung mehrere Zhlerstnde durchlaufen kann. Unser Exemplar zhlt pro Rastung um zwei weiter, weswegen man seine Funktion nicht vollstndig mit einem Digital-Multimeter nachprfen kann. Die oben beschriebene Funktion eignet sich auch, um den Taster des Gebers mit auszulesen (Soft-Link). An - Aus - An Der Atmega kann nicht nur Signale aufnehmen, sondern sie auch mit seinen I/O-Pin s erzeugen. Jeder Port-Pin kann bis zu 20 mA in beide Richtungen (nach High und nach Low) treiben. Allerdings ist der Gesamtstrom pro Port auf rund 100 mA und fr den kompletten Chip auf 200 mA begrenzt. Die 20 mA eines Pins sind gut geeignet, um LEDs anzusteuern - fr Relais, Motoren oder Glhbirnen reicht das aber nicht aus. Zudem sind die Ausgnge nicht potenzialfrei und knnen nur Gerte ansteuern, die mit demselben Massepotenzial arbeiten. Bentigt man nur mehr Strom oder Spannung bei gleichem Bezugspotenzial, so reicht ein Transistor am Ausgang. Der Transistor muss sowohl zum gewnschten Laststrom als auch zur Betriebsspannung des Verbrauchers (V+) passen. Die Sperrspannung muss ber der Betriebsspannung liegen. Der maximale Kollektorstrom richtet sich nach dem Innenwiderstand der Last. Um diese Schaltung fr mehrere Ausgnge nicht jeweils einzeln aufbauen zu mssen, gibt es ICs mit Transistor-Arrays (zum Beispiel ULN2803, Ausgangsspannung bis 50 V). Sie enthalten sieben oder acht einzelne Transistoren mit zusammengeschalteten Emittern und integrierten Basiswiderstnden. Fr induktive Lasten halten sie noch eine Freilaufdiode fr jeden Ausgang bereit. Vermittler Potenzialfreie Ausgnge erhlt man zum Beispiel mit einem kleinen Relais, das ein Transistor treibt. Dabei schtzt eine Diode (1N4148) in Gegenrichtung (Kathode an Betriebsspannung) parallel zur Relaisspule den Transistor vor Spannungsspitzen. Diese entstehen in der Spule beim Abschalten der Relaisspannung. Netzspannung sollte man mit dem Relais aber keinesfalls schalten, da fr das 230-Volt-Netz zahlreiche Sicherheitsbestimmungen zu beachten sind. Die Ausgnge des Controllers liefern bis zu 20 mA Strom. Reicht dies nicht aus oder ist eine hhere Schaltspannung ntig, hilft ein NPNTransistor mit Basiswiderstand weiter. Deutlich schneller und langlebiger als Relais sind Optokoppler. Sie bestehen aus einer Leuchtdiode und einem Fototransistor in einem lichtdichten Gehuse. Die Leuchtdiode lsst sich mit einem Vorwiderstand direkt von einem Port-Pin des Atmega ansteuern, der Fototransistor arbeitet als normaler Schalttransistor im Zielsystem. Ausblick Um die Messwerte von den einzelnen Sensoren komfortabel auszuwerten und auch die Stellgren fr die Ausgnge zu verndern, bietet sich der Webserver des AModuls an. Codebeispiele dazu gab es bereits im zweiten Teil des Projektes [2]. Das B-Modul bietet genug Raum fr eigene Experimente, auch mit Sensoren, die ihre Kapazitt oder Induktivitt ndern. Sie erfordern aber deutlich mehr Mikrocontroller-Programmierung: Timer, Sensoren und Drehgeber | c't Seite 5 von 6 http://www.heise.de/ct/artikel/Sensibelchen-289608.html 23.04.2012 Kommentieren