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:

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 << BitN
ummer); // 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
(
// Eigentliches Programm
}
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():
{
/* Timer2, zum Betrieb mit der seriellen Schnittstelle, fuer die IR-Kommunikation auf 36 kHz eingestellt. */
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
OCR2 = 0x91; // duty cycle fuer 36kHz
TIMSK |= (1 << TOIE2); // 36kHz counter

/*
Die serielle Schnittstelle wurde waehrend der Boot-Phase schon programmiert und gestartet.
Hier werden die Parameter auf "2400 1N8" gesetzt.

*/
UCSRA = 0x00;
UCSRB = 0x00;
UCSRC = 0x86; // 1 Stop Bit | No Parity | 8 Data Bit
UBRRL = 0xCF; // 2400 bps @ 8.00 MHz

/*
Datenrichtung der I/O-Ports festlegen. Dies ist durch die Beschaltung der Asuro-Hardware nicht aenderbar.
Port B: Richtungsvorgabe Motor links;
Gruenanteil-Status-LED
Seriell Senden;
Takt fuer die Geschwindigkeit beider Motoren;
Port D: Richtungsvorgabe Motor rechts;
Rotanteil-Status-LED
Vordere LED;
Odometrie-LED (Radsensor);

*/
DDRB = LEFT_DIR
| GREEN_LED | IRTX | PWM ;
DDRD = RIGHT_DIR | RED_LED
| FRONT_LED | ODOMETRIE_LED ;

/* PWM-Kanaele OC1A und OC1B auf 8-Bit einstellen. Sie werden fuer die Geschwindigkeitsvorgaben der Motoren benutzt. */ TCCR1A = (1 << WGM10) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = (1 << CS11); // tmr1-Timer mit MCU-Takt/8 betreiben.
/* Einstellungen des A/D-Wandlers auf MCU-Takt/64 */ ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);

/* Sonstige Vorbereitungen. - Alle LED's ausschalten - Motoren stoppen und auf Vorwaerts stellen. - Globale Variable autoencode ausschalten. */ ODOMETRIE_LED_OFF;
FrontLED (OFF);
BackLED (ON, ON);
BackLED (OFF, OFF);
StatusLED (GREEN);

MotorDir (FWD, FWD);
MotorSpeed (0, 0);

autoencode = FALSE;

/* Funktion zum ALLGEMEINEN ZULASSEN von Interrupts. */ 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:

/* Timer2, zum Betrieb mit der seriellen Schnittstelle, fuer die IR-Kommunikation auf 36 kHz eingestellt. */
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
OCR2 = 0x91; // duty cycle fuer 36kHz
TIMSK |= (1 << TOIE2); // 36kHz counter
//...

SIGNAL (SIG_OVERFLOW2)
{
TCNT2 += 0x25;
//...

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); // Rad-LED's OFF DDRC |= (1 << PC0) | (1 << PC1); // Port als Output => KEINE Odometrie 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:

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


wird fortgesetzt