CO2 Sensor mit I2C an IOW56

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

Moderator: Guido Körber

Post Reply
Asimo
Posts: 4
Joined: Mon Feb 16, 2015 12:59 am

CO2 Sensor mit I2C an IOW56

Post by Asimo »

Hallo allerseits :)

Ich bin hier neu und auch noch nicht so Erfahren mit der IOWarrior Programmierung.

Ich versuche gerade einen CO2 Sensor über I²C und einem IOWarrior 56 auszulesen aber habe noch einige Verständnisprobleme.
Habe durch euer Forum und die Dokumentation zwar schon einiges erfahren doch das Ganze noch immer nicht wirklich durchschaut.

Den Warrior kann ich Problemlos ansprechen und dank des hier im Forum vorgetellten All in One tools konnte ich auch sehen, dass der Sensor an der richtigen Adresse (A0) erkannt wird. Leider stürzt das Programm danach immer ab, was weitere Tests verhindert.

Jedenfalls bin ich mir über den Kommunikationsablauf und die Implementierung im Unklaren.
Ich möchte ein Start und ein Control byte senden und schreibe diese in die report.bytes des Warriors? Wo finde ich welches byte welche funktion anspricht? Ich finde nur die Warriorports im Datenblatt.

Auf der Suche nach der richtigen Adressierung habe ich gesehen, dass manchmal die ReportID und manchmal das erste Byte zur Schreib/Lese Definition verwendet wird.
Wo ist der Unterschied?

Auch geht aus dem Datenblatt hervor, dass mein Control byte E1/F1 sein sollte um an die gewünschten Daten zu kommen.

Die zusammengeschnipselte Code sieht derweil in etwa so aus:

Code: Select all

   
            memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);
            report.ReportID = 0x02; // I2C-write-Mode
            report.Bytes[0] = 0xC2; // number of bytes to be read with start and stop bit
            report.Bytes[1] = 0xE1; // Control byte welches um den Co2 wert low anfragt
            report.Bytes[2] = 0xA0; // Pin adresse an der SCL und SDA liegen
          
            for (j=2;j<8;j++)
                report.Bytes[j] = 0x00;

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

            memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);
            report.ReportID = 0x03; // I2C-Read-Mode
            report.Bytes[0] = 0xC2; // number of bytes to be read with start and stop bit
            report.Bytes[1] = 0xA1; // leseadresse
           

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

            for (j=0;j<3;j++)
             co2[j] = (unsigned int) report.Bytes[j];


            if (report.Bytes[1] & 0x80) 
                printf("Error\n");
            
            else 
                printf("Erfolgreich\n");
      

Ist der ausgelesene Wert dann in byte[2] und die checksumme in byte[3]?

Vielen Dank für jegliche Hilfe und entschuldigt die vermutlich sehr diletantischen Fragen,

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

Re: CO2 Sensor mit I2C an IOW56

Post by Christoph Jung »

Na die Byte-Belegung steht doch im Datenblatt zu den IO-Warriorn.

1. Für den IO-Warrior56 die richtige Buffergröße Wählen, also nicht IOWKIT_SPECIAL_REPORT_SIZE sondern IOWKIT56_SPECIAL_REPORT_SIZE
Sowie IOWKIT56_SPECIAL_REPORT also Variable (damit auch alle 63 Byte genutzt werden können)
2. Die I2C-Adresse muss in das report.Byte[1] rein (Beim lesen und Schreiben)
3. Nach jedem Schreibbefehl mit I2C muss ein Lesebefehl kommen um die Antwort (ACK) auszulesen, sonst hat man später "Geister Reports"
4. Der Lesebefehl (Report.ID = 0x03) kennt kein Start- und Stop-Bit. Einfach die Anzahl an Bytes rein, die gelesen werden sollen.

Der IO-Warrior sendet keine Checksumme. Im Byte[0] steht beim IOW56 die Anzahl der gelesenen Bytes und die Error-Flags drin. Alles ab Byte[1] sind dann Daten.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Asimo
Posts: 4
Joined: Mon Feb 16, 2015 12:59 am

Re: CO2 Sensor mit I2C an IOW56

Post by Asimo »

Vielen Dank für die schnelle Rückmeldung

Tatsächlich! Tut mir Leid die habe ich wohl übersehen da ich zuerst nur auf pipe 0 herumexperimentiert habe.

1.Seltsamerweise hängt sich das Programm mit der IOWKIT56_SPECIAL_REPORT_SIZE immer auf, aber funktioniert mit IOWKIT_SPECIAL_REPORT_SIZE.
Allerdings benötige ich auch keine 63 Byte.

