Daten loggen über I2C (IOWarrior24)

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Hallo allerseits!

Das ist mein erster Eintrag hier, ich bin fange gerade erst an mit der IOWarrior-Programmierung.

Zunächst einmal mein Anliegen:
Ich will über den IO-Warrior mit einem I2C-Temperatursensor kommunizieren. Nach der Initialisierung sollen Temperaturwerte in bestimmten Zeitintervallen kontinuierlich bspw. in eine Textdatei ausgegeben werden (so dass eine Weiterverarbeitung bspw. in Excel möglich ist).

Bisher habe ich den IOWarrior mit dem Simple-I2C-Tool erfolgreich getestet.
Außerdem habe ich den Labview-Treiber von Hartwig habe ausprobiert.. Leider erscheint bereits bei einem einfachen read die Fehlermeldung "IIC send error" (ich habe nur einen open-block, einen I2C_readA-Block und einen close-block hintereinander geschaltet).
Weiß einer, woran das liegen könnte?

Ist es vielleicht einfacher, das Simple-I2C-Tool so zu erweitern, dass damit nach einem entsprechenden Button-Klick kontinuierlich Daten in eine Text-Datei geloggt werden? Wenn ja, welche Schritte wären dafür nötig?
Eine Konsolenausgabe gemäß cout oder das Schreiben in eine Textdatei mit fstream werden zwar vom Compiler nicht angemeckert, haben aber auch sonst keine Auswirkung bei der Ausführung (wahrscheinlich weil das Projekt ja keine Konsolen- sondern eine Win-Applikation ist).

Irgendwelche sinnvollen Tipps? Wie würdet Ihr da dran gehen?

Gruß,
Pjay
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by Christoph Jung »

um welchen I2C-Chip handelt es sich denn?

Ich habe glaub ich eine Anwenung, mit der man Temperaturen loggen kann. Muss mal schaun wo ich die habe. Das Simple I2C-Tool umzubauen macht mehr Arbeit, als sich ein passendes tool selber zu schreiben, egal ob Consolenprogramm oder Win-Applikation.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Hallo!
Beim Temperatursensor handelt es sich um den ADT7420 von Analog Devices (http://www.analog.com/en/mems-sensors/d ... oduct.html).
Auch wenn der Sensor nicht der Gleiche sein sollte wie Ihrer/Deiner, so würde mir das Programm sicherlich trotzdem weiterhelfen, weil ich dann schon mal eine Basis hätte (also egal was: bitte an Pjay85@web.de!!).

Grüße,
Pjay
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by Christoph Jung »

So ich hab mal geschaut und hab nur ein Programm für einen SPI Temperatursensor. Leider nichts, was mit I2C zu tun hat in der Richtung.

Wegen des LabView-Problems. Ist denn auch der I2C initialisiert worden? Denn ohne den Special-Mode "I2C" wird das nichts mit dem lesen.
Kenn mich da aber mit Labview auch nicht aus.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Schade..
Die Initalisierung habe ich durchgeführt (die war auch erfolgreich). Nur der write- und der read-Befehl wollen nicht...

Ich finde es auch blöd, dass es kein vernünftiges Beispiel für Windows mit C-Programmierung (Konsolenanwendung!) gibt... nicht jeder hat Visual Studio, und C ist eine beliebte Programmiersprache.
Was mir fehlt ist einfach ein Netbeans oder Eclipse-Project mit allen nötigen Bibliotheken eingebunden und einem kleinen Beispiel..
Naja, ich versuch mal selber was auf die Beine zu stellen.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by Christoph Jung »

In dem SDK ist ein Beispiel für Simple-IO enhalten, was in reinem C geschrieben ist. Vllt. hilft das ein wenig Weiter.
Wer allerdings C kann, sollte mit dem Sourcecode vom Visual Studion klar kommen, bzw. den lesen können. Der Programmablauf ist der selbe.

Wir können leider nicht alle IDEs unterstützen, dafür gibt es einfach zu viele. Und zur not kann man sich ja mal Visual Studion Express besorgen. Das ist kostenlos und hat eine komplette C-Umgebung.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Ich habe jetzt mal damit begonnen, meine eigenes kleines Log-Programm zu schreiben.

Ich kann nun endlich alles in meinem Netbeans compilieren, IowKitOpenDevice und IowKitCloseDevice sowie das Initialisieren von I2C scheinen auch schon mal zu funktionieren.
Jetzt geht es an das Auslesen von Daten... Dazu habe ich mir folgende Funktion geschrieben:

/* Read I2C-data */
void ReadI2C(IOWKIT_HANDLE ioHandle, UCHAR adr, UCHAR numbytes)
{
IOWKIT_SPECIAL_REPORT report;
ULONG res;

memset(&report,0x00,IOWKIT_SPECIAL_REPORT_SIZE);
report.ReportID = 0x03; // I2C-Read-Mode
report.Bytes[0] = numbytes; // number of bytes to be read
report.Bytes[1] = adr; // Adress for read

/*read bytes*/
(void) IowKitWrite(ioHandle, IOW_PIPE_SPECIAL_MODE, (char*) &report, IOWKIT_SPECIAL_REPORT_SIZE);

memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);

IowKitRead(ioHandle, IOW_PIPE_SPECIAL_MODE, (char*) &report, IOWKIT_SPECIAL_REPORT_SIZE);

if(report.Bytes[0] & 0x80)
{
printf("Error beim Lesen!\n");
}
else
{
printf("Lesen erfolgreich");
}
}

