Mittwoch, 1. September 2010

Windrad: Mikrocontroller AVR ATMega644

Ende Juli gab es in der direkten Umgebung ein schweres Gewitter. Nach einem sehr lauten Donner etwa zu Mittag gab die Netzwerkschnittstelle des Mikrocontrollers (Rabbit BL2000) den Geist auf. Sonst funktionierte er normal, nur gab es ab diesem Zeitpunkt keine Statistiken mehr (ein Ersatzcontroller um 250 Euro war mir zu teuer).

Ich hatte aber sowieso schon länger vor die Regelung auf einen ATMega Controller von AVR umzustellen. Diese Teile können beinahe genausoviel, kosten aber nur einen Bruchteil (Prozessor etwa 5 Euro, gesamtes Entwicklungsboard mit Netzwerk-Chip etwa 27 Euro). Ich kaufte das bekannte fertige Entwicklungsboard AVR-NET-IO bei Pollin und setzte sofort den etwas besseren Prozessor ATMega644 ein (64kByte Flash Speicher statt 32kByte beim ATMega32).



Sofort musste ich zur Kenntnis nehmen dass die Umstellung doch sehr viel Arbeitszeit verschlingen würde. Damit ich mit dem Controller Netzwerkverbindungen aufbauen kann brauche ich einen TCP/IP Stack und möglichst komfortable Programme / Dienste dazu (zB: HTTP-Server, HTTP-Client usw.). Diese Dinge funktionierten mit dem Rabbit Board wirklich einfach. Für den AVR Controller musste ich alles neu umsetzen.

Nach langem Suchen bin ich auf das Projekt OpenMCP gestossen. Die Software funktioniert problemlos mit dem ATMega644er Prozessor und dem Netzwerkchip ENC28j60 welcher am Pollin Board verbaut ist. Man programmiert genauso in C, eigene Programme lassen sich einfach zum Gesamtsystem ergänzen. Ich finde diese Software ist sehr aufgeräumt und bietet genug fertige Funktionalität um einfache Anwendungen umzusetzen. Es gibt zum Beispiel fertige Bibliotheken für

  • Netzwerkkonfiguration (IP einstellen, ab dann funktioniert mal ICMP)
  • Webserver mit CGI Funktionalität (ist einfach einzubinden)
  • NTP zur Zeitsynchronisierung übers Netzwerk
  • einfacher Zugriff auf AD-Wandler
  • einfacher Zugriff auf Digital Ein/Ausgänge (GPIO)
  • Bibliotheken für Netzwerkverbindungen (damit kann man zB relativ einfach eine HTTP-Anforderung senden)
  • automatische Uhrzeit/Datumsfunktionen, einfache Verwendung von Timern
  • und vieles mehr....
Jedenfalls habe ich nun endlich die erste lauffähige Version fertig. Ich habe eine Erweiterungsplatine angefertigt welche am 25poligen Anschluss des Pollin Boards angeschlossen wird. Auf diesem Board sind nur Kleinigkeiten drauf (Spannungsversorgung, Spannungsteiler für ADC's und Anschlüsse für diverse Ein/Ausgänge). Seit heute Mittag läuft nun diese Anlage:


Endlich habe ich also wieder Statistiken von unserem Windrad im Netz. Ich hoffe dass dieser Controller stabil läuft...

Kommentare:

  1. Hallo,

    auch wenn dieser Beitrag schon etwasd älter ist...
    Ich bin auch gerade dabei, OpenMCP mit dem Pollin-Board zu verwenden und würde gerne empfangene Daten an einen Webserver per HTTP-Request übertragen, also Aufruf einer URL a-la http://www.meinserver.de/empfang.php?daten=blabla
    Die TCP-Funktionen habe ich schon gefunden, nur leider kein Beispiel, in welcher Reihenfolge ich welche Funktion aufrufen muss.
    Haben sie vielleicht ein Beispiel?

    Danke,
    Dennis

    AntwortenLöschen
  2. da kann ich folgendes anbieten: (hoffentlich bleibt es lesbar im Kommentar)

    // jetzt die URL aufrufen
    struct STDOUT oldstream;
    int SOCKET = -1;
    long IP;
    int connectTries = 3;

    // URL auflösen
    IP = DNS_ResolveName_P( PSTR(WEBSERVER) );
    if ( IP == -1 ) {
    sprintf(lastLogMsg, "DNS Fehler");
    return;
    }

    // zum Webserver verbinden
    while (connectTries > 0 && SOCKET < 0) {
    #if defined(WATCHDOG)
    wdt_reset();
    #endif
    SOCKET = Connect2IP( IP, 80 );
    connectTries--;
    }
    if ( SOCKET == -1 ) {
    sprintf(lastLogMsg, "Timeout bei Verbindung zu Webserver");
    return;
    }

    // STDOUT umbiegen auf die neue Verbindung und alten STDOUT sichern
    STDOUT_save( &oldstream );
    STDOUT_set( _TCP, SOCKET );


    // Request senden
    printf_P( PSTR(WEBURL),
    intervalStateMean.voltageGenerator,
    intervalStateMean.currentGenerator,
    (int)intervalStateMean.rpm,
    intervalStateMean.voltageBat,
    frequ,
    intervalStateMean.vwind,
    intervalStateMax.voltageGenerator,
    intervalStateMax.currentGenerator,
    (int)intervalStateMax.rpm,
    intervalStateMax.voltageBat,
    intervalStateMax.vwind,
    intervalStateMax.powerGenerator,
    intervalStateMean.energy,
    dumpload,
    intervalStateMean.bremse,
    intervalStateMean.ladung,
    stop,
    Zeit.uptime
    );

    printf_P( PSTR("\r\n") );
    printf_P( PSTR("\r\n") );

    // Gesicherte STDOUT wieder herstellen
    STDOUT_restore( &oldstream );
    CloseTCPSocket( SOCKET );

    AntwortenLöschen