Rudi's Homepage - AVR Projekte

EnglishDeutsch

myAVR Board

Beschreibung:

Zielsetzung

Dieser Abschnitt soll demonstrieren, wie man die mit 12 Euro recht preiswerte myAVR-Experimentierschaltung mit ausschließlich freien Programmen nutzen kann.

Das myAVR-Experimentiersystem.
Das myAVR-Experimentiersystem.
Das Experimentiersystem basiert auf einen ATmega8, der über ein SP12-kompatibles ISP-Programmiersystem über den Parallelport programmiert werden kann. Auf der Platine sind 3 Leuchtdioden, 2 Schalter und 2 Potentiometer und ein Summer verfügbar. Desweiteren ist die serielle Schnittstelle des ATmega über einen MAX232-Pegelwandler angeschlossen.

So schön die hardwaremäßige Ausstattung ist, so beschränkt ist man programmseitig. Auf der beigelegten CD findet sich nur die Demonstrationsversion einer an sich nicht schlechten Entwicklungsumgebung, die auch unter Wine keine Zicken macht. Nur ist das eben eine Demonstrationsversion, deren Laufzeit auf 30 Tage begrenzt ist und in dieser Zeit auch nur 30 Minuten genutzt werden kann.

Assembler-Programmierung

Zuerst soll gezeigt werden, wie man mit VM-Lab Assemblerprogramme schreiben, übersetzen und simulieren kann und schließlich das Programm mit avrdude auf den Mikrocontroller laden kann. Nach dem Starten sollte VM-Lab folgendes Bild zeigen:

Startbildschirm von VMLab
Startbildschirm von VMLab
Zuerst legt man mit Projekt->Neu ein neues Projekt an. In dem erscheinenden Dialog muß neben dem Projektnamen und dem Projektarbeitsverzeichnis der Name einer Assemblerquelltextdatei angegeben werden. Nennen wir sie erst einmal blinken.asm. Zudem muß noch der Mikrocontroller eingegeben werden - in unserem Fall der ATmega8.
Anlegen eines neuen Projekts
Anlegen eines neuen Projekts
Nun bearbeiten wir die Projektkonfigurationsdatei. Dort muß zum einen die Taktfrequenz auf 3,9894 MHz geändert werden, zum anderen kann hier zusätzliche angeschlossene Hardware beschrieben werden. Zum Anfang soll nur eine LED blinken. Deshalb fügen wir mit den folgenden Zeilen noch eine LED hinzu, die an Port C Anschluß 0 über einen Widerstand angeschlossen ist, allerdings im Gegensatz zum Experimentierboard gegen +Us und nicht gegen Masse:
			R1  PC0 vb1 1.2k
			D1  VDD vb1  ; x: Panel LEDs 1 - 8
			
Die Vorlagen für die Bauelemente bekommt man übrigens aus dem Components-Menü von VM-Lab. Ausgeschrieben würden die Anweisungen wie folgt lauten: "Widerstand R1 von PC0 nach Knoten vb1 (selbst definiert). LED1 von +Us nach Knoten vb1". Abschließend wird noch die Anweisung eingefügt, die Spannung an PC0 über die Zeit zu plotten:
			.plot v(PC0)
			
Die Projektkonfigurationsdatei sollte dann wie folgt aussehen:
Die Konfigurationsdatei.
Die Konfigurationsdatei.
Nun können wir uns dem Assembler-Quelltext zuwenden. Der Assemblercode beginnt mit der Definition von Registervariablen und einem Makro für den benutzten Portanschluß. Danach kommt die "Interruptvektortabelle", welche sicherheitshalber für jeden Interrupt sofort einen Rücksprung anordnet. In der Initialisierungssektion kommt für Leute wie mich, die vorher nur Tinys mit 3-Ebenen-Hardwarestack programmiert haben, etwas neues - die Initialisierung des Stackpointers. Dieser wird an das obere Ende des RAM's gelegt, da der Stack nach unten wächst. Danach kommt eine Endlosschleife, welche abwechselnd die LED ein- und ausschaltet und dazwischen durch den Aufruf einer Warteroutine etwas pausiert.

Wenn das Übersetzen des Quelltextes mit F9 bzw. "Project->Build" ohne Probleme absolviert wurde, kann die Simulation gestartet werden. Vorher kann man sich mit "View->Scope" und "View->Control Panel" das Oszilloskop und die Anzeige/Steuereinheit auf den Bildschirm holen. Das Ergebnis sollte dann so aussehen:

VM-Lab
VM-Lab

Programmieren mit AVR-Dude

Nun soll ja nicht nur die simulierte LED blinken, sondern auch die echte LED. Zu diesem Zweck habe ich AVR-Dude genommen. Um das Brennen zu vereinfachen, habe ich folgendes Makefile geschrieben, welches mit "make install" die Hex-Datei brennt.