Leider landet das programm im Teil mit "Error beim Lesen" (weil das MSB des "0." Bytes = 1 ist, und demnach ein Fehler vorliegt).
Mit der Funktion lese ich die eigentlichen Daten natürlich nicht aus, ich wollte erstmal überprüfen, ob meine Vorgehensweise korrekt ist, weil ich nicht sicher bin, wie das mit dem Auslesen von Daten funktioniert:
Der obere Teil der Funktion (bis zum IowKitWrite) ist denke ich so implementiert, wie im IOWarrior-datasheet beschrieben... Ich weiß nur nicht so ganz, wie ich dann an die gelesenen Bytes komme.
Im IOWarrior-datasheet steht "Data is returned in input reports with ID=3 (which is different from the output Report ID=3 used to initiate the read transaction) via endpoint 2. The data is returned in chunks of up to six bytes eachwith an error flag and byte count. Multiple reports may be returned in reaction to a read request:
ReportID: $03 in
1: flags
2-7: data"

Sorry aber ich verstehe das nicht ganz. Muss ich direkt nach dem Write einen Read durchführen (so wie oben im Code)? Mit dem Return-Wert kann ich ja nicht viel anfangen, der sagt mir ja was anderes.

Über Support wäre ich dankbar...

Gruß,
Pjay
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by Christoph Jung »

Der Code-Ausschnitt sieht erstmal richtig aus.
Das, was gelesen wird, wird in report.Byte[] gespeichert. Darum auch das memset(...) vor der Read-Funktion um sicherzustellen, das nichts, bzw. 0 in report steht.

Wichtig, die Adresse zum lesen ist eine andere als beim schreiben.
Wenn die Adresse zum schreiben 0x20 ist, dann ist die zum lesen 0x21.

Das was das Datenblatt dort sagt ist einfach nur, dass man in einem Lesezyklus des IOW24 nur 6 Bytes lesen kann. Wenn man mehr haben möchte muss man nach dem Read ein weiteres Read für die Nächsten 6 Byte starten. Vorher natürlich die Report.Bytes zwischenspeichern.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Danke für die Info!
Ich hatte eine falsche Adresse verwendet, ich habe vergessen, die Nullen (bzw. hier die Null) aufzufüllen bis ich den Byte voll habe (01001000). Das mit dem zusätzlichen Bit war auch eine wichtige Information.

Mittlerweile bin ich auch schon ein großes Stück weiter, bin aber gerade in Eile.. nächste Woche geht's dann weiter ;-)

Danke bis hierhin...
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Hallo Herr Christoph Jung!
Ich habe den Code mittleweile soweit erweitert, dass ich an die Temperaturwerte des Sensors herankomme (1 byte MSB und 1 byte LSB).
Was ich derzeit erfolglos versuche ist, die beiden Bytes mit den Temp.-Werten wiederholt auszulesen:

Code: Select all

