[AVR GCC Kurs] Steuerung eines DC-Motors

  • Dies ist also nun der "offizielle" Thread zu unserer kleinen Programmier-Session.


    Ich werde versuchen, um 16.00h von meiner Arbeit wieder zurück zu sein, damit wir dann langsam beginnen können.


    Eine Bitte vorweg:
    Bitte postet nur direkt zu diesem Thema. (Falls schon direkt am Anfang Fragen zu LCDs oder Stepper gestellt und beantwortet werden, steigt später niemand mehr durch den Thread durch...)
    Falls sich einige Spezialisten nicht daran halten - bitte nicht darauf eingehen!
    (Wenn der Motor erst mal schnurrt, können wir uns gern andere Themen oder Problemen widmen...)


    Was Ihr bis heute nachmittag schon tun könntet:
    Installiert ein halbwegs aktuelles AVR-Studio. (Bei mir läuft Version 4.13.571. Die Version wird anfangs im Project Wizard eingeblendet.)


    Installiert ein stabiles WinAVR. (Bei mir läuft noch 20071221. Die neueren erzeugten bei mir eine niedrigere Codedichte...)


    Zieht Euch das vollständige Datenblatt vom ATmega8515. Folgende Abschnitte sind besonders interessant:
    USART Reception (für DMX)
    Timer (für PWM)
    Ports


    Blättert kurz das C-Tutorial bei mikrocontroller.net durch, dass Ihr ungefähr im Kopf habt, wo was steht.


    Zieht Euch mein Archiv für den DMX-Empfang und überfliegt schon einmal die AN012.


    (das hört sich nach viel an - ist aber alles in 2-3h erledigt...)


    bis später,
    Henne

  • ich wäre dann da...


    *ping*


    Dann schau ich um 18.00h noch mal vorbei...


    bis dann.

  • [Hier noch was Organisatorisches]


    Sorry für die Termin-Verwirrung. Mir war auch nicht klar, dass Henne schon Freitag 16 Uhr anfangen wollte. Also - nun beginnen wir heute abend 18 Uhr. Leider müssen wir wohl mit einigen rechnen, die dann erst morgen dazukommen.


    Leider ist Rudi's Server heute morgen down gegangen und er konnte den Chat noch nicht wiederaufsetzen.


    Übrigens, das von Hendrik erwähnte Dokument AN012 findet man hier:
    http://www.hoelscher-hi.de/hendrik/light/ressources.htm


    Frank

  • Dann wollen wir mal:


    Wir werden die meiste Zeit mit dem AVR-Studio arbeiten. Hierbei handelt es sich um eine IDE (integrated development environment) für AVR-Microcontroller.
    Dort schreiben wir den Code und simulieren ihn auch. Zum Kompilieren ruft das AVR-Studio Programme auf, die Ihr mit WinAVR installiert habt. (Theoretisch kann man also auch nur mit WinAVR programmieren - finde ich aber weniger durchgängig...)


    Die fertigen Hex-Files werden dann wie gewohnt mit PonyProg, etc. auf den AVR übertragen.

  • Startet das AVR-Studio.


    Der Project-Wizard erscheint:
    Beginnt ein neues "AVR GCC" Projekt.
    Wählt als Name z.B.: Motor und lasst auch gleich einen Ordner und ein initial file erstellen.
    Wählt einen Pfad, wo Ihr alle Projektdateien abspeichert mit "Location".
    (bei mir: C:\eigene Programme\Rev3_0\)


    Klickt dann auf "Next"

  • Wählt den "AVR Simulator" als Debug Platform und als Device den ATmega8515.


    Klickt auf Finish.


    Nun habt Ihr schon mal die wichtigsten Einstellungen.


    (BTW: Mit speziellen Tools kann direkt die Hardware als debug platform genutzt werden. Dazu tauscht das AVR-Studio permanent mit dem AVR den Status aus und visualisiert ihn im Simulator. Der mega8515 kann das aber noch nicht...)

  • Es werden nun drei Fenster angezeigt:


    Links das Projektverzeichnis:
    In Source Files werden die einzelnen Dateien mit dem Quellcode eingefügt. Die Dateien haben die Endung .c (C-Files), .s (Intel-Assembler Files. Achtung: Dieser Code ist nicht mit dem AVR-Assembler identisch!!) oder .cpp (C++ Files).


    In Header Files werden Dateien mit Bekanntmachungen für andere Source Files eingefügt.
    In diesen Headern stehen globale Variablen, Funktionen die von anderen Dateien aufgerufen werden, Aufzählungen - halt Alles was Ihr von außen bei einer Quellcode-Datei beeinflussen möchtet.


    Der Rest ist erst einmal weniger spannend.



    Unten die Compiler-Meldungen:
    Habt Ihr Unfug gemacht, meckert dort der Compiler, Linker, was-auch-immer. Wenn Alles gut geht, zeigt er Euch an, wie groß der Code ist und wieviel Platz noch bleibt...


    Das Wichtigste ist nun aber erst mal das große leere Fenster: der Editor.
    Hier tippen wir den Code ein.


    Seid Ihr noch dabei?

  • [Chat geht nicht...]


    Nun beginnen wir mal mit dem ersten Programm:


    Zunächst ein paar Kommentare, damit man in ein paar Jahren noch durchsteigt:


    /* DMX Motorsteuerung
    Version: 0.1
    Datum: 15.08.08
    Autor: H.Hölscher (www.hoelscher-hi.de)
    Target: DMX Transceiver @8MHz
    Lizenz: GPLv2
    */


    Dann binden wir ein paar Definitionen ein, mit denen wir später arbeiten wollen:


    #include <avr/io.h>
    #include <stdint.h>
    #include <avr/wdt.h>


    Die "io.h" sagt dem Kompiler, was wir mit typischen Peripherienamen, etc. meinen und übersetzt sie in die physikalische Adresse. So können wir zum Beispiel schreiben:
    "PORTA= 0xFF;" und nicht "0x23= 0xFF"
    Natürlich sind die physikalischen Adressen bei jedem AVR-Typ anders - aber deshalb haben wir ja bereits festgelegt, dass wir mit einem mega8515 arbeiten.


    Die "stdint.h" erklärt dem Compiler was wir mit verschiedenen Variablentypen meinen. Andernfalls kann der GCC nichts mit "char", "integer" oder "short" anfangen und wirft Fehlermeldungen.


    Die "wdt.h" läst uns auf den Watchdog zugreifen.
    Wenn dieser Wachhund nicht alle paar ms von uns zurückgerufen wird, startet er den AVR neu. Somit stehen wir bei einem Absturz des AVRs nicht im Dunkeln sondern sind nach <1s wieder dabei ;)
    Da ich ihn sicherheitshalber gern schon mit den fuses aktiviere, rufen wir ihn einfach sicherheitshalber einfach zurück - auch wenn wir ihn zunächst gar nicht initialisieren...

  • Dann deklarieren wir unsere erste Variable:


    uint16_t count;


    Dies ist eine nicht-negative (unsigned) Variable mit 16bit, die wir "count" nennen.
    Count kann also einen Wert von 0 bis 2^16, also 65535, annehmen.


    Jetzt fehlt eigentlich nur noch der erste spektakuläre Code:



    Das Hauptprogramme lautet immer:
    int main(void)
    {
    }
    Es heißt also main, bekommt beim Aufruf keine Werte mit und gibt einen Integer (beim Absturz...) zurück.


    Zunächst initialisieren wir PortA sicherheitshalber als Ausgang, indem wir das Datenregister auf 0b11111111 (also 0xFF) setzen und machen alle Pins LOW.


    Dann initialisieren wir PortD in ähnlicher Weise. (Schaut mal in den Schaltplan auf meiner Seite - dann seht Ihr den Sinn der Werte ;)


    Nun kommt eine for-Endlosschleife, damit wir nicht den Code ein Mal abarbeiten und dann abstürzen.
    Darin setzen wir zunächst den Watchdog zurück.
    Dann ziehen wir 1 von count ab (count= count -1;) und schauen anschließend, ob wir 0 erreicht haben.
    Wenn ja, läuft count über und wir wechseln den Status der LED an PortD, Pin7. (Wer mit dem Exklusiv-Oder Probleme hat, sollte noch mal in das C-Tut auf mikrocontroller.net linsen...)

  • anbei noch mal der Code...


    Nach dem Abspeichern drückt Ihr Strg+F7 und kompiliert damit das Programm und startet den Simulator.


    Das Nachrichtenfenster sollte nun zeigen, dass die Geschichte erfolgreich war und 180byte Programmcode erzeugt wurde.


    Das ist ziemlich viel für die paar Zeilen - deshalb klicken wir auf das Zahnrad-Icon (von mir aus auch Schnecke - auf jeden Fall neben dem blauen X) und wählen als Optimization "-0s" und kompilieren noch mal.


    Siehe da: 130bytes :D


    BTW:
    -0o: keine Optimierung
    -01..-03: Optimierung der Geschwindigkeit
    -0s: Optimierung der Codegröße. (Wenig Code geht auch schneller ;)

  • Nun klickt Ihr bei "Debug" auf "AVR Simulator Options" und wählt 8MHz als Frequenz.


    Nochmal kompilieren.


    Nun kann mit Tippen von F11 Schritt für Schritt der Code durchlaufen werden.


    Das Ergebnis seht Ihr links, wenn Ihr den I/O-View Reiter anwählt.


    Das Hex-File findet Ihr in dem default-Ordner innerhalb Eures Projekt-Ordners. Wenn Ihr es mit PonyProg auf den Transceiver überspielt, flackert die rote LED mit 16-20Hz.


    =====
    Ich lass Euch jetzt erst Mal 30min werkeln und ess was - dann können wir mal DMX einbinden 8)

  • Zunächst fügt Ihr die "lib_dmx_in.c" und die "lib_dmx_in.h" aus dem Archiv "rxd.zip" in Euer Projektverzeichnis ein.


    Dann geht Ihr links im AVR-Studio auf den Reiter "AVR GCC" und fügt die lib_dmx_in.c zu den source files und die lib_dmx_in.h zu den Header Files.


    Nun möchten wir ja mit unserem Hauptprogramm Funktionen aus der Lib nutzen können. Dazu müssen wir die Header Datei oben in Eurem Code bekannt machen:


    #include "lib_dmx_in.h"


    (Die io.h und stdint.h können wieder entfernt werden, da ich sie in der Header Datei einbinde...)


    Damit die Initialisierung etwas strukturierter aussieht, bekommt sie eine eigene Prozedur:


    Code
    void init_system(void){DDRA=  0xFF;                 //low outputsPORTA= 0;DDRD=  0b10000110;	    //DMX, spare, LED1PORTD= 0b01111010;init_DMX();		    //initialisiere DMX-Empfang}


    Über init_DMX () rufe ich den Initialisierungscode aus der Lib auf und muss mich nicht weiter darum kümmern.


    Nun zum Hauptprogramm:



    Mit cli sperre ich zunächst die Interrupts, damit mir kein Ereignis dazwischenfunkt. Dann initialisiere ich den Transceiver und gebe die Interrupts wieder frei.
    Mit get_dips() lese ich die Startadresse ein.
    Und danach schau ich nur noch, ob mein erster Kanal >50% ist. Falls ja, knipse ich die rote LED an.

  • anbei der Quellcode...


    Interessant ist noch der Header:
    Durch
    #define DIPSWITCH
    aktiviere ich die Funktion zum Auslesen der DIPs


    Da ich zunächst zwei DMX Kanäle einlesen möchte, setze ich:
    #define DMX_CHANNELS (2)


    Und da wir einen Quarz mit 8MHz verbaut haben heißt es:
    #define F_OSC (8000) //Quarzfrequenz in kHz



    Wenn Ihr soweit seid, können wir mal Alles simulieren...

  • Gut, dass Du fragst, Frank:
    In C werden alle Variablen immer automatisch mit 0 initialisiert, wenn nichts anderes angegeben ist.


    (Ob das allgemeiner Standard ist, weiß ich aber nicht...)

  • Da gibt es mehrere Möglichkeiten:


    Maus über Variable halten
    Das klappt meist bei einfachen Variablen. Bei Arrays oder Strukturen geht das nicht.


    Du schaust im Memory-Fenster (Tabellen-Icon) in das SRAM (Data).
    Falls Du dort nicht fündig wirst, schau in die Register.
    Wo was liegt, wird Dir wieder angezeigt, wenn Du die Maus über die Varable hältst.


    Das Alles geht natürlich erst nach dem Kompilieren im Simulationsmodus ;)


    PS: Ich habe grad noch mal geguckt - bei mir wird count komplett in den Registern gehalten und das SRAM-Spiegelbild wird nicht aktualisiert. Dies darf der Compiler, da ich count nicht als "volatile" deklariert habe. (Aus diesem Grund sind alle Variablen, auf die sowohl Hauptprogramm und ISR (interrupt service routines) zugreifen, als volatil gekennzeichnet!)



    Bereit für "DMX für Erwachsene"??

  • Newly created posts will remain inaccessible for others until approved by a moderator.

    The last reply was more than 365 days ago, this thread is most likely obsolete. It is recommended to create a new thread instead.