Stand
05.10.2010 - Dr.-Ing. Erhard Henkes
ASURO - der ideale Einstieg?
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO
-
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO
Foto: Dr. Erhard Henkes
Wer sich als Einsteiger
mit diesem niedrigen und begrenzten Niveau anfreunden kann, ist mit dem
Roboterbausatz
ASURO gut beraten. Im
ausführlich gestalteten Handbuch
findet man auf 78 Seiten die notwendigen Details für einen gelungenen
Einstieg
in
die Elektronik und die Programmierung von Microcontrollern in
der Programmiersprache C.
Was den ASURO zu einem mobilen
Roboter macht, sind
seine beiden
Gleichstrommotoren, die ihn programmgesteuert auf ebenem Gelände
navigieren
lassen. Die beiden Motoren und das zweistufige Getriebe mit einer
Untersetzung von 25:1 bringen den kleinen, leichten Flitzer gehörig auf
Trab.
Folgendes
Blockbild des ASURO vermittelt Ihnen einen ersten Überblick über
die
zur Verfügung stehenden Aktoren, Sensoren und Schnittstellen:
ASURO -
ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO-ASURO - ASURO -
ASURO - ASURO - ASURO
ASURO -
ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO
- ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO-ASURO
- ASURO -
ASURO - ASURO - ASURO
ASURO kann auf
seine sechs Taster (im vorderen Bereich), auf seine Radumdrehungen
(links und rechts), auf Helligkeitsunterschiede an seinen beiden
vorderen Fototransistoren
(z.B. für Linienverfolgung), auf die
Batteriespannung und auf Informationen via serielle IR-Schnittstelle
reagieren. Als
Zentrale wird ein Microcontroller von Atmel des Typs ATmega8L eingesetzt.
Der entscheidende Vorteil
des
ASURO: Er ist
einfach aufzubauen, kostengünstig zu erwerben, weit
verbreitet (mehr als 10000 verkaufte Einheiten) und es gibt eine große
ASURO-Community auf www.roboternetz.de,
die sowohl den Einstieg
als auch
die Weiterentwicklung fördert und unterstützt. Darüberhinaus gibt es
von Robin Gruber et. al. zwei
Bücher über den ASURO mit dem Titel "Mehr Spaß ...". Der dritte Band zum Thema
Regelungstechnik wurde im zweiten Band zwar angekündigt, wird aber aus
wirtschaftlichen
Gründen wahrscheinlich nicht verwirklicht. Man findet im "roboternetz"
allerdings bereits genügend Material zum Thema PID-Regelung.
Engagierte Programmierer
werden im Umfeld des ASURO vergebens nach komplexen Programmen suchen.
Dafür ist ASURO aber auch nicht entwickelt worden. Er ist ein
"Einsteigermodell" für Anfänger im Löten, in Elektronik und in der
Programmierung mit C. Er beseitzt eine einfache Platine und eine
rudimentäre Mechanik (Kleben, Löten, Kabelbinder).
Dafür ist er kostengünstig (<50¤) zu erwerben und ziemlich rasch
aufgebaut.
ASURO kennen lernen
ASURO ist eine Idee des Vereins "Deutsches
Zentrum
für Luft- und Raumfahrt e.V." (DLR), der diesen Roboterbausatz zu
Studienzwecken
entwickelte. Asuro wird gerne als Demonstrationsobjekt der Robotik bzw.
Informatik an
Schulen genutzt. Hier
sind seine "Erfinder" zusehen. Der ASURO ist seit Anfang 2005 auf dem
Markt, also noch ein recht frisches Produkt. Hier
findet man erste Meinungen aus der Anfangszeit über dieses neue Angebot
an
die Gemeinde der Roboterbastler. Da der
ASURO mit inzwischen über 10000 verkauften Einheiten zu einer Art
"Volksroboter" (in Anlehnung an den damaligen "Volkscomputer"
Commodore VC20 und C64) geworden ist, wollte ich "ihn" kennen lernen,
denn ich gehöre zu denen, deren erster Computer zuhause ein "C64"
(Rascher Nachfolger des VC20) war und die damit in die Programmierung
eingestiegen sind. Die Sprache des C64 war BASIC. ASURO wird
vorwiegend
mit C gefüttert, weil Assembler doch etwas schwierig zu erlernen ist.
Mich
interessierte bei ASURO zunächst die Möglichkeiten der
Robotik-Programmierung. Für
andere ist der Einstieg in die Elektronik, in die Welt der
Microcontroller oder in das Erlernen der Programmiersprache C das
Entscheidende. Mein erstes Fazit: Was will man für diesen niedrigen
Preis mehr erwarten? Auf jeden Fall kann man mit ASURO erste
Gehversuche machen, die wesentlichen Möglichkeiten und
Herausforderungen bezüglich Antrieb, Orientierung und Sensorik
praktisch kennen lernen und vor allem praktisch erspüren, ob man dieses
interessante, aber auch anspruchsvolle Hobby weiter verfolgen will.
Viele interessiert und begeistert das Erlebnis, ASURO selbst
aufzubauen. Persönlich war ich weniger am Löten, sondern mehr an den
programmiertechnischen
Möglichkeiten und Grenzen interessiert. Für Jüngere kann der ASURO
allerdings auch ein
Einstieg in die Elektronik darstellen, denn ohne Microcontroller geht
in diesem Gebiet nur noch wenig.
Um diesen
kleinen Roboter - kann man ihn wirklich schon so nennen? - von allen
Seiten zu beschnuppern, besorgte ich mir
einen
Bausatz, zwei fertig aufgebaute ASURO (via ebay) und die beiden
Bücher "Mehr Spaß mit ASURO" (Band 1 und 2) von Robin
Gruber et. al. Der Autor gehört zur
Abteilung Robotersysteme des DLR.
Ich
empfehle, sich zunächst
- falls möglich - einen fertig aufgebauten ASURO zu besorgen, den man
später wieder
verkaufen kann, wenn man das möchte, und erst danach einen ASURO selbst
zu fertigen, denn auf was es wirklich ankommt, erkennt man erst im
Betrieb.
Aufbautipps
Wenn Sie den Bausatz zu einem Fertiggerät
komplementieren wollen oder müssen, dann empfehle ich zumindest diese
hilfreiche Sortierhilfe
für die Widerstände. Allerdings fehlen dort die Widerstände R25 u. R 26
(beide 2 K) und R 21 (1K). Als Unterlage unter die Sortierhilfe
empfiehlt sich z.B. eine Styrodurplatte. Dann kann man die Widerstände
senkrecht aufstellen. Beim Aufbau sollten Sie auf Folgendes achten:
Achsen erst dann komplett
fixieren, wenn der Abstand genau stimmt, so dass die Zahnräder frei
laufen. Die Motoren befestigt man an der Ritzelseite besser mit einem
stärkeren Kabelbinder (Baumarkt, Elektronikhandel). Die
Encoderaufkleber sollte man erst aufbringen, wenn man ganz
sicher sind, wo diese hingehören. Widerstände genau nach Aufdruck
einstecken. Vorsicht mit den Beinchen der ICs (Umknickgefahr), keine
Gewalt anwenden!
Falls Sie eine Erweiterungsplatine verwenden wollen: Tischtennissball
nicht mit Kleber, sondern für die Funktionstests nur vorne und hinten
provisorisch vorne und hinten mit Isolierband fixieren (das hält sogar
auf Dauer). Die vordere Diode und die beiden
Fototransistoren nicht einlöten, da diese Verbindungen für die
Expansion benötigt werden (großer Nachteil des ASURO!).
Verständnis für den ASURO
Nehmen wir nun an, der Roboter ist nach Anweisung aufgebaut (die
Chancen stehen gut).
Seine Sensoren und
Aktoren sind korrekt mit dem Microcontroller verbunden. Der Weg dahin
ist eine
praktische Fleißarbeit nach exakter Vorgabe und guter Anleitung (siehe
Handbuch auf CD oder im Internet).
Wie auch immer, das elektronische Handwerk gehört auf jeden Fall zur
Robotik dazu, vor allem, wenn man später eigene Ideen in die Tat
umsetzen will.
Für seine Aktionen benötigt ASURO elektrische Energie. Diese
erhält man bei mobilen
Systemen typischerweise von
Batterien (4*1,5 Volt) oder Akkus (4*1,2 Volt). ASURO verwendet aus
Gründen der Gewichtseinsparung Batterien bzw. Akkus des Typs AAA (z.Z.
mit bis zu 1000 mAh erhältlich). Hierbei gibt es etwas Wichtiges zu
beachten: Der fertig zusammengebaute Asuro verfügt über
einen Jumper (JP1), der
eine Diode überbrücken kann (siehe Bild).
Dieser sichert auf einfache Weise die Spannungsversorgung der CPU in
akzeptabler Höhe:
- Werden normale Batterien
verwendet, muss der Jumper JP1 offen sein. Andernfalls kann der
Mikroprozessor zerstört werden.
- Bei Verwendung von Akkus
muss
wegen der geringeren Spannung (1,2 Volt) der parallel geschaltete Jumper geschlossen (Diode D9 überbrückt) sein.
Eine Spannungsstabilisierung besitzt ASURO von Haus aus nicht.
Bezüglich
der Energiegewinnung würde man vor allem im Freien gerne die Sonne
anzapfen. Hierfür gibt es bereits konkrete Experimente: ASURO
mit Solarzelle. Man sollte allerdings wiisen, dass im Freien die
Odometrie in der Regel versagt. Damit versagen die Encoder-gestützten
Bewegungsfunktionen der erweiterten ASURO-Bibliothek.
Wir "flashen" den ASURO
ASURO ist die Hardware, Energie der Treibstoff vor allem für die
Motoren. Die Sensoren und die elektronische Verschaltung verbrauchen
recht wenig Strom. Was nun fehlt ist die
Software. Ein
Programm muss her, z.B. ein
kleiner
Selbsttest. Ein Microcontroller benötigt ein Programm im Binärformat.
Das sind bei ASURO - wie auch bei vielen anderern Robotern -
Programme mit der Endung hex
als Erkennungszeichen. Das Programm wird
über die
serielle Schnittstelle eines PCs übertragen. Ob das mit einem festen
Kabel (ISP wie beim STK500, per
Funk oder wie beim ASURO über einen
RS232-Infrarot-Transceiver (siehe Bild) erfolgt, spielt prinzipiell
keine Rolle.
RS232-Infrarot-Transceiver
Foto: Dr. Erhard Henkes
Das
Programm muss in den Programmspeicher der CPU, um dort sein Unwesen
oder Wesen
zu treiben. Dafür gibt es sogenannte Flash-Programme, z.B. das ASURO
Flash Tool. Im Beispiel übertragen wir das Programm SelfTest.hex
von einem PC mit MS Windows auf den ASURO:
Bei einem Verbindungsproblem oder ohne ASURO sieht das wie folgt aus:
Fragen:
Woher bekommt man das ASURO Flash Tool (für MS Windows)? HIER
Woher bekommt man fertige HEX-Programme für den ASURO? HIER
In welchen Speicher des ATmega8L
wird das Programm eigentlich übertragen?
ATmega8L
Der ATmega8L besitzt
in seinem Aufbau folgende wichtige Elemente:
Aus den Beschreibungen des Microcontrollers:
8 KB of In-System
Self-Programmable Flash
Endurance: 10,000
Write/Erase Cycles
Optional Boot Code
Section with Independent Lock Bits
In-System
Programming by On-chip Boot Program
True
Read-While-Write Operation
512 Bytes EEPROM
Endurance: 100,000
Write/Erase Cycles
1 KB Internal SRAM
Programming Lock
for Software Security
Zum Thema Unterschiede der Speicher im ATmega8L gibt es hier
einen hervorragenden Übersichtsartikel.
Der binäre Programmcode wird
aus dem Speicher des PC in den
Flash-Speicher des
Microcontroller übertragen und direkt aus
diesem ausgeführt.
Das EEPROM ist der richtige
Speicher für Messwerte oder Einstellungen, die nach dem Ausschalten
nicht verschwinden sollen.
Das SRAM dient für flüchtige
Daten, z. B. während des Programmablaufs als Speicher für den "Stack". Dort
werden beim
Aufrufen von Unterprogrammen die Rücksprungadressen abgelegt.
Wer den ATmega8L vertieft analysieren will - und das kann man jedem nur
empfehlen - studiert das Datenblatt.
Am besten zeichnen Sie ihr eigenes Blockschaltbild mit eigenen Notizen,
damit Sie sich die Zusammenhänge einprägen und auch die Feinheiten
verstehen.
Vgl. auch Schaltbild im Handbuch ASURO S.74.
Der ATmega8L besitzt
einen RISC-Mikroprozessor. Dieser folgt der
Harvard-Architektur, d.h. er besitzt getrennte Speicher für
Instruktionen (unser Programm) und Daten. Instruktionen (und konstante
Daten) liegen im 8 KB "On-chip In-System
Reprogrammable" Flash-Speicher. Der Flash-Speicher verfügt über zwei
Sektoren: In der "boot section"
ist der Bootloader, der das Programm in der
"application section" startet.
Die "application section" beinhaltet das
"Programm" sowie dessen
konstante Daten (unsere HEX-Datei). Da der Bootloader 1 KB belegt,
bleiben noch 7 KB für
unser Programm. Wer die MB und GB aus PCs gewöhnt ist, wird sich
fragen,
wie man hier auf Dauer klar kommt. Wir werden sehen, wie weit man mit
dem ASURO kommt.
Variable Daten, mit denen gearbeitet
werden soll,
befinden sich im 1 KB SRAM. Dieser RAM ist statisch aufgebaut und
operiert mit vollem Prozessortakt.
Im Datenblatt finden Sie auch den Unterschied zwischen ATmega8L (ASURO) und
ATmega8:
Operating Voltages 2.7 - 5.5V (ATmega8L)
4.5 - 5.5V (ATmega8)
Speed Grades 0
- 8 MHz (ATmega8L) 0 - 16 MHz (ATmega8)
Der ASURO wird quarzstabilisiert mit 8 MHz getaktet. Diese
Geschwindigkeit ist für den ASURO ausreichend. Nachteilig wird diese
Frequenz erst, wenn man den I²C-Bus im "fast mode" (400 kHz) betreiben
will. Dazu benötigt man 16 MHz.
Programmierung in C
Wer eigene Programme erstellen will benötigt einen Compiler/Linker,
der den Weg bahnt vom eigenen Programm in C zur binären hex-Datei. Den
Compiler für C/C++ WIN AVR
erhält man hier.
Die Installation auf MS WIndows verläuft problemlos. Aber was habe
ich dann auf meiner Platte? Wer es nicht gewohnt ist, im
Kommandozeilenmodus zu kompilieren, wird sich nun etwas schwer tun. Der
Editor ist ein programmers notepad 2.
Der Clou bei der Programmierung ist das make-File, das uns das Tippen
der Kommandos
abnimmt. Für die Erstellung von Programmen für den Asuro mit C gibt es
vom
Hersteller eine
mitgelieferte Programmbibliothek. Die Bibliothek besteht insbesondere
aus den folgenden beiden Dateien: asuro.h
und asuro.c.
Neben dieser Programmbibliothek des Herstellers gibt es innerhalb
der ASURO-Community inzwischen modifizierte Versionen. Empfehlenswert
ist die
Version aus dem Forum Roboternetz.
In dieser Version wurden Fehler behoben, und es wird vor allem eine
erweiterte
Funktionalität geboten.
Die ASURO lib findet sich hier.
Wir verwenden die aktuellste Bibliothek (z.Z.
Version 2.80). Es sollte eigentlich keinen Grund geben, die inzwischen
völlig überholte Originalversion
einzusetzen, auch nicht für die Ultraschallerweiterung. Die hier
zietierten Sourcecodes entstammen noch der Version 2.70.
Im Kopf von asuro.h findet man
folgenden Eintrag:
/*!
* \file asuro.h
* \brief Definitionen und Funktionen der ASURO Bibliothek
*
* $Revision: 2.70 $
* $Date: 07. Januar 2007 $
* $Author: Jan Grewe, Robotrixer, Waste, Stochri, Andun,
m.a.r.v.i.n $
*
\version V001 - 10.02.2007 - m.a.r.v.i.n\n
+++
my_t Neue Datenstruktur\n
Datenstruktur fuer die Asuro-Hardwareabhaengigen Parameter die
jeder User fuer seinen Asuro in der Datei myasuro.h selber
einstellen kann um die Asuro-Typischen Eigenschaften zu definieren.
\version V002 - 18.02.2007 - Sternthaler\n
+++
my_t\n
-
Neue Variable fuer MY_MOTOR_DIFF zum ausgleichen unterschiedlicher\n
Motoren.
-
Aendern aller enthaltenen Variablen auf einen moeglichst kleinen\n
Speicherbedarf. Notwendige Typumwandlungen muessen im Code durch\n
casten erfolgen.
\version V003 - 20.02.2007 - m.a.r.v.i.n\n
+++
my_t Datenstruktur wieder entfernt\n
Es
werden direkt die Defines aus der myasuro.h verwendet.
\version V004 - 06.04.2007 - m.a.r.v.i.n\n
Batterie und OdometrieData Funktionen umbenannt in
Battery und OdometryData.\n
Alte
Funktionsnamen ueber Defines beibehalten
*/
Die ASURO Lib ist ab Version 2.70 nicht mehr nur eine
Quellcode-Bibliothek, sondern eine Objectcode-Bibliothek, das heißt die
Bibliothek
besteht aus einem Archiv von Objekt Files, die nicht mehr kompiliert,
sondern über die Bibliothek libasuro.a nur noch gelinkt
wird. Der Vorteil der Objekt-Bibliothek gegenüber der
Sourcecode-Bibliothek ist
die signifikant verringerte Größe der binären Files (hex). Im Gegensatz
zur Sourcecode-Bibliothek werden nämlich nur die Objekt Files gelinkt,
die vom
Programm tatsächlich aufgerufen werden. Bei der Sourcecode-Bibliothek
werden dagegen alle Files gelinkt, unabhängig davon, ob sie benötigt
werden oder nicht.
AVR Studio
Ich empfehle für ein Projekt-orientiertes Programmieren das Atmel AVR
Studio. Dieses kostenlose Tool kann man sowohl für die Assembler- als
auch in Verbindung mit AVR-GCC für die C-Programmierung einsetzen. An
einem einfachen Beispiel zeigen wir hier den hoffentlich auch bei Ihnen
problemlosen Einstieg mit dem Betriebssystem Windows 2000 oder XP (bei
Vista gibt es teilweise System-Probleme, deren Behebung im Internet
beschrieben sind).
Man installiert WinAVR
und anschließend das Atmel
AVR Studio. Das AVR Studio verfügt über ein PlugIn für Win-AVR, so
dass man sich um dessen Pfade nicht selbst kümmern muss. Als Device
wählt man den atmega8, die Frequenz beträgt 8000000 Hz (= 8000 kHz = 8
MHz). Wichtig ist der Eintrag für die Optimierung mit "-Os", ansonsten
gibt es Probleme mit dem Zeitverhalten.
Als nächstes muss man die "Include Directories" auf die Header-Dateien
(Files mit Endung h) einrichten:
Für die Library libasuro.a muss ebenfalls der Pfad bekannt sein. Wurde
diese z.B. über das MakeFile der Bibliothek bereits in das
entsprechende WinAVR-Lib-Verzeichnis kopiert, so steht diese Bibliotehk
bereits zur Verfügung. Ansonsten muss man den Pfad selbst einrichten,
hier das Beispiel, bei dem die Library libasuro.a bereits in WinAVR
gelandet ist:
Es ist wichtig, dass man diese Zusammenhänge richtig versteht.
Bezüglich der allgemeinen
Dateien des ASURO sorgt man für das Bekanntmachen der Pfade für die
Header (über das Include-Verzeichnis). Die Bibliothek libasuro.a ist
bereits via WinAVR bekannt (ansonsten Pfad einstellen) und wird als
"Link Object" zugefügt.
Header-Dateien werden in den entsprechenden Source-Dateien mittels
#include ... angegeben. Für das Einfügen sorgt der Präprozessor (auch
Precompiler genannt), der sich übrigens auch die Ersetzungen durch
#define kümmert. Nun geht der Compiler zu Werke. Dieser macht aus den
Source-Dateien mit der Endung c sogenannte Objekt-Dateien mit der
Endung o.
Die notwendigen Source-Dateien fügen wir im AVR Studio im sogenannten
"Project Tree" (beim Stierkopf, Bezeichnung "AVR GCC") in die
virtuellen Ordner ein.
Dies sind unsere Datei, in die wir unseren Sourcecode schreiben, und -
ganz wichtig! - asuro.c. Denn asuro.c wurde bei der libasuro.a weg
gelassen, da in dieser Datei oft Änderungen notwendig sind. Diese
Struktur der ASURO-Bibliothek ist fragwürdig und führt bei
Programmieranfängern manchmal zu Verständnisproblemen. Nachfolgend
zeigen wir den Project Tree:
Sie sehen hier die beteiligten Dateien:
1) für den Präprozessor: die Header-Dateien xxx.h
2) für den Compiler: die Source-Dateien asuro.c und unsere Projektdatei
xxx.c (Namen frei wählbar, hier ASURO_001.c)
3) für den Linker: libasuro.a (und später die kompilierten
Objekt-Dateien asuro.o und xxx.o)
Im Windows-Explorer
(nicht verwechseln mit dem virtuellen Project-Tree des AVR Studio)
sollten sich im Windows-Verzeichnis des Projektes (Bild links) nur
folgende Dateien finden:
Also bitte nicht die Header-Dateien oder Source-Dateien der
ASURO-Bibliothek in dieses Projektverzeichnis kopieren. Das schafft nur
Durcheinander!
Im Ausgabe-Verzeichnis (Standard: default) finden wir unsere hex-Datei
(hier ASURO_001.hex), die wir anschließend zum Realitätstest in den
ATmega8L des ASURO "flashen" können.
Wenn Sie neugierig sind, öffnen Sie im Unterverzeichnis dep mit einem
Editor (z.B. Notepad+) die Datei asuro.o.d. Dort findet man sehr schön
aufgelistet die entsprechenden Header-Dateien, die mit der Source-Datei
verbunden sind:
asuro.o:
../../../AsuroLib/lib/asuro.c ../../../AsuroLib/lib/asuro.h \
c:/winavr/bin/../avr/include/avr/io.h \
c:/winavr/bin/../avr/include/avr/sfr_defs.h \
c:/winavr/bin/../avr/include/inttypes.h \
c:/winavr/bin/../avr/include/stdint.h \
c:/winavr/bin/../avr/include/avr/iom8.h \
c:/winavr/bin/../avr/include/avr/portpins.h \
c:/winavr/bin/../avr/include/avr/version.h \
c:/winavr/bin/../avr/include/avr/interrupt.h \
c:/winavr/bin/../avr/include/stdlib.h \
c:\winavr\bin\../lib/gcc/avr/4.1.1/include/stddef.h \
C:\ASURO_SRC\Projekte\ASURO_001\..\..\AsuroLib\lib\inc/myasuro.h
../../../AsuroLib/lib/asuro.h:
c:/winavr/bin/../avr/include/avr/io.h:
c:/winavr/bin/../avr/include/avr/sfr_defs.h:
c:/winavr/bin/../avr/include/inttypes.h:
c:/winavr/bin/../avr/include/stdint.h:
c:/winavr/bin/../avr/include/avr/iom8.h:
c:/winavr/bin/../avr/include/avr/portpins.h:
c:/winavr/bin/../avr/include/avr/version.h:
c:/winavr/bin/../avr/include/avr/interrupt.h:
c:/winavr/bin/../avr/include/stdlib.h:
c:\winavr\bin\../lib/gcc/avr/4.1.1/include/stddef.h:
C:\ASURO_SRC\Projekte\ASURO_001\..\..\AsuroLib\lib\inc/myasuro.h:
Dies hilft Ihnen weiter, wenn Sie sich für die "includierten"
Bezeichnungen interessieren.
ASURO Bibliothek
Die Kunst beim Verstehen der Programme besteht nun darin, sich
systematisch von außen (High Level - Benutzersicht) nach innen
(Low Level - aus Sicht des Microcontrollers) durch die
leider nicht sauber getrennten Programmschichten -
Funktionen und Namensfestlegungen (#define, Makro)
- zu arbeiten. Als Einstieg kann man folgende Kurzbeschreibung der
Programmbibliothek (ohne Details)
des ASURO verwenden: Link
Man sollte bezüglich der Programmiersprache C vor allem die Bit-Logik
und die Zuweisung beherrschen:
C-Kurse:
http://www2.its.strath.ac.uk/courses/c/
http://www.pronix.de/pronix-649.html
Logik:
http://en.wikipedia.org/wiki/Bitwise_operation
http://en.wikipedia.org/wiki/Bit_manipulation
Logische
Operatoren
&
bitweises AND
|
bitweises OR
~
bitweises NOT
^
bitweises XOR
<<
bitweises Linksschieben
>>
bitweises Rechtsschieben
Zuweisungsoperatoren
=
Zuweisung
+=
Zuweisung nach Addition
-=
Zuweisung nach Subtraktion
*=
Zuweisung nach Multiplikation
/=
Zuweisung nach Division
%=
Zuweisung nach Modulo
<<
Zuweisung nach bitweisem Linksschieben
>>
Zuweisung nach bitweisem Rechtsschieben
&=
Zuweisung nach bitweisem AND
|=
Zuweisung nach bitweisem OR
^=
Zuweisung nach bitweisem XOR
Beispiel:
PORTx |= (1 << BitNummer); // Bit in PORTx setzen
PORTx &= ~(1 << BitNummer); // Bit in PORTx löschen
Am Beispiel der Initialisierungs-Funktion des ASURO steigen wir in
seine "Bibliothek" ein::
int main ()
{
int wert;
Init ();
while (1) // Endlosschleife
(
}
return 0; // wird nicht erreicht
}
Mit dieser Funktion werden Anfangseinstellungen erzeugt, die für die
meisten Aufgaben sinnvoll sind. Der Name Init(...) ist einprägsam, aber was
steckt dahinter? Solche Informationen findet man in der Dokumentation
der ASURO Bibliothek. Nun zur Gewöhnung an die Namen der Variablen der
Blick in das
Innenleben der Funktion Init():
{
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
OCR2 = 0x91;
TIMSK |= (1 << TOIE2);
UCSRA = 0x00;
UCSRB = 0x00;
UCSRC = 0x86;
UBRRL = 0xCF;
DDRB = LEFT_DIR | GREEN_LED | IRTX | PWM ;
DDRD = RIGHT_DIR | RED_LED | FRONT_LED | ODOMETRIE_LED ;
TCCR1A = (1 << WGM10) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = (1 << CS11);
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
ODOMETRIE_LED_OFF;
FrontLED (OFF);
BackLED (ON, ON);
BackLED (OFF, OFF);
StatusLED (GREEN);
MotorDir (FWD, FWD);
MotorSpeed (0, 0);
autoencode = FALSE;
sei ();
}
Hierbei finden sich folgende wichtige Elemente der Programmiersprache C:
Aufruf einer Funktion:
MotorDir (FWD, FWD);
bitweise ODER-Verknüpfung:
DDRB = LEFT_DIR | GREEN_LED | IRTX | PWM ;
DDRD = RIGHT_DIR | RED_LED | FRONT_LED | ODOMETRIE_LED ;
Links-Shift-Operator:
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
Low Level Programmierung des ATmega8(L)
Wenn Sie den ASURO und vor allem sein "Gehirn", nämlich den ATmega8L,
richtig verstehen wollen - und dazu rate ich Ihnen dringend - dann
müssen Sie hier
ein wenig inne halten und sich die Bezeichnungen genau anschauen. Die
notwendigen
Informationen findet man im spezifischen Datenblatt
des
Microcontrollers ATmega8L. Wir schauen uns die "Low Level
Programmierung" an einem konkreten
Beispiel aus der Init-Funktion und einer Interrupt-Funktion
an:
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20); OCR2 = 0x91; TIMSK |= (1 << TOIE2);
|
Im
Register TCCR2 werden die Bits WGM20, WGM21, COM20, COM21, CS20 auf 1
gesetzt.
Das Register OCR2 wird auf hexadezimal 91 - binär 10010001
- gesetzt.
Im Register TIMSK wird das Bit TOIE2
auf 1 gesetzt.
Beim Overflow und Rücksetzen auf Null wird der Timer/Counter TCNT2 in
der
Interrupt-Funktion um 37 (0x25) erhöht.
Im Datenblatt erhält man
detaillierte Informationen über diese 8-Bit-Register und ihre
spezifischen Bits:
TCCR2, WGM20, WGM21:
The counting sequence is determined by the setting of the WGM21 and WGM20 bits located in the
Timer/Counter Control Register (TCCR2).
There are close connections between how the counter behaves (counts)
and how waveforms are generated on the Output Compare Output OC2.
The Timer/Counter (TCNT2) and Output
Compare Register (OCR2)
are 8-bit registers. Interrupt request (shorten as Int.Req.) signals
are all visible in the Timer Interrupt Flag Register (TIFR). All
interrupts are individually masked with the Timer Interrupt Mask Register (TIMSK). ... The Timer/Counter can be
clocked internally, via the prescaler, or asynchronously clocked from
the TOSC1/2 pins, as detailed later in this section. The asynchronous
operation is controlled by the Asynchronous Status Register (ASSR). The
Clock Select logic block controls which clock source the Timer/Counter
uses to increment (or decrement) its value. The Timer/Counter is
inactive when no clock source is selected. The output from the clock
select logic is referred to as the timer clock (clkT2). The double buffered Output Compare Register
(OCR2) is compared with the Timer/Counter value at all times. The
result of the compare can be used by the waveform generator to generate
a PWM or variable frequency output on the Output Compare Pin (OC2).
Es ist hier nicht ganz einfach zu verstehen, wie man auf die Frequenz
von 36 kHz kommt. Die Formel ist:
8000 kHz / (256-37+3) = 36,036
kHz
Der Timer TCNT2 zählt von 37 bis 256 (=0). Der Prozessor benötigt nun 3
Takte (clock cycles), das entspricht 0,375 Mikrosekunden bei 8 MHz, für
die
Ausführung der Operation +=. Dies kann man z.B. in der Datei test.lss
erkennen:
TCNT2 += 0x25
in
r24, 0x24
subi
r24, 0xDB
out
0x24, r24
Wer sich für die Details der Instruktionen (genaue Aktion,
Zeitbedarf, ...) der AVR-Mikroprozessoren interessiert, dem sei das Dokument
"8-bit AVR Instruction Set" zum Nachschlagen empfohlen.
Diese drei Takte (clock cycles) darf man bei der Betrachtung des
zeitlichen Ablaufs nicht vernachlässigen! Die
Symmetrie unseres Rechtecksignals an Pin OC2 wird durch den Wert 145
(0x91) in OCR2 (Umschaltung von Lo- auf Hi-Signal zu diesem Zeitpunkt)
gewährleistet:
145-37+3 =
111
Takte Lo-Signal
256-145
= 111 Takte Hi-Signal
------------------------------
222 Takte
8000 kHz / 222 = 36,036 kHz
Die Zusammenhänge sind in diesem Fall relativ komplex. Aber durch
intensives und umfassendes Analysieren lässt es sich verstehen. Ohne
dieses Verständnis
der Aufbau- und Ablauforganisation des Microcontrollers ist man
übrigens nicht in der Lage, eigene Low-Level-Abläufe bzw
-Funktionen zu
erstellen.
Schauen
wir uns ein weiteres Detail an, nämlich die relativ einfache Funktion BackLED(...):
void
BackLED (unsigned char left,
unsigned char right)
{
if (left || right)
{
PORTD &= ~(1 << PD7);
DDRC |= (1 << PC0) | (1 << PC1);
PORTC |= (1 << PC0) | (1 << PC1);
}
if (!left)
PORTC &= ~(1 << PC1);
if (!right)
PORTC &= ~(1 << PC0);
}
Hier müssen Sie nur heraus finden, was PORTx
und DDRx (x steht für a,b,c,d,
...) bedeutet. Suche im Datenblatt verwenden, und schon verfügt man
über die benötigte Information.
Interessant sind auch die "Low-Level"-Funktionen für die Motoren in der
Datei motor_low.c:
inline
void MotorSpeed (unsigned char
left_speed, unsigned char
right_speed)
{
OCR1A
= left_speed;
OCR1B
= right_speed;
}
inline void MotorDir (unsigned char
left_dir, unsigned char
right_dir)
{
PORTD
= (PORTD &~ ((1 << PD4) | (1 << PD5))) | left_dir;
PORTB
= (PORTB &~ ((1 << PB4) | (1 << PB5))) | right_dir;
}
Jetzt stellt sich die wichtige Frage, woher kennt eigentlich der
Compiler die Bedeutung der direkt auf den Microprozessor bezogenen
Bezeichnungen wie
OCR1A, OCR1B, PORTB, PORTD, PB4, PB5, PD4, PD5 ?
Schauen wir zunächst in asuro.h
nach. Dort findet man: #include
<avr/io.h>
Diese Datei findet
man in <WinAVR_ROOT>\avr\include\avr\io.h (
<WinAVR_ROOT> ist z.
B. C:\WinAVR )
Damit geht man in die Tiefe bis an den Microcontroller.
In io.h findet
man:
#elif defined (__AVR_ATmega8__)
#include <avr/iom8.h>
Dieses __AVR_ATmega8__
wird übrigens durch das make-File geliefert: mcu = atmega8
In iom8.h
findet man an verschiedenen Stellen die define-Anweisungen für diese
Bezeichnungen. Hier die Auszüge für unsere gesuchten Bezeichnungen:
#define
OCR1A _SFR_IO16(0x2A)
#define
OCR1B _SFR_IO16(0x28)
#define
PORTB _SFR_IO8(0x18)
#define
PORTD _SFR_IO8(0x12)
#define
PB5 5
#define
PB4 4
#define
PD5 5
#define
PD4 4
Nun fehlen uns zum vollständigen
Verständnis noch die Makros _SFR_IO16(...)
und _SFR_IO8(...).
Die Festlegungen finden sich in der Datei sfr_defs.h:
#ifndef
__SFR_OFFSET
/* Define as 0 before including
this file for compatibility with old asm
sources that don't
subtract __SFR_OFFSET from symbolic I/O addresses. */
#define __SFR_OFFSET 0x20
#endif
#define _SFR_IO8(io_addr)
((io_addr) + __SFR_OFFSET)
#define _SFR_IO16(io_addr)
((io_addr) + __SFR_OFFSET)
Damit
sehen Sie nun an diesem Beispiel eine geschlossene Kette von MotorSpeed(...)
bzw. MotorDir(...)
bis zu den einzelnen Bits an den Ein- und Ausgängen des
Microcontrollers. Dies ist sehr wichtig, wenn Sie eigene Entwürfe
umsetzen wollen, denn nur, wenn Sie die wesentlichen Zusammenhänge der
Microcontroller-Programmierung in C verstehen, können Sie diese auf
neue
Bedürfnisse anpassen. Den
Vorteil der Programmiersprache C erkennen Sie hier deutlich. Man kann
sich
durch Schichtung von Defines, Makros und Unterfunktionen ein immer
abstrakteres Modell schaffen, das direkt auf die Belange der
Programmierung auf hoher Ebene eingehen kann. Das schafft Übersicht und
spart Zeit bei der Programmierung.
Aufbauend auf
MotorSpeed(...) und MotorDir(...)
wurde z. B. die Funktion SetMotorPower(...)
entwickelt:
void SetMotorPower (int8_t leftpwm, int8_t rightpwm)
{
unsigned char left, right;
if
(leftpwm <
0)
// Ein negativer Wert fuehrt ...
{
left =
RWD;
// ... zu einer Rueckwaertsfahrt,
...
leftpwm =
-leftpwm;
// aber immer positiv PWM-Wert
}
else
left =
FWD;
// ... sonst nach vorne, ...
if
(leftpwm == 0)
left =
BREAK;
// ... oder bei 0 zum Bremsen.
if
(rightpwm < 0)
{
right = RWD;
rightpwm = -rightpwm;
}
else
right = FWD;
if
(rightpwm == 0)
right = BREAK;
MotorDir (left,
right);
// Drehrichtung setzen
/*
Die Geschwindigkeitsparameter mit 2 multiplizieren, da der Absolutwert
der Parameter dieser Funktion nur genau die Haelfte von der
MotorSpeed()-Funktion
betraegt.
*/
MotorSpeed (leftpwm * 2, rightpwm *
2);
}
Hier ein konkretes Beispiel:
// Setzt die Geschwindigkeit fuer
den linken Motor auf 60 (vorwaerts),
// und für den rechten Motor auf -60 (rueckwaerts)
// Asuro soll auf der Stelle drehen.
SetMotorPower (60, -60);
Gleiches gilt für die leicht
verständlichen und besser einsetzbaren Funktionen
void Go (int distance, int
speed)(...) und void Turn (int degree, int speed)(...)
aus der Lib
2.70.
ASURO selbst programmieren
Nun ist aber endgültig der Moment gekommen, an dem man selbst mit der
C-Programmierung des Microcontrollers beginnen will. Wir schreiben auf
Basis des Programmes
test.c in FirstTry
(...\ASURO_SRC\AsuroLib\examples\FirstTry)
unsere erstes Programm:
#include
"asuro.h"
int
main()
{
Init();
int i=0;
for (i=0;i<100;++i)
{
BackLED (OFF, ON);
Msleep(200);
BackLED (ON, OFF);
Msleep(200);
}
BackLED (OFF, OFF);
while (1); //ansonsten
endlos
return 0; //wird nicht erreicht
} |
Der von uns eingefügte Code lässt die linke und rechte rote BackLED 100
mal abwechselnd blinken. Dann werden beide BackLED ausgeschaltet. Die
Pausen in der for-Schleife kann man mit der Funktion Msleep(...)
bereits in Millisekunden angeben. Das macht den Code besser lesbar als
bei der Verwendung der Basis-Funktion Sleep(...).
void Msleep (int dauer)
{
int z;
for (z = 0; z <
dauer; z++)
Sleep (36);
}
Dieses
Programm wird nun mit unserem ASURO Flash Tool (s.o.) in den
Microcontroller übertragen. Es werden "15 Pages" erfolgreich
übertragen.
Beim Flashen geht man folgendermaßen vor:
1) Übertragungseinheit und ASURO mit den Bauteilen zueinander halten
2) ASURO ausschalten
3) Flash-Programm starten
4) Während der Statusbalken nach rechts läuft (!), ASURO einschalten,
bevor der Statusbalken bei 100% ankommt
Die Schritte 2 und 3 kann man auch umkehren.
Hat man dies richtig gemacht, ergeben sich z. B. folgende Meldungen:
Können Sie diese Blinkfrequenz (ca. 30 mal pro Sekunde) noch erkennen?
BackLED
(OFF, ON);
Msleep(16);
BackLED
(ON, OFF);
Msleep(16); |
Die Dokumentation der zur
Verfügung stehenden Funktionen und Variablen findet man z.B. hier:
...\ASURO_SRC\AsuroLib\doc\html\index.chm
Suchen
Sie dort nach der Funktion StatusLED(...).
Mit dem nachfolgenden Programm testen wir die vier Zustände dieser
"farbigen" LED:
#include
"asuro.h"
int
main()
{
Init();
const int DAUER=400;
int i=0;
for (i=0;i<20;++i)
{
StatusLED (GREEN);
Msleep (DAUER);
StatusLED (RED);
Msleep (DAUER);
StatusLED (YELLOW);
Msleep (DAUER);
}
StatusLED (OFF);
while (1);
return 0;
}
|
ASURO sagt "Hallo
Welt!"
Jetzt wird es aber höchste Zeit für ein "Hallo Welt" - Programm. Dafür
gibt es die Datenübertragung und das Programm HyperTerminal unter MS
Windows.
Zum Schreiben gibt es die einfache Funktion SerWrite(...).
#include
"asuro.h"
int
main()
{
Init();
const int DAUER=500;
StatusLED (YELLOW);
while (1)
{
SerWrite("Hallo
Welt!\r\n",13);
Msleep(DAUER);
SerWrite("Mein
Name ist ASURO!\r\n",22);
Msleep(DAUER);
SerWrite("Ich
bin ein mobiler Roboter.\r\n",30);
Msleep(DAUER);
}
while (1);
return 0;
} |
Nun Starten wir unser HyperTerminal. Dieses nützliche Programm -
wahrscheinlich wussten Sie als Windows-User überhaupt nicht, dass Sie
es besitzen - findet man bei MS Windows unter Programme - Zubehör -
Kommunikation - HyperTerminal. Übernehmen Sie 2400 Bit/s, 8
Datenbits,
keine Parität, ein Stoppbit, keine Flusssteuerung. Nach dem Starten des
ASURO findet sich auf dem HyperTerminal folgende Dauerausgabe:
Mit diesem kleinen Programm kann man bestens die Reichweite und die
notwendige Ausrichtung der Verbindung zwischen ASURO und
RS232-Kommunikationseinheit überprüfen. Man stellt dabei fest,
dass eine Funkverbindung der vorhandenen Infrarot-Verbindung deutlich
überlegen wäre.
Wenn Sie wissen wollen, wie schnell die Datenverbindung funktioniert,
können Sie einfach die Pausen auskommentieren.
ASURO gibt Gas,
fährt mit Go(...) und Turn(...)
Nun wird es aber Zeit, dass wir die Motoren anwerfen. Das machen wir
zunächst auf höchster Ebene, nämlich mit Go(...) und
Turn(...) der erweiterten
Bibliothek. Das macht Laune. Wir probieren es mit
Vorwärts-/Rückwärtsfahren und einem
Dreieck bzw. Quadrat:
#include "myasuro.h"
#include "asuro.h"
int main(void)
{
Init();
EncoderInit();
int i;
for(i=0;i<10;++i)
{
Go( 1000,150); //
1 Meter
Go(-1000,150);
}
while(1);
return 0;
} |
#include
"myasuro.h"
#include "asuro.h"
int
main()
{
Init();
EncoderInit();
int i,j;
for (i=0; i<10;
++i)
{
for (j=0; j<3; ++j) //Dreieck
{
Go(500,150);
Turn(120,150);
}
}
for (i=0; i<10; ++i)
{
for (j=0; j<4; ++j) //Quadrat
{
Go(500,150);
Turn(90,150);
}
}
while (1);
return 0;
}
|
Bei Ihnen funktioniert alles bestens? Asuro führt all diese Figuren
fehlerfrei aus? Winkel und abgefahrene Strecken stimmen in Gradmaß und
Längenmaß? Die Wahrscheinlichkeit ist minimal, denn das Geradeausfahren
ist für Asuro bereits eine schwierige Disziplin. Bei
mir gab es in einem Fall beim Vorwärtsfahren nach kurzer
Strecke einen heftigen Drall nach links. Das ging soweit, dass Asuro
nur noch das rechte Rad drehte. Ich dachte schon, ein Antrieb sei
kaputt oder blockiert. Programme wie Go(...)
und Turn(...)
sind nicht schwer zu verstehen, aber dennoch zu komplex, um Fehler auf
einfache Art lokalisieren zu können.
Werfen wir zum Verständnis einen Blick in die Funktion Go(...), die man in der
Datei encoder.c findet:
void Go (int distance,int speed)
{
uint32_t enc_count;
int tot_count = 0;
int diff = 0;
int l_speed = speed, r_speed = speed;
// calculation tics/mm
enc_count=abs(distance)*10000L;
enc_count/=MY_GO_ENC_COUNT_VALUE;
EncoderSet(0,0); // reset encoder
MotorSpeed(l_speed,r_speed);
if (distance<0) MotorDir(RWD,RWD);
else MotorDir(FWD,FWD);
while (tot_count<enc_count)
{
tot_count += encoder[LEFT];
diff = encoder[LEFT] - encoder[RIGHT];
if (diff > 0)
{ //Left faster than right
if ((l_speed > speed) || (r_speed > 244)) l_speed -= 10;
else r_speed += 10;
}
if (diff < 0)
{ //Right faster than left
if ((r_speed > speed) || (l_speed > 244)) r_speed -= 10;
else l_speed += 10;
}
EncoderSet(0,0); // reset encoder
MotorSpeed(l_speed,r_speed);
Msleep(1);
}
MotorDir(BREAK,BREAK);
Msleep(200);
}
|
Nehmen wir zum Rechnen ein konkretes Beispiel: Go(500,150);
#define
MY_GO_ENC_COUNT_VALUE 19363L
(findet
sich in myasuro.h)
enc_count
= abs(distance)*10000L; // enc_count = 500 *
10000 ==> 5000000
enc_count /= MY_GO_ENC_COUNT_VALUE;
// enc_count = 5000000 / 19363
==>
258
Das ist die zu erreichende Zielmarke an Zählern über die Odometrie. Es
wird nun solange vorwärts gefahren bis diese Zielzahl erreicht ist.
while
(tot_count<enc_count){...}
Dabei wird das linke Rad zum Zählen verwendet.
tot_count
+= encoder[LEFT];
Zum
Vergleich werden die Zähler rechts und links verglichen.
diff =
encoder[LEFT] - encoder[RIGHT];
Nehmen wir an, links sind mehr Zähler als rechts, diff also positiv,
dann wird je nach Geschwindigkeit entweder links um 10 Power-Einheiten
reduziert oder rechts um 10 Power-Einheiten erhöht.
if (
(l_speed > speed) || (r_speed > 244) )
{
l_speed -= 10;
}
else
{
r_speed += 10;
}
Ein transparentes Verfahren, das analog in Turn(...)
eingesetzt wird. Voraussetzung für das Gelingen ist, dass die Odometrie
verlässliche Daten liefert und die gesamte Antriebselektrik und
-mechanik funktioniert. Über die Konstanten in myasuro.h
kann man sein individuelles Exemplar softwareseitig so
kalibrieren, dass die gefahrerene Distanz und der gedrehte Winkel
möglichst genau passen.
Es gibt allerdings noch einige Hürden. Diese liegen in der Messung der
Umdrehungen begründet, die mittels schwarz bzw. weißer Flächen, einem
Fototransistor und einer Diode erfolgt. Für die Analyse der Odometrie
benötigen
wir eindeutige Tests, die
uns aufzeigen, welche Messdaten durch den Fototransistor entstehen. Mit
dem nützlichen Programm "LoggingOdometers
V1.0" (2006-05-21, Arexx-Henk)
kann man seine individuellen Odometrie-Daten an das Hyperterminal
übertragen. Das Min/Max-Ergebnis für rechts und links war z.B. bei
einer Messung:
Left
min/max values
078
208
Right
min/max values
155
224
Überträgt man die davor stehenden beiden Datenreihen durch einfaches
"copy & paste" aus dem HyperTerminal in ein
Tabellenkalkulationsprogramm (z. B. MS Excel) und erzeugt hieraus eine
Liniengrafik, so erkennt man, dass es sich
bei den gemessenen Hell-Dunkel-Werten um mehr oder weniger ausgeprägte
Sinuskurven
handelt:
Bei der rechten Messung mussten übrigens keine elektronischen Bauteile
ausgetauscht werden, sondern das Problem war die "schlabbernde"
Mechanik der Zahnräder. Man muss sicherstellen, dass die
Encoder-Scheibe sich
möglichst wenig entlang der Achse bewegen kann. das gelingt z. B. durch
etwas außen auf die Achsenenden aufgebrachtes Lötzinn oder eine
mechnische Halterung. Diode und
Transistor wurden mit zurecht geschnittenen und durch Wärme und Zange
oben geschlossenen Schrumpfschlauch gegen Fremdlicht abgedeckt. Das
geht noch besser mit kleinen Papphäusschen (innen schwarz), die man mit
Kleber auf der Platine befestigt. Damit
lässt sich weiter arbeiten. Nun sieht die Messung deutlich besser aus.
Sobald sich allerdings die Versorgungsspannung verändert, muss man neu
kalibrieren. Das ist eben "Asuro". Einfachste Technik, aber leider auch
maximale Variabilität! Gerade aus solchen Erfahrungen lernt man aber
für die Perfektionierung eigener Projekte.
In myasuro.h
kann man auf Basis von Messungen der Odometriewerte passende Grenzwerte
für die
Hell-Dunkel-Grenzen rechts und links getrennt setzen. Dies gilt auch
für die Längen- und Winkeleinstellung.
Wen wir gerade beim Kalibrieren sind, können wir uns auch um die
Längen- und Winkel -Einstellungen in myasuro.h
kümmern. Hier ein kleines Programm, das uns dabei helfen kann :
#include
"asuro.h"
#include
"myasuro.h"
int
main(void)
{
Init();
EncoderInit();
StatusLED (YELLOW);
Go(1000,150);
Msleep(1000);
Go(-1000,150);
Msleep(1000);
Turn(90,150);
Msleep(1000);
Turn(-90,150);
Msleep(1000);
Turn(-90,150);
Msleep(1000);
Turn(180,150);
Msleep(1000);
Turn(-450,150);
StatusLED (GREEN);
while (1);
return 0;
}
|
Man legt einen Meter neben den ASURO und kalibriert die
Längeneinstellung
#define
MY_GO_ENC_COUNT_VALUE 19750L /*!< GO Funktion,
Divisor fuer Entfernung */
und durch Betrachten der Drehwinkel die Einstellung für das korrekte
Drehen
#define
MY_TURN_ENC_COUNT_VALUE 140L /*!< Turn Funktion,
Mutiplikator fuer Winkel */
Die Längeneinstellung sollte man bei gutem Umgebungslicht mit ca. 1-2%
Genauigkeit
treffen. In der Sonne ging bei mir allerdings nichts!
Bei der Winkeleinstellung sieht es aufgrund der geringeren Zahl an
Impulsen schwieriger aus. Einen sauberen 90° Winkel habe ich nicht
geschafft.
Dieser ist vielleicht aber auch nicht notwendig.
Wir kalibrieren die
Taster des ASURO
Die sechs taktilen Sensoren - genannt "Taster" - werden raffiniert über
Widerstände über einen Analog-Digital-Konverter (ADC4) ausgewertet.
Hierbei muss man unbedingt die Werte 1,2,4,8,16,32 erhalten, wenn der
entsprechende Taster gedrückt wird.
Folgendes ist hierbei zu beachten, damit das richtig funktioniert:
1) Kalibration in myasuro.h
vornehmen:
/* Tastaturabfrage
*/
/*! Faktor
zur Berechnung der gedrueckten Tasten.\n
Der Originalwert ist \b 61L und koennten im Bereich zwischen ca. 58L und
65L schwanken. Dieser Wert gleicht Toleranzen der Widerstaende an den
Tastern aus.
*/
#define MY_SWITCH_VALUE
61L
/*!< Multiplikator fuer Tasterwerte */
Beginnen Sie mit 61 und testen Sie entsprechend dem unter 3)
angehängten Programm.
2) Der Wert aus myasuro.h
wird in Pollswitch(...)
in der Datei switches.c
verwendet:
unsigned
char PollSwitch (void)
{
unsigned int i;
int
ec_bak =
autoencode;
// Sichert aktuellen Zustand
/*
Autoencode-Betrieb vom ADC-Wandler unterbinden.
*/
autoencode = FALSE;
DDRD
|=
SWITCHES;
// Port-Bit SWITCHES als Output
SWITCH_ON;
// Port-Bit auf HIGH zur Messung
ADMUX
= (1 << REFS0) |
SWITCH; // AVCC reference with external
capacitor
Sleep
(10);
ADCSRA
|= (1 <<
ADSC);
// Starte AD-Wandlung
while
(!(ADCSRA & (1 << ADIF)))
// Ende der AD-Wandlung abwarten
;
ADCSRA
|= (1 <<
ADIF);
// AD-Interupt-Flag zuruecksetzen
i =
ADCL + (ADCH <<
8);
// Ergebnis als 16-Bit-Wert
SWITCH_OFF;
// Port-Bit auf LOW
Sleep
(5);
/*
Autoencode-Betrieb vom ADC-Wandler wiederherstellen.
*/
autoencode = ec_bak;
/*
Die Original Umrechenfunktion von Jan Grewe - DLR wurder ersetzt durch
eine Rechnung ohne FLOAT-Berechnungen.
return ((unsigned char) ((( 1024.0/(float)i - 1.0)) * 61.0 +
0.5));
Wert 61L evtl. anpasssen, falls fuer K1 falsche Werte zurueckgegebn
werden.
*/
return
((10240000L / (long)i - 10000L) * MY_SWITCH_VALUE
+ 5000L) / 10000;
}
3) Mit folgendem Programm kann getestet werden:
#include
"asuro.h"
int main(void)
{
int
radix = 10;
int
poll = 0;
char
wert[3];
Init();
while(1)
{
poll = PollSwitch();
int i;
for(i=0;i<3;++i)
wert[i]=' ';
itoa (poll, wert, radix);
SerWrite (wert, 3);
SerWrite ("\n\r", 2);
}
}
4) 1,2,4,8,16,32 - alles o.k.? Weiter.
5) Jetzt mehrere Taster drücken. Summe sollte stimmen. Nein? Go to 1)
Hinweis: Die Datei myasuro.h ist erst ab Version 2.7 der
ASURO-Bibliothek vorhanden.
Benutzer der Orginal-CD-Libary bzw. von Versionen vor 2.7 müssen die
Anpassung direkt in der Funktion PollSwitch()
in der Datei asuro.c
ändern.
ASURO folgt einer
Linie
Richtig interessant wird es, wenn man versucht, mit dem ASURO einer
Linie zu folgen. Dies ist eine klassische Aufgabe für jeden Roboter.
ASURO hat hierfür als Grundausstattung eine Leuchtdiode vorne in der
Mitte und links und rechts davon zwei
Fototransistoren. Die Differenz des Lichtes, dass bei den
Fototransistoren über die Reflektion von unten eintrifft und von diesen
in eine Spannungsdifferenz umgewandelt wird, verwendet man als
Eingangsgröße für einen
Regelprozess, der den ASURO z.B. symmetrisch auf einer schwarzen Linie
hält.
Die Umsetzung erfolgt durch Einstellung bzw. schnelle Veränderung der
Antriebsgeschwindigkeiten der beiden
Motoren. Wer dieses Thema ernsthaft angehen will, sollte versuchen, das
Prinzip des PID-Reglers
zu verstehen. Ich empfehle diesen
hervorragenden Artikel zum Einstieg.
Die mathematische Grundlage des PID-Reglers ist folgende Gleichung:
Die Funkltion y(t) ist hierbei die zeitabhängige Stellgröße und e(t)
die
zeitabhängige Regelabweichung (Differenz aus Ist und Soll). Eine
Regelung umfasst im Unterschied zu einer
Steuerung einen geschlossenen Regelkreis. Das
bedeutet, dass man eine Messgröße - in unserem Fall die Differenz der
Spannung zwischen linkem und rechtem Fototransistor - z.B. einem
Regelalgorithmus zuführt, der daraus eine Stellgröße errechnet, die man
für die Motorensteuerung verwenden kann. Auf diese Weise hält man den
ASURO auf einer Linie fest, bzw. man versucht es. Die jeweils gemessene
Größe (Istwert) ist x, der Sollwert u oder w. Die Abweichung e ist die
Differenz aus Soll und Ist. Der Regler generiert daraus ein y, das dann
über die "Regelstrecke" wieder zu einem neuen Istwert x führt. Die
Störgröße nennt man s oder z. In unserem Fall ist dies z.B. eine
Veränderung der Liniencharakteristik, die eine Veränderung der
Motorengeschwindigkeit erfordert. Schwierige Elemente sind scharfe
Knicke oder scharfe S-Kurven. Leicht sind Kreise oder Geraden.
siehe: http://www.hyperkommunikation.ch/lexikon/lexikon_index.htm
Eine genaue Betrachtung und ein Programm für den ASURO findet man hier:
http://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=11818&highlight=pid
Den entscheidenden Teil des Programms, der den PID-Regelalgorithmus
abbildet, ziehen wir noch einmal heraus:
x = don -
doff;
|
Abweichung |
yp
= x * kp;
|
P-Anteil berechnen |
isum
+= x;
if (isum > 16000) isum =
16000;
if (isum < -16000) isum = -16000;
yi
= isum / 625 * ki; |
I-Anteil
berechnen
Begrenzung um Überlauf zu
vermeiden
|
yd = (x -
xalt) * kd + drest;
if (yd >
255) drest = yd - 255;
else if (yd < -255) drest = yd + 255;
else
drest = 0; |
D-Anteil
berechnen und
nicht berücksichtigten Rest addieren
Rest merken
|
y = yp + yi + yd;
|
Stellgröße des PID-Reglers
|
Die Parameter kp, ki und kd müssen Sie auf Ihren individuellen ASURO
anpassen. Hoffentlich klappt es bei Ihnen halbwegs. Auf jeden Fall
lernt man auf diese Weise die PID-Regelung an einem konkreten
praktischen Beispiel kennen. Ihnen fehlt noch die richtige
Teststrecke? Voilà: linefollowing-arena_170.jpg
Beginnen Sie mit geraden Strecken und mit den Kreisen im Inneren. Dies
geht am einfachsten.
ASURO erhält eine
Navigationshilfe - Ultraschall
Was ist Navigation? Die Antwort findet man hier:
Unter Navigation
bezeichnet man das Sichzurechtfinden in einem
geografischen Raum, um einen bestimmten Ort zu erreichen. Die Tätigkeit
des Navigierens besteht aus drei Teilbereichen:
- Bestimmen der geografischen Position durch Ortung nach
verschiedensten Methoden
- Berechnen des Weges zum Ziel und
- Führung des Fahrzeugs zu diesem Ziel, also vor allem das Halten
des optimalen Kurses
Es
ist also eine zentrale Aufgabe beim Bau von Robotern. Es ist
sogar das Thema, das einen besonders großen Reiz auf die Bastler
ausübt.
ASURO ist im Originalzustand "fast blind". Seine Sensorik besteht aus
der Odometrie, mit der man die Radumdrehungen messen kann, einer
Linienverfolgungseinheit und sechs einfachen Tastern, die ihm eine
Kollision im vorderen Bereich melden können. Er muss also mit einem
Hindernis regelrecht zusammen stoßen, um darauf gezielt reagieren
zu können. Ein großer Nachteil sind die überstehenden Räder, mit denen
ASURO sich leicht "festfressen" kann. Auch beim Rückwärtsfahren ist er
blind. Diese Situation mit den taktilen Sensoren als Kollisionssensorik
ist grob vergleichbar mit dem
Niveau eines Paramecium
aurelia.
siehe:
http://upload.wikimedia.org/wikipedia/commons/c/cb/Paramecium.jpg
Paramecium
- Einzeller des Jahres 2007
Das Paramecium aurelia besitzt allerdings viel mehr "Taster", nämlich
ca. 10000 Stück, die man Wimpern (Cilien) nennt, als unser dagegen
primitiv wirkender ASURO. Auch in anderer Hinsicht ist es überlegen,
denn "bei Hindernissen kommt das
Pantoffeltierchen mit
Leichtigkeit hindurch, da es eine elastische Haut hat und sich mühelos
durchzwängen kann." ( http://de.wikipedia.org/wiki/Paramecium
)
Wie kann man hier beim ASURO weiter kommen, damit er den Wimpertierchen
in anderer Hinsicht etwas voraus hat? Ideal wäre eine Stereokamera und
ein richtiges "Gehirn". Aber da ist der ASURO weit davon entfernt. Eine
interessante Erweiterungsmöglichkeit wird in dem Buch "Mehr
Spaß mit ASURO Band 1" erwähnt, nämlich die Ausrüstung mit einem
Ultraschall-Sender und einem
Ultraschall-Empfänger. Die
Kosten hierfür betragen ca. 20 Euro, also eine erschwingliche
Angelegenheit.
In der Biologie kennt man das Echoortungssystem
mit Ultraschall z.B. bei
Fledermäusen. Einige nachtaktive Insekten als potenzielle Opfer
besitzen daher ein Ultraschallgehör.
Hier folgen einige Fotos eines meiner ASUROs nach der Erweiterung mit
einer (via ebay komplett mit allen Bauteilen erstandenen)
Ultraschall-Platine:
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO -
ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO -
ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO -
ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO -
ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -
ASURO - ASURO - ASURO - ASURO - ASURO - ASURO -ASURO - ASURO
Fotos: Dr. Erhard Henkes
Geopfert werden mussten bei diesem ASURO
die Linienverfolgungseinheit
(rote LED + 2 Fototransistoren vorne unten), da man diese Ein-/Ausgänge
des Microcontrollers leider benötigt. Hier werden die Schwächen des
ASURO offensichtlich! Bereits bei der ersten Erweiterung müssen
Elemente weichen. Daher empfiehlt es sich, mit mehreren ASUROs zu
experimentieren, um verschiedene Features parallel testen zu können.
Bei obigem Exemplar habe ich bereits beim Aufbau die Erweiterung im
Blick gehabt, die vordere LED und die beiden flankierenden
Fototransistoren also nicht erst eingelötet. Den halben Tischtennisball
fixierte ich nur mit einem Streifen Isolierband anstelle Heißkleber.
Mit dieser Vorgehensweise lässt sich die Erweiterung sauber und ohne
Probleme implementieren.
Die Verschaltung der Ultraschall-Erweiterungseinheit mit dem
Microcontroller des ASURO bitte
dem Buch "Mehr
Spaß mit ASURO Band 1" oder dem Roboternetz
entnehmen):
Der Sender ( Murata 400ST
(
Datenblatt ) oder Polaroid
40LT12 ) wird direkt an OC2
(Pin 17, Timer2) des ATmega8L angeschlossen. Das RC-Glied zwischen PD6
und VCC/2 erzeugt eine typische Entladungskurve und dient dazu, einen
"Ultraschall-Kurzschluss" zwischen Sender und Empfänger auszublenden.
Das physikalische Prinzip beruht darauf, dass man mit dem Sender einen
Ultraschallimpuls (ca. 40 kHz, "Chirp") aussendet, der durch Reflexion
an Hindernissen abgeschwächt und zeitversetzt beim Empfänger ankommt.
Die Schallgeschwindigkeit
in Luft bei 20°C beträgt 34,3 cm/ms und bei 25°C bereits
34,6 cm/ms. Kommt ein "Ultraschall-Echo" bei üblicher Zimmertemperatur
demnach nach genau einer Millisekunde zurück, so beträgt der Abstand
des Hindernisses etwa 17,2 cm. Für den Abstand gilt die Formel
Abstand [cm] = 0,5
* 34,4 cm/ms * Zeit [ms]
Die Software des Buches "Mehr
Spaß mit ASURO Band 1" hat sich mit der neuen ASURO-Bibliothek Version 2.7 leider
überholt, denn man hat hierbei nicht auf Kompatibilität mit älterer
Software geachtet. Funktionierende Software, mit der man sogar den
Abstand zum Hinderniss messen kann, findet man hier: http://www.roboternetz.de/phpBB2/viewtopic.php?t=31260
Deklarieren Sie folgende Funktionen in asuro.h:
void
InitUltrasonics(void);
void
RestoreAsuro(void);
int
Chirp(void);
Implementieren Sie die obigen Funktionen
in asuro.c.
Folgende Funktion muss sich in asuro.c
befinden:
ISR(TIMER2_COMP_vect)
{
//TCNT2 += 0x25;
// Auskommentieren. Wichtig!
count36kHz++;
if(!count36kHz) timebase++;
}
Der "Ultraschall-Teil" von asuro.c
sollte nach den obigen Manipulationen wie folgt aussehen (Dank an "dopez" und "m.a.r.v.i.n" aus dem "roboternetz", siehe hier: http://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=10907&postdays=0&postorder=asc&start=103)
Mit folgendem Programm können
Sie die Schaltung über das Hyperterminal testen und kalibrieren:
#include
"asuro.h"
int
abstand=0;
int
main(void)
{
Init();
SerWrite("\r\n ---
ultrasonic test ---",29);
Msleep(1000);
do
{
abstand = Chirp();
SerWrite("\r\n distanz in cm: ",20);
Msleep(500);
PrintInt(abstand);
}
while(1);
return
0;
}
Wenn Sie sich auf Dauer nicht mit dem bei
MS Windows mitgelieferten Programm "Hyperterminal" zufrieden geben
wollen, sondern ein völlig eigenes Programm auf dem PC entwickeln
wollen, dann sind Sie z.B. hier an der richtigen Stelle: http://www.codeproject.com/system/serial.asp
Laden Sie die Demo und compilieren Sie diese, schon haben Sie ihr
eigenes Terminal.
Als Einstellungen für die serielle
IR-Schnittstelle wählen Sie:
Daraufhin sollte es mit der Verbindung
zwischen ASURO und Computer via serieller Schnittstelle klappen
(Programm aus der Demo).
Der Vorteil eines Programms am PC, dessen Sourcecode sie ändern können,
besteht darin, dass ein eigenes Terminal gebastelt werden kann, das an
individuelle Ansprüche der Aufgabe angepasst ist. Hierzu benötigt man
allerdings die entsprechenden Programmiertools, z.B. MS Visual C++ 6.
Ich wollte auf diese Möglichkeit der individuellen GUI-Programmierung
an dieser Stelle nur hinweisen. Siehe: MFC-Tutorial
des Verfassers.
Einen Ausgangspunkt für
eigene Experimente mit ASURO und Ultraschall-Erweiterung finden Sie hier.
Der Code vergleicht die Ergebnisse zweier "Chirps", weil manchmal
gewaltige Sprünge im Messen auftreten, die nicht real sind. Ich gebe
hier bewusst einen nicht optimierten Code an. Optimieren Sie dieses
Programm und passen Sie es auf Ihre angestrebte Bewegungsstrategie
an. Erfolgreiche Ideen bitte im ASURO-Forum posten.
/*
Bewegung auf Basis Ultraschallortung
Dr. Erhard Henkes, Mai 2007
*/
#include
"asuro.h"
// incl. der Funktionen InitUltrasonics, RestoreAsuro, Chirp von
"dopez" (roboternetz)
#define
MAXDIFF 80
// Sehr große Sprünge zunächst ausblenden
int
main(void)
{
int
abstand, abstand_alt, diff, zaehler=0;
Init();
abstand = Chirp();
while(TRUE)
{
abstand_alt = abstand;
abstand = Chirp();
++zaehler;
diff = abstand - abstand_alt;
if( (abstand>15) && (abs(diff)<MAXDIFF) )
{
StatusLED(GREEN);
MotorDir(FWD, FWD);
MotorSpeed(150, 150);
}
else if( (abstand>10) && (abstand<=15) &&
(abs(diff)<MAXDIFF) )
{
StatusLED(GREEN);
MotorDir(FWD, FWD);
MotorSpeed(100, 150);
Msleep(30);
}
else
{
StatusLED(RED);
MotorDir(RWD, RWD);
MotorSpeed(150, 100);
Msleep(100);
}
if (zaehler > 400)
{
StatusLED(RED);
BackLED(ON,ON);
MotorDir(RWD, RWD);
MotorSpeed(200, 250);
Msleep(10);
BackLED(OFF,OFF);
}
if (zaehler > 405)
{
StatusLED(RED);
BackLED(ON,ON);
MotorDir(RWD, RWD);
MotorSpeed(250, 200);
Msleep(10);
BackLED(OFF,OFF);
if(zaehler > 410)
zaehler = 0;
}
}
return
0;
}
Lustige Videos mit ASURO
ASURO
fegt die Stube
ASURO erkennt die
Tischkante
ASURO
balanciert