int main(int argc, char** argv) {

    ioHandle = IowKitOpenDevice();

    if ((f = fopen("Temperatur-Ausgabe.txt", "w")) == NULL) {
        printf("Fehler bei Erstellen der Datei! \n");
        exit(1);
    }

    if (ioHandle != NULL) {
        printf("success, access device \n");

        /* init I2C-Port */
        init_i2c(ioHandle); 
        
       for (j = 0; j < repeat; j++) {
            memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);
            report.ReportID = 0x03; // I2C-Read-Mode
            report.Bytes[0] = 2; // number of bytes to be read
            report.Bytes[1] = address | 0x01; // Adress for read

            /*read bytes*/
            IowKitWrite(ioHandle, IOW_PIPE_SPECIAL_MODE, (char*) &report, IOWKIT_SPECIAL_REPORT_SIZE);
            IowKitRead(ioHandle, IOW_PIPE_SPECIAL_MODE, (char*) &report, IOWKIT_SPECIAL_REPORT_SIZE);

            if (report.Bytes[1] & 0x80) {
                printf("Error beim Lesen!\n");
            } 
            else {
                printf("Lesen erfolgreich \n");
            }
            
            temp_shifted = (unsigned int) report.Bytes[1];
            temp_shifted = (temp_shifted << 8);
            temp = (unsigned int) (temp_shifted ^ report.Bytes[2]);
            temp = ((temp >> 3)*10) / 16;
            printf("temp = %d\n",  temp);
            wait(2); /* 2 Sekunden Verzögerung vor dem nächsten Aufruf*/
       //   fprintf(f,"Temperatur: %d\n",temp);
        }        
             IowKitCloseDevice(ioHandle);
    }
    else 
    {
        printf("didn't open IoWarrior, handle error");
    }
    printf("ende \n");
    return (EXIT_SUCCESS);
}
Sobald ich die Variable repeat auf mehr als 1 setze, erhalte ich ein "RUN FAILED"... woran kann das liegen?

Viele Grüße,

Pjay
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by Christoph Jung »

Zum einen erfüllt die if-Abfrage in der Schleife keinen Sinn. Entweder rausnehmen oder den Berechnungsblock in das else einbauen.
Desweiteren würde ich wait() durch sleep() ersetzen. Das ist nicht so CPU-Intensiv. Ein Wert von 2000 entspricht 2 Sekunden.


Woher kommt dieser Fehler? erzeugt das das Programm oder kommt vom Sensor diese Fehlermeldung. Ich sie dieses "RUN FAILED) nirgends.

Evtl. sollte vor dem Lesen noch einmal der Zeiger auf das Startregister gesetzt werden, denn wenn der Sensor das selber hochzählt ist er nicht mehr
in den Register, wo die Werte für die Temperatur stehen.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

Christoph Jung wrote:Zum einen erfüllt die if-Abfrage in der Schleife keinen Sinn. Entweder rausnehmen oder den Berechnungsblock in das else einbauen.
Desweiteren würde ich wait() durch sleep() ersetzen. Das ist nicht so CPU-Intensiv. Ein Wert von 2000 entspricht 2 Sekunden.
Für sleep muss ich windows.h einbinden. Einige Definitionen darin überschneiden sich mit denen der iowkit-API, daher bin ich auf wait ausgewichen.
Woher kommt dieser Fehler? erzeugt das das Programm oder kommt vom Sensor diese Fehlermeldung. Ich sie dieses "RUN FAILED) nirgends.
Der Fehler wird vom Debugger automatisch ausgegeben... bei einem Durchlauf wird "RUN SUCCESFUL" in der Konsole angezeigt, sonst wird "RUN FAILED (exit value 1)" angezeigt. Zuvor werden aber ganz normal und ohne Fehlermeldung die printfs ausgegeben (allerdings wird die Textdatei nicht korrekt beschrieben).
Evtl. sollte vor dem Lesen noch einmal der Zeiger auf das Startregister gesetzt werden, denn wenn der Sensor das selber hochzählt ist er nicht mehr
in den Register, wo die Werte für die Temperatur stehen.
Welchen Zeiger soll ich auf welches Register setzen? Ich führe doch das memset und die Initialisierung der report-Daten innerhalb der for-schleife aus...

Aus dem IOWarrior-Datensheet geht leider nicht 100%ig hervor, wie das genau mit dem Lesen abläuft.