Brennen mit AVR-Dude und Make.
Brennen mit AVR-Dude und Make.
Vor der ersten Verwendung sollte man mit "make write_fuse" auch das Konfigurationswort schreiben. Wenn nun noch mit einem Stück Draht Port C 0 mit einer LED verbunden wird, so sollte diese freudig blinken.

Senden über die serielle Schnittstelle und A/D-Wandlung

Mit diesem Projekt kann man die Sendefunktion der seriellen Schnittstelle und den A/D-Wandler prüfen. Das Programm läßt die A/D-Wandlung im "Einzelschuß"-Modus laufen. Der Vorgang wird durch die Beendigung eines Datentransfers der seriellen Schnittstelle angestoßen. Das ist sinnvoller, da der A/D-Wandler mit einer Abtastrate von mindestens 50 kHz laufen soll - zu schnell für die serielle Schnittstelle. Mit dem freiem Matlab-Clone "Octave" kann man die Abtastdaten recht einfach einlesen und darstellen:

			fid=fopen("/dev/ttyS0","rb"); x=fread(fid,10240,"uchar"); fclose(fid); plot(x)
			
Das Ergebnis (Eingangsspannung kam vom Potentiometer) sah dann so aus:
Darstellen der Abtastwerte unter Octave
Darstellen der Abtastwerte unter Octave

Empfangen über die serielle Schnittstelle und D/A-Wandlung (PWM)

Mit diesem Projekt kann man die Empfangsfunktion der seriellen Schnittstelle und die LED's prüfen. Zum Betrieb des Programms muß PortB Anschluß 3 mit einer LED verbunden werden. Über ein Terminalprogramm (Einstellung: 9600 baud, 8N1) kann nun mit den Tasten +,-,0-9 und Space die Helligkeit der LED variiert werden.


IR-SoftUART

Beschreibung:

Zielsetzung

Ziel dieses Projektes war die Übertragung von perjodisch aufgezeichneten Abtastwerten eines Analogeingangs in Form eines ASK-modulierten NRZ-Binärsignals. Empfangen werden sollte das Signal durch einen IR-Empfänger TSOP1738, an dem über einen Max232 Pegelwandler die serielle Schnittstelle eines PC's angeschlossen werden kann. Als Ausgangsbasis wurde der ATtiny15 gewählt, da er sowohl Analog/Digitalwandler wie auch die nötigen Zeitgeber besitzt. Wie sich herausstellte, reichte der interne RC-Oszillator des ATtiny15 vollkommen aus. Da neben dem 8-poligen Chips nur ein Widerstand und eine IR-Sendediode benötigt werden, kann der Sender sehr kompakt aufgebaut werden.

Schaltungsaufbau

Der Schaltplan ist im folgenden Bild dargestellt (Analogeingang: PB2)

Aufbau der Schaltung.
Aufbau der Schaltung.
Aufgebaut wurde die Schaltung testweise auf einem Experimentierbrett.
Aufbau der Schaltung.
Aufbau der Schaltung.
Für eine wirkliche Realisierung sollte die Sendediode gegen +Us statt gegen Masse geschaltet werden (im Program dann aber anpassen!).

Das Program

Der Quelltext des Programms findet sich hier, zusammen mit einem Makefile zur Übersetzung und Programmierung über einen SP12-Programmieradapter. Das Programm nutzt den Zeitgeber 1 zur Erzeugung der 38 kHz Modulationsfrequenz und den Zeitgeber 0 zur Erzeugung des Bittaktes. Der Abtasttakt wird durch den heruntergeteilten A/D-Konvertierungszyklus erzielt. Dazu wird im A/D-Wandlerinterrupthandler ein Zählregister heruntergezählt und nur beim Nulldurchgang eine Datenübertragung angestoßen. So wird eine Abtastrate von rund 1.6 Herz erzielt. Die Datenübertragungsroutine selbst lädt den Bitzähler auf 10 Bit (8 Datenbits + Startbit + Stopbit), aktiviert den Modulator für das Startbit und startet den Zeitgeber 0. Bei jeden Überlauf des Zähler/Zeitgeber 0 wird in der entsprechenden Interruptserviceroutine zuerst einmal der Vorladewert für den Zeitgeber 0 erneuert, damit dieser in einer Bitdauer wieder "zuschlägt". Danach wird geprüft ob der Anfang oder das Ende vom Stopbit an der Reihe ist. Im letzteren Fall wird der Zeitgeber 0 abgestellt, da die Übertragung beendet ist, im ersteren Fall der den Modulator entsprechende Zeitgeber 1. Für die Datenbits wird der Modulator je nach dem LSB des Datenbytes ein- oder ausgeschaltet und das Datenwort bitweise nach rechts geschoben. Wenn das Programm auf eine andere Baudrate als 1200 umgeschrieben wird, darauf achten, daß CPU-Takt/(Baudrate*Vorteiler Zähler0) < 255 ist!