2. Ich bin jetzt irritiert welche Adresse überhaupt hineingehört. Hatte Anfangs die Pinadresse genommen allerdings werden die Pins mit dem IIC Mode sowieso festgelegt.
Auch steht in der Dokumentation für den Sensor, dass ein Schreibbefehl folgenden Aufbau haben sollte:
Image
Also zuerst ein Control und dann erst das Address byte.

Beim lesen scheint die Adresse garnicht benötigt zu werden:
Image

3, 4 danke wurde übernommen :)
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: CO2 Sensor mit I2C an IOW56

Post by Christoph Jung »

Bitte einmal den Quelltext für das Auslesen komplett Posten damit man sich das mal anschauen kann.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Re: CO2 Sensor mit I2C an IOW56

Post by Guido Körber »

Asimo wrote:1.Seltsamerweise hängt sich das Programm mit der IOWKIT56_SPECIAL_REPORT_SIZE immer auf, aber funktioniert mit IOWKIT_SPECIAL_REPORT_SIZE.
Allerdings benötige ich auch keine 63 Byte.
Das Datenpaket mit dem mit dem IO-Warrior kommuniziert wird hat ein festes Format. Wenn weniger als 62 Bytes über den I2C übertragen werden, dann stehen halt weniger Bytes in dem Datenpaket drin, wie viele gültig sind gibt man ja im ersten Byte des Datenpakets an. Die Länge des Paketes ändert sich dadurch nicht.
Asimo wrote:2. Ich bin jetzt irritiert welche Adresse überhaupt hineingehört. Hatte Anfangs die Pinadresse genommen allerdings werden die Pins mit dem IIC Mode sowieso festgelegt.
Auch steht in der Dokumentation für den Sensor, dass ein Schreibbefehl folgenden Aufbau haben sollte:
Das sind dann Daten die spezifisch für den Sensor sind und nichts mit dem IO-Warrior zu tun haben, der reicht die nur durch ohne sich dafür zu interessieren was die bedeuten. Anscheinend verwendet der Sensor das erste Byte einer Schreibaktion nach der I2C Adresse als Registeradresse. Dazu sollte das Datenblatt des Sensors Auskunft geben.
Asimo
Posts: 4
Joined: Mon Feb 16, 2015 12:59 am

Re: CO2 Sensor mit I2C an IOW56

Post by Asimo »

Hmm im Sensordatenblatt steht nichts aber ich werde noch genauer auf der Herstellerseite suchen.
Vielen Dank
Der vollständige Code sieht im Moment so aus:

Code: Select all

//
//      CO2 Measurement
//

#include <stdio.h>
#include "stdafx.h"
#include "iowkit.h"
#include "windows.h"


void init_i2c(IOWKIT_HANDLE ioHandle);
void abfrage (IOWKIT_HANDLE ioHandle);

int main()
{


    IOWKIT_HANDLE ioHandle;
    int j, repeat=10, co2[1][6];
    unsigned int temp_shifted;
    IOWKIT56_IO_REPORT report;



    ioHandle = IowKitOpenDevice();


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

        init_i2c(ioHandle);
        puts("initende");


        for(j=0; j<repeat; j++)
        {
            abfrage(ioHandle);
        }
    }

    IowKitCloseDevice(ioHandle);



    printf("ende \n");
    return (EXIT_SUCCESS);
}


void init_i2c(IOWKIT_HANDLE ioHandle)
{
    IOWKIT56_IO_REPORT report;


    memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);
    report.ReportID = 0x01; // I2C-activate-Mode
    report.Bytes[0] = 0x01; // enable
    report.Bytes[1] = 0x00; //

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

void abfrage (IOWKIT_HANDLE ioHandle)
{
    int co2[1][6];

    IOWKIT56_IO_REPORT report;



    memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);
    report.ReportID = 0x03; // I2C-Read-Mode
    report.Bytes[0] = 0x02; // number of bytes to be read with start and stop bit
    report.Bytes[1] = 0xE1; // leseadresse


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

    co2[0][1] = (unsigned int) report.Bytes[1];


    memset(&report, 0x00, IOWKIT_SPECIAL_REPORT_SIZE);
    report.ReportID = 0x03; // I2C-Read-Mode
    report.Bytes[0] = 0x02; // number of bytes to be read with start and stop bit
    report.Bytes[1] = 0xF1; // leseadresse


    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[0] & 0x80)
    {
        printf("Error\n");
    }
    else
    {
        printf("Erfolgreich\n");


        co2[1][1] = (unsigned int) report.Bytes[1];

        printf("Wert[low/high] = %d/%d\n",  co2[0][1], co2[1][1]);

        Sleep(1000);
    }
}
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: CO2 Sensor mit I2C an IOW56