Eigentlich ist die Addresse des Temp.-Sensors 1001000 = 0x48... Wenn ich das Confiurationsregister des Sensors beschreiben möchte, dann klappt das auch nur mit dieser Addresse.
Beim Lesen muss ich die Addresse 10010000 = 0x90 angeben, damit das klappt. Wieso ist das so?
Ich wundere mich, warum das mit dem Lesen überhaupt geht... um die beiden Temperatur-Bytes auszulesen, muss gemäß Datenblatt nach der Device-Addresse (1001000) eigentlich die Register-Addresse gesendet werden, erst dann werden die beiden Bytes vom Sensor gelesen (s. Anhang).
Gemäß dem IOWarrior-Datasheet kann (neben "count") aber nur 1 Byte an Addresseninformation ("command") verschickt werden.. warum also werden scheinbar die Temperaturbytes ausgelesen, wenn ich command = 0x90 verwende??
Ich denke ich muss mir da noch was mit einem write vor dem read, dann aber mit der Addresse 0x48 überlegen.

Für Infos wäre ich sehr dankbar, weil ich gerne verstehen würde, was ich da genau mache ;-)
Attachments
read_sensordata.jpg
read_sensordata.jpg (190.93 KiB) Viewed 9807 times
Pjay
Posts: 19
Joined: Tue Jul 05, 2011 6:11 pm

Re: Daten loggen über I2C (IOWarrior24)

Post by Pjay »

übrigens: auch wenn ich die Initialisierung mit in die for-Schleife nehme, bleibt das Problem mit dem RUN FAILED bestehen.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by Christoph Jung »

Ich wundere mich, warum das mit dem Lesen überhaupt geht... um die beiden Temperatur-Bytes auszulesen, muss gemäß Datenblatt nach der Device-Addresse (1001000) eigentlich die Register-Addresse gesendet
Das bedeutet, dass vor dem Lesen einmal "richtig" geschrieben werden muss, also mit reportID 0x02 muss auf Adresse X auf register 0x00 (oder was auch immer im Datenblatt als Register für MSB und LSB der Temperatur angegeben ist) nichts geschrieben werden.
Beim erstem Asuführen ist der Temperatursensor von Haus aus au Register X als Startposition gesetzt und wird dann jedesmal beim Lesen hochgezählt.
Also folgendes muss noch gemacht werden:

Code: Select all

memset()....
ReportID = 0x02
Byte[0] = 0xC2  //Start- und Stopbit, 2 Bytes Senden
Byte[1] = adresse
Byte[2] = Register laut Datenblatt

IowKitWrite(...)
IowKitRead(...) //ACK Lesen.

Das muss vor der Leseroutine ausgeführt werden, damit der Zeiger im Chip immer wieder auf "Anfang" gesetzt wird.
Welchen Zeiger soll ich auf welches Register setzen? Ich führe doch das memset und die Initialisierung der report-Daten innerhalb der for-schleife aus...
memset(...) hat nichts mit dem Sensor zu tun sondern ist einfach nur für das setzten der Variable "report" zuständig.
Aus dem IOWarrior-Datensheet geht leider nicht 100%ig hervor, wie das genau mit dem Lesen abläuft.
Das steht in der Regel in den Datenblättern der Sensoren drin, da das immer abhängig vom Hersteller ist.
Eigentlich ist die Addresse des Temp.-Sensors 1001000 = 0x48... Wenn ich das Confiurationsregister des Sensors beschreiben möchte, dann klappt das auch nur mit dieser Addresse.
Beim Lesen muss ich die Addresse 10010000 = 0x90 angeben, damit das klappt. Wieso ist das so?
Den Zusammenhang versteh ich nicht. Laut Dateblatt ist die Adresse 0x48 in 7-Bit Modus. Bei 8-Bit (der IO-Warrior nutzt 8-Bit) ergibt sich daraus eine 0x90. Somit sollten die Adressen 0x90 und 0x91 sein.
übrigens: auch wenn ich die Initialisierung mit in die for-Schleife nehme, bleibt das Problem mit dem RUN FAILED bestehen.
Inititalisierung nur 1x verwenden. Man muss ja auch nicht das Licht nach dem Einschalten einschalten.. ;)
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
friend-of-rq
Posts: 389
Joined: Sun Feb 13, 2005 1:22 pm
Location: Gerblingerode / Duderstadt
Contact:

Re: Daten loggen über I2C (IOWarrior24)

Post by friend-of-rq »

@Pjay

schon mal das Test-Programm All-In-One (I2C-Funktion) ausprobiert ... das kannst Du mit deinem Sensor erst mal spielen, bevor es ans programmieren geht.

Gruss Ralf
Post Reply