Remote Control/Fernsteuerung

Beschreibung:

Zielsetzung

Ziel dieses Projekts war die Steuerung der Helligkeit einer LED durch eine Infrarot-Fernbedienung, realisiert auf einem ATtiny15. Dieser bietet die erforderliche Pulsweitenmodulation und hat die nötige Anzahl an Zeitgebern. Das gesamte Paket mit VMlab-Projektdateien und Makefile zum Installieren/Kalibrieren findet sich hier. Ein Kurzfilm der Schaltung in Aktion findet sich hier.

Analyse des Fernsteuerungssignals

Zur Lösung dieser Aufgabe muß man erst einmal verstehen, wie die Fernsteuerung die Information codiert. Zu diesem Zweck habe ich das Signal erst einmal am PC über die Soundkarte aufgezeichnet. Dazu habe ich einen TSOP1738 (36 geht auch) gemäß dem folgenden Bild auf einem Experimentierbrett aufgebaut und das Ausgangssignal an den Mikrofoneingang der Soundkarte angeschlossen.

Testaufbau Signalanalyse.
Testaufbau Signalanalyse.
Anschließend habe ich das Signal mit der höchsten verfügbaren Abtastrate mit Audacity aufgenommen. Das Resultat sah so aus:
Das Fernsteuersignal, invertiert.
Das Fernsteuersignal, invertiert.
Da der TSOP das Signal invertiert (ohne aktives Signal führt sein Ausgang H-Pegel), der angezeigte Ruhepegel aber negativ ist, liegt das Signal in invertierter Form vor. Diesen Fehler könnte man mit Audacity schnell korrigieren. Man erkennt schnell die Art der Modulation; eine logische "0" wird durch einen Impuls von 1 ms Breite gebildet, dem eine Pause von 1 ms folgt, bei einer logischen "1" ist die Pause 2 ms lang. Es handelt sich somit um eine "Pausenmodulation". Ein Vergleich mit der Dokumentation von Fernsteuerungsprotokollen ergab, das es sich um das Sharp-Protokoll handelt (was laut Hersteller ja auch zu erwarten war). Somit wurde auch klar, daß die ersten 5 Bit die Geräteadresse angeben (bei meiner Fernsteuerung war es die 18) und die folgenden 8 Bit ein Kommando darstellten. Bei mir war z.B. "lauter" die 20, "leiser" die 21 usw. Zusätzlich wurde bei gedrückt gehaltener Taste (Dauerkommando) das Kommandobyte abwechselnd bitinvertiert gesendet.

Modellierung mit VM-Lab

VMlab bietet mit der NRZ-Signalquelle eine hervorragende Möglichkeit, um solche Signale zu modellieren. Damit wird die Entwicklung und besonders die Fehlersuche dramatisch vereinfacht. Die NRZ-Quelle legt NRZ-codierte Pulsfolgen auf die Tasten der Tastatur im Kontrollzentrum (dort, wo auch die Schieber und die Leuchtdioden sind). Zur Modellierung wird jedes "0"-Bit der Fernsteuerungssequenz in eine "01"-Folge umgewandelt, jedes "1"-Bit in eine "011"-Folge (TSOP invertiert!). Die Umrechnung habe ich mit dem folgendem Octave-Script automatisiert:

			function [key]=generiereKey(adresse,kommando)
 				bits = {"01","011"};
  				key = "";
  				for k=0:4
    				key=sprintf("%s%s",key,bits(1+bitand(adresse,1)));
    				adresse=bitshift(adresse,-1);
  				end;
  				for k=0:7
    				key=sprintf("%s%s",key,bits(1+bitand(kommando,1)));
    				kommando=bitshift(kommando,-1);
  				end;
  				key=sprintf("%s%s%s01",key,bits(2),bits(1));
			end;
			
Diese Funktion fügt auch gleich die benötigten Endebits hinzu, so daß die erzeugte Zeichenkette gleich in VMlab weiterverwendet werden kann:
			P1  NRZ(1m) PB2 ; 1 ms
				+ KEY_0 "0101101010110101011010110101010110101" ; "lauter" (Adr. 18, Kommando 20)
				+ KEY_1 "01011010101101101011010110101010110101" ; "leiser" (Adr. 18, Kommando 21)
				+ KEY_F "1"
			
Wichtig ist, daß die Pulsbreite auf 1 ms gestellt ist und das mit der Taste "F" das Ausgangssignal der NRZ-Quelle von Tri-State auf logisch "1" gezogen werden kann. Das folgende Bild zeigt die Übereinstimmung zwischen dem simuliertem und dem gemessenem Signal (nach Invertierung).
Vergleich Simulation/reales Signal.
Vergleich Simulation/reales Signal.