Post by Christoph Jung »

- Als erstes erstmal alle IOWKIT56_IO_REPORT in IOWKIT56_SPECIAL_REPORT ändern.
- Das Selbe für IOWKIT_SPECIAL_REPORT_SIZE in IOWKIT56_SPECIAL_REPORT_SIZE
- Im init_i2c das Read() entfernen, ist bei initialiseren eines Special-Modes nicht notwendig (der IOW sendet keine Antwort darauf)
- In der abfrage() report.Bytes[0] = 0x02; in report.Bytes[0] = 0xC2; ändern. Start und Stop-Bit, oder zumindest das Startbit MUSS gesetzt sein bei der ersten Schreibtransaktion. Die Anzahl der Bytes (0x02) ergibt sich aus den Werten von report.Byte[1] bis report.Byte[X].



Dann fehlt entweder die Geräte-Adresse oder das Register, auf das geschreiben werden soll. Also report.Bytes[1] MUSS die I2C-Adresse vom CO2-Sensor sein. In report.Bytes[2] dann das Register, auf das geschrieben werden soll, danach dann wenn nötig Daten. Beim reinen Lesezugriff aber nur 2 Byte senden, um den Pointer auf das Register zu setzten.

Ausnahme wäre, wenn im Datenblatt steht, das man kein Register setzen muss zum lesen.


In der Leseroutine das report.Bytes[1], stimmt die Adresse?

I2C-Adressen sind für den IO-Warrior immer 8Bit, und die Schreibadressen sind immer Gerade, z.B. 0x02, 0x04, 0x06, 0x08, usw. und Leseadressen immer mit 0x01 dazu-geodert, also 0x03, 0x05, 0x07, 0x09 und so weiter.

Die Adresse ist immer im Datenblatt zum Sensor zu finden und wenn das eine 7Bit Adresse ist muss diese um eins nach links geschoben werden

BYTE 8bit_adresse = 7bit_adresse << 1;

Code: Select all

	IOWKIT56_SPECIAL_REPORT report;
	memset(&report, 0x00, IOWKIT56_SPECIAL_REPORT_SIZE);

	report.ReportID = 0x02;
	report.Bytes[0] = 0xC2; //Start+Stop und 2 Byte
	report.Bytes[1] = adr; //Geräteadresse
	report.Bytes[2] = reg; //Register, auf das zugegriffen werden soll
	IowKitWrite(handle, IOW_PIPE_SPECIAL_MODE, (char*)&report, IOWKIT56_SPECIAL_REPORT_SIZE);
	IowKitRead(handle, IOW_PIPE_SPECIAL_MODE, (char*)&report, IOWKIT56_SPECIAL_REPORT_SIZE);

	report.ReportID = 0x03;
	report.Bytes[0] = 0x01; //Anzahl der zu lesenen Bytes 
	report.Bytes[1] = adr | 0x01; //Leseadresse

	IowKitWrite(handle, IOW_PIPE_SPECIAL_MODE, (char*)&report, IOWKIT56_SPECIAL_REPORT_SIZE);
	IowKitRead(handle, IOW_PIPE_SPECIAL_MODE, (char*)&report, IOWKIT56_SPECIAL_REPORT_SIZE);

//Auswertung der Daten

Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Asimo
Posts: 4
Joined: Mon Feb 16, 2015 12:59 am

Re: CO2 Sensor mit I2C an IOW56

Post by Asimo »

Vielen Herzlichsten Dank für die schnelle, und freundliche Hilfe!

Im Datenblatt steht keine Adresse aber ich habe gerade gelesen, dass der E2 Bus (um den es sich hier eigentlich handelt) gerade beim Adressieren doch ein bisschen vom I2C abweicht.
Werde die Spezifikationen jetzt noch einmal genau durchgehen und dann stellt sich hoffentlich die Erleuchtung ein :)

Vielen Dank nochmal, die Tipps haben sehr geholfen :)

Edit die Adresse scheint sogar 2Byte groß zu sein (0x0367) und ich glaube ich muss für jedes einzelne byte das ich senden /empfangen will einen schreibe/lesezyklus machen um alle ACKs rauszubekommen
Mühsam ernährt sich das Eichhörnchen^^
Post Reply