Grundidee

Die Grundidee ist recht einfach. Der Tiny mißt die Zeit zwischen zwei fallenden Flanken und unterscheidet so "0"- und "1"-Bits. Die Zeitmessung wird mit dem Zeitgeber 0 durchgeführt, die Flankenerkennung mit dem INT0-Interrupt. Deshalb muß der TSOP and PB2 angeschlossen werden. An PB1/OC1A wird die Leuchtdiode gegen +5V mit Vorwiderstand angeschlossen, da dies der Ausgang für das PWM-Signal ist. Mehr Bauelemente werden bis auf die spannungsstabilisierte Stromversorgung nicht benötigt, da der Tiny mit dem internen 1.6 MHz-Oszillator läuft.

Aufbau der Schaltung.
Aufbau der Schaltung.
Der Testaufbau.
Der Testaufbau.

Umsetzung

Das Programm beginnt mit der Interrupt-Vektortabelle. Genutzt werden der INT0-Interrupt zur Flankenerkennung und der Überlaufinterrupt von Zeitgeber 0, um das System nach einem Störimpuls zurückzusetzen. Nach dem Reset beginnt der Initialisierungsteil. Zuerst wird das Kalibrierungsbyte geschrieben, damit der RC-Oszillator wirklich mit 1.6 MHz läuft. Diesen Wert muß man für jeden Mikrocontroller mit "make read_cal" auslesen. Danach werden einige Arbeitsregister initialisiert und PB1 als Ausgang geschaltet. Mit der Befehlssequenz

			ldi	temp,255
			out	OCR1B,temp
			; schnelle PWM, invertiert, 25 MHz
			ldi	temp,((1<<PWM1)+(1<<COM1A1)+(1<<COM1A0)+1) 
			out	TCCR1,temp
			clr	helligkeit
			out 	OCR1A,helligkeit
			
wird die PWM zur Steuerung der LED eingestellt. Die Parameter sind: Wertebereich 0-255 (OCR1B), PWM-Modus, PWM invertiert und Takt = CPU-Takt*16 (TCCR1) sowie PWM-Vorgabewert in der Registervariablen "helligkeit". Die folgende Sequenz schaltet den Schlafmodus frei und stellt ihn auf "Idle". Zudem wird die Interruptquelle für INT0 auf eine fallende Flanke gesetzt:
			; erlaube Schlafen, Schlafmodus="idle", INT0 auf fallender Flanke
			ldi	temp,(1<<SE)+(1<<ISC01)
			out	MCUCR,temp
			
Danach werden noch die Interrupts INT0 und Zeitgeber 0 - Überlauf freigeschaltet, daß globale Interruptmaskierungsbit freigeschaltet und der Mikrocontroller in eine Endlosschleife geschickt, wo er schlafend auf eine fallende Flanke warten soll:
			ldi	temp,(1<<INT0) ; schalte INT0 frei
			out	GIMSK,temp
			ldi	temp,(1<<TOIE0) ; T0 Überlaufinterrupt
			out	TIMSK,temp		
   			sei	; erlaube Unterbrechungen
		forever:
			sleep
			rjmp forever
			
Der wohl wichtigste Teil findet in der INT0-Serviceroutine "neuesBit" statt. Dort wird zuerst der aktuelle Zählerstand und damit der Abstand der letzten fallenden Flanken gesichert. Danach wird geprüft, ob überhaupt ein stabiler "0"-Pegel anlag oder ob es sich um eine kurzzeitige Störung handelte. Wenn dem nicht so war, wird je nach dem Bitindex verfahren. Für das "0. Bit" (Beginn einer Übertragung), wird der Zeitgeber 0 überhaupt gestartet und die Datenvariablen zurückgesetzt. Ansonsten wird nach dem 5. Bit die Adresse und am Ende der Gesamtübertragung (nach 5+8+2=15 Bits) das Kommandowort kopiert, die Übertragung beendet und die Auswertungsroutine "auswertung" aufgerufen. Für die Adreß- und Kommandobits wird zudem noch die Bitwertigkeit durch einen Vergleich des Flankenabstands mit einem Schwellwert festgestellt. Der Schwellwert berechnet sich zu (1.5*10^-3)/(Vorteiler=64)*Oszillatorfrequenz. Eigentlich müßten es 2.5 ms sein, aber es funktioniert nur mit 1.5. Da ergab die Simulation mit VMlab auch andere Werte als in der Realität (2.5 ms vs. 1.5 ms). Die Bits werden dann noch von links in die Datenvariable geschoben, da bei dem Sharp-Protokoll mit dem LSB angefangen wird.

-->