- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 64

Thema: Raspi C/C++, Raspi als I2C-Master: byte arrays zu Arduino slave hin + her schicken?

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Hallo,

    ich sehe da ein Problem im ARDUINO-Code.

    Der hängt sich weg, auch wenn man zwischen Senden und Empfangen eine Sekunde Pause einlegt.
    Demnach läuft kein Puffer über, aber irgendetwas ist.

    Meine aktuellen Codes:
    MEGA:
    Code:
    // Wire Slave Receiver
    // by Nicholas Zambetti <http://www.zambetti.com>
    
    // Demonstrates use of the Wire library
    // Receives data as an I2C/TWI slave device
    // Refer to the "Wire Master Writer" example for use with this
    
    // Created 29 March 2006
    
    // This example code is in the public domain.
    
    
    #include <Wire.h>
    
    #define REGSIZE 240
    
    byte rspeicher[REGSIZE];
    byte wspeicher[REGSIZE];
    byte puffer[32];
    byte Register=1;
    byte rdblock=0;
    byte wrblock=0;
    byte pos=0;
    byte fertig=0;
    
    void setup() {
      Wire.begin(4);                // join I2C bus with address #8
      Wire.onReceive(receiveEvent); // register event
    //  Wire.onReceive(receiveEventRoh); // register event
      Wire.onRequest(requestEvent); // register event
      Serial.begin(57600);           // start serial for output
    /*  for(byte i=0;i<REGSIZE;i++){
        wspeicher[i]=i;
        
      }*/
      Serial.println();  
      Serial.println("Starte I2C-Test");  
    }
    
    void loop() {
      byte i=0;
      delay(100);
      if (fertig !=0){
        fertig=0;
        for (i=0;i<REGSIZE;i++){
          wspeicher[i]=rspeicher[i];
          Serial.print(rspeicher[i]);
          Serial.print (" ");
        }
        Serial.println();
      }
    }
    
    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEvent(int howMany) {
        rdblock = Wire.read();
        if (rdblock<=7){
          pos=0;
          while (0 < Wire.available()) { 
            if (pos<30){
              rspeicher[rdblock*30+pos] = Wire.read(); 
              pos++;
            }
          }
          if (rdblock==7){
            fertig=1;
          }
        }else{
          if (rdblock >=10 && rdblock <=17){
            wrblock=rdblock-10;
            Serial.print("Leseblock: ");
            Serial.println(wrblock);
          }
        }
    }
    
    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEventRoh(int howMany) {
      while (0 < Wire.available()) { 
        byte x=Wire.read();
        Serial.print (x);
        Serial.print (" ");
      }
      Serial.println();
    }
    
    // function that executes whenever data is requested by master
    // this function is registered as an event, see setup()
    void requestEvent() {
      //Wire.write(speicher[Register],1);
      memcpy( &puffer[1],&wspeicher[wrblock * 30],30);
      puffer[0]=wrblock;
      Wire.write(puffer,31);
    }
    Raspberry Pi:
    Code:
    // GCC -Wall -pthread -o /var/scripte/i2cmaster01 /var/scripte/i2cmaster01.c -lpigpio -lrt
    // /var/scripte/i2cmaster01
    //I2C mit pipgio
    //peterfido
    //V0.0.1
    #include <stdio.h>
    #include <stdlib.h>
    //#include <stdarg.h>
    #include <string.h>
    //#include <ctype.h>
    #include <unistd.h>
    
    #include <signal.h>
    #include <pigpio.h>
    
    
    //#define SDA 3
    //#define SCL 5
    #define BAUD 100
    #define ADDRESS 0x04
    #define MSGSIZE  240
    #define LOOPS 30
    char empfdata[MSGSIZE];  // 
    char senddata[MSGSIZE];
    char commando[32];
    
    int handle=0;
    int handles=-1;
    unsigned int laenge=0;
    
    void handleSigInt( int parameter );
    
    
    void handleSigInt( int parameter )
    {
        int res=0;
        int dl=0;
        if (handles >= 0){
            for (dl=0;dl<handles;dl++){
                res=i2cClose(dl);    
                printf("%d geschlossen: %d\n",dl, res);
            }
        }
        gpioTerminate();
        printf( "\nSIGINT wurde augeloest - Programm wird beendet\n" );
    
        exit( 1 );
    }
    
    void senden() {
        
        int res=0;
        int i=0;
        char wrblock=0;
    
        for (wrblock=0;wrblock<=7;wrblock++){
            handle=i2cOpen(1,ADDRESS,0);
            handles ++;
            if (handle>=0){
                laenge=31;
                printf("Oeffnen OK %d\n",handle);
                res=0;
                memcpy( &commando[1],&senddata[wrblock * 30],laenge);
                commando[0]=wrblock;
                res=res+i2cWriteDevice(handle,commando,laenge);
                usleep(5000);
    
                for(i=0;i<laenge;i++){
                    printf("%d ",commando[i]);
                }                    
                printf("\n");
                
                if (res==0){
                    printf("Senden OK\n");
    
                }else{
                    printf("I2C-Fehler: %d\n", res);
                }
                res=i2cClose(handle);
                
                if (res!=0){
                    printf("Fehler beim schliessen: %d\n", res);
                }else{
                    handles--;
                }
            }else{
                printf("Fehler beim oeffnen: %d\n", res);
            }    
        }    
    }
    
    void empfangen() {
        
        int res=0;
        int i=0;
        char rdblock=0;    
        for (rdblock=0;rdblock<=7;rdblock++){
            handle=i2cOpen(1,ADDRESS,0);
            handles ++;
            if (handle>=0){
                laenge=31;
                printf("Oeffnen OK %d\n",handle);
                commando[0]=rdblock+10;
                res=i2cWriteDevice(handle,commando,1);
                if (res==0){
                    
                    usleep(30000);
                    res=i2cReadDevice(handle,commando,laenge);
                    if (res>0){
    /*                printf("Empfangen:\n");
                        for(i=0;i<laenge;i++){
                            printf("%d ",commando[i]);
                        }                    
                        printf("\n");*/
                    //    memcpy( &commando[1],&empfdata[commando[0] * 30],laenge-1);
                        for (i=0;i<laenge-1;i++){
                            empfdata[commando[0]*30+i]=commando[i+1];
                        }                
                    }else{
                        printf("Fehler beim Blockeinlesen: %d\n", res);
                    }
                }else{
                    printf("Fehler beim Leseblock schreiben %d\n", rdblock);
                }
                    res=i2cClose(handle);//+i2cClose(handle1);
                    
                    if (res!=0){
                        printf("Fehler beim schliessen: %d\n", res);
                    }else{
                        handles--;
                    }
    
            }else{
                printf("Fehler beim oeffnen: %d\n", res);
            }    
        }    
        printf("Empfangen:\n");
        for(i=0;i<MSGSIZE;i++){
            printf("%d ",empfdata[i]);
        }                    
    }
    
    int vergleichen()
    {
        unsigned int i=0;
        int ret=0;
        for (i=0;i<MSGSIZE;i++){
            if (empfdata[i]!=senddata[i]){
                ret=-1;
                break;
            }
        }
        return ret;
    }
    
    int main(int argc, char **argv)
    {
        int i=0;
        int dg=0;
        
    /*    for(i=0;i<MSGSIZE;i++){
            senddata[i]=i;
        }*/
        signal( SIGINT, &handleSigInt );
        signal( SIGTERM, &handleSigInt );
        if (gpioInitialise() < 0)
        {
            printf("Fehler beim Initialisieren von gpio!");
            gpioTerminate();
        }else{
            for(dg=0;dg<LOOPS;dg++)
            {    
                srand(time(NULL));
                for(i=0;i<MSGSIZE;i++){
                     senddata[i]=rand() % 255;
                }        
                senden();
    //            usleep(100000);
                sleep(1);
                empfangen();
    //            usleep(100000);
                sleep(1);
                if (vergleichen()==0){
                        printf("Daten OK\n");
                }else{
                    printf("Daten fehlerhaft\n");
                }
            }
        }
    
        gpioTerminate();
        
        return 0;
    }
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  2. #2
    HaWe
    Gast
    wenn ich in meinen eigenen Code (siehe https://www.roboternetz.de/community...l=1#post623669) in der Loop statt delay(1) ein delay(2000) eingebe, habe ich kein Problem mit der Verbindung per Arduino DUE -

    der Raspi sendet zwar lustig vor sich hin, aber der Arduino sendet und empfängt immer im 2-Sekundentakt die dann jeweils aktuellsten Daten:

    Sendarr[4]= 36, [5]= 0, Recvarr[4]= 0, [5]= 93


    Sendarr[4]= 37, [5]= 0, Recvarr[4]= 0, [5]= 168


    Sendarr[4]= 38, [5]= 0, Recvarr[4]= 0, [5]= 243


    Sendarr[4]= 39, [5]= 0, Recvarr[4]= 0, [5]= 61


    Sendarr[4]= 40, [5]= 0, Recvarr[4]= 0, [5]= 133


    Sendarr[4]= 41, [5]= 0, Recvarr[4]= 0, [5]= 209


    Sendarr[4]= 42, [5]= 0, Recvarr[4]= 0, [5]= 29


    Sendarr[4]= 43, [5]= 0, Recvarr[4]= 0, [5]= 104


    Sendarr[4]= 44, [5]= 0, Recvarr[4]= 0, [5]= 179


    Sendarr[4]= 45, [5]= 0, Recvarr[4]= 0, [5]= 255


    Sendarr[4]= 46, [5]= 0, Recvarr[4]= 0, [5]= 75


    Sendarr[4]= 47, [5]= 0, Recvarr[4]= 0, [5]= 151

    - - - Aktualisiert - - -

    ps,
    auch bei mir funktioniert dann
    #define MSGSIZE 32
    einwandfrei.

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Hallo,

    auch möglich, dass der Raspi durch sein Multitasking I2C etwas aus dem Takt bringt und der Code für den MEGA das nicht mag.

    Aktuell habe ich es soweit, dass beide Seiten Fehler erkennen und danach dann 'einfach' weitermachen. Läuft schon eine Weile durch.

    Beschäftige ich den MEGA mit en paar UART-Ausgaben, dann steigt die Fehlerquote an. Somit ist da nicht wirklich viel Luft für Dein Vorhaben. Da der Raspi mit vielen Sensoren und Slaves umgehen kann, würde ich dem die meiste Arbeit aufbürden und den MEGA nur für 'kritische' Aufgaben nutzen, da meiner Erfahrung nach die AVRs zuverlässiger arbeiten. Im Zweifel den Watchdog aktivieren.

    Raspi:
    Code:
    // GCC -Wall -pthread -o /var/scripte/i2cmaster01 /var/scripte/i2cmaster01.c -lpigpio -lrt
    // /var/scripte/i2cmaster01
    //I2C mit pipgio
    //peterfido
    //V0.0.2
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    #include <signal.h>
    #include <pigpio.h>
    
    #define ADDRESS 0x04
    #define MSGSIZE  240
    char empfdata[MSGSIZE];  // 
    char senddata[MSGSIZE];
    char commando[32];
    
    int handle=0;
    int handles=-1;
    unsigned int laenge=0;
    
    void handleSigInt( int parameter );
    
    
    void handleSigInt( int parameter )
    {
        int res=0;
        int dl=0;
        if (handles >= 0){
            for (dl=0;dl<handles;dl++){
                res=i2cClose(dl);    
                printf("%d geschlossen: %d\n",dl, res);
            }
        }
        gpioTerminate();
        printf( "\nSIGINT wurde augeloest - Programm wird beendet\n" );
    
        exit( 1 );
    }
    
    void schreiben() {
        
        int res=0;
        int i=0;
        char wrblock=0;
        int Fehler=0;
        
        for (wrblock=0;wrblock<=7;wrblock++){
    
            laenge=31;
            memcpy( &commando[1],&senddata[wrblock * 30],laenge);
            commando[0]=wrblock;
            res=i2cWriteDevice(handle,commando,laenge);
            if (res!=0){
                printf("S I2C-Fehler: %d, Block: %d\n", res,wrblock);
                Fehler++;
                wrblock--;
                usleep(15000);
                if (Fehler==10){
                    break;
                }
            }
            usleep(15000);
        }
        printf("Gesendet:\n");
        for(i=0;i<MSGSIZE;i++){
            printf("%d ",senddata[i]);
        }    
        printf("\n");
    }
    
    void lesen() {
        
        int res=0;
        int i=0;
        char rdblock=0;
        int Fehler=0;    
        
        for (rdblock=0;rdblock<=7;rdblock++){
    
            laenge=31;
            commando[0]=rdblock+10;
            res=i2cWriteDevice(handle,commando,1);
            if (res==0){
                usleep(30000);
                res=i2cReadDevice(handle,commando,laenge);
                if (res==laenge){
                    printf("Empfangene Daten: %d, Block: %d\n",res,rdblock);
    
                    for (i=0;i<laenge-1;i++){
                        empfdata[commando[0]*30+i]=commando[i+1];
                    }                
                }else{
                    printf("E Fehler beim Blockeinlesen: %d, Block: %d\n", res,rdblock);
                    Fehler++;
                    rdblock--;
                    usleep(15000);
                    if (Fehler==10){
                        break;
                    }
                }
            }else{
                printf("E Fehler beim Leseblock schreiben %d, Block: %d\n", res,rdblock);
                break;
            }
        }    
        printf("Empfangen:\n");
        for(i=0;i<MSGSIZE;i++){
            printf("%d ",empfdata[i]);
        }    
        printf("\n");    
    }
    
    int vergleichen()
    {
        unsigned int i=0;
        int ret=0;
        for (i=0;i<MSGSIZE;i++){
            if (empfdata[i]!=senddata[i]){
                ret=-1;
                break;
            }
        }
        return ret;
    }
    
    int main(int argc, char **argv)
    {
        int res=0;
        int i=0;
        int dg=1;
        unsigned int Fehler=0;
    
        signal( SIGINT, &handleSigInt );
        signal( SIGTERM, &handleSigInt );
        if (gpioInitialise() < 0)
        {
            printf("Fehler beim Initialisieren von gpio!");
            gpioTerminate();
        }else{
            handle=i2cOpen(1,ADDRESS,0);
            if(handle>=0){
                handles ++;
                printf("\n\n\nStarte I2C-Test (%d)\n\n",handle);
                while (1)
                {    
                    srand(time(NULL));
                    for(i=0;i<MSGSIZE;i++){
                         senddata[i]=rand() % 255;
                    }        
                    schreiben();
                    usleep(100000);
                    lesen();
                    usleep(100000);
                    if (vergleichen()==0){
                            printf("Daten OK %d\n",dg);
                            Fehler=0;
                    }else{
                        printf("***************************** Daten fehlerhaft %d *****************************\n",dg);
                        Fehler++;
                        usleep(500000);
                        if (Fehler==10){
                            break;
                        }
                    }
                }
            }else{
                printf("E Fehler beim Oeffnen: %d\n", handle);    
            }
        }
        res=i2cClose(handle);
        
        if (res!=0){
            printf("E Fehler beim Schliessen: %d\n", res);
        }else{
            handles--;
            printf("E Schliessen OK %d\n",handle);
        }
    
        gpioTerminate();
        
        return 0;
    }
    MEGA:
    Code:
    // Wire Slave Receiver
    // by Nicholas Zambetti <http://www.zambetti.com>
    
    // Demonstrates use of the Wire library
    // Receives data as an I2C/TWI slave device
    // Refer to the "Wire Master Writer" example for use with this
    
    // Created 29 March 2006
    
    // This example code is in the public domain.
    
    
    #include <Wire.h>
    
    #define REGSIZE 240
    
    byte rspeicher[REGSIZE];
    byte wspeicher[REGSIZE];
    byte puffer[32];
    byte Register=1;
    byte rdblock=0;
    byte wrblock=0;
    byte pos=0;
    byte fertig=0;
    long dg=0;
    long timeout=0;
    
    void setup() {
      Wire.begin(4);                // join I2C bus with address #4
      Wire.onReceive(receiveEvent); // register event
    //  Wire.onReceive(receiveEventRoh); // register event
      Wire.onRequest(requestEvent); // register event
      Serial.begin(57600);           // start serial for output
    /*  for(byte i=0;i<REGSIZE;i++){
        wspeicher[i]=i;
        
      }*/
      Serial.println();  
      Serial.println("Starte I2C-Test");  
    }
    
    void loop() {
      byte i=0;
      delay(100);
      timeout++;
      if (timeout==30){
          timeout=0;
          Wire.begin(4); 
          Serial.println("Fehler!");
          dg=0;
      }
    
      if (fertig !=0){
        fertig=0;
        timeout=0;
        dg++;
        Serial.println(dg);
        
        for (i=0;i<REGSIZE;i++){
          wspeicher[i]=rspeicher[i];
    //      Serial.print(rspeicher[i]);
    //      Serial.print (" ");
        }
    //    Serial.println();
      }
    }
    
    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEvent(int howMany) {
        byte x=0;
        if(howMany == 31){
          rdblock = Wire.read();
          if (rdblock<=7){
            pos=0;
            while (0 < Wire.available()) { 
              if (pos<30){
                rspeicher[rdblock*30+pos] = Wire.read(); 
                pos++;
              }
            }
            if (rdblock==7){
              fertig=1;
            }
          }
        }
        if (howMany==1){
            x=Wire.read();
            if (x >=10 && x <=17){
              wrblock=x-10;
      //        Serial.print("Leseblock: ");
      //        Serial.println(wrblock);
            }
        }
        while (0 < Wire.available()) { 
            x=Wire.read();
        }
    }
    
    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEventRoh(int howMany) {
      while (0 < Wire.available()) { 
        byte x=Wire.read();
    //    Serial.print (x);
    //    Serial.print (" ");
      }
    //  Serial.println();
    }
    
    // function that executes whenever data is requested by master
    // this function is registered as an event, see setup()
    void requestEvent() {
      //Wire.write(speicher[Register],1);
      memcpy( &puffer[1],&wspeicher[wrblock * 30],30);
      puffer[0]=wrblock;
      Wire.write(puffer,31);
    }
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  4. #4
    HaWe
    Gast
    hallo,
    ich verstehe jetzt deinen Code nicht mehr -
    ist es noch so wie in meinem Ausgangs-Code,

    - dass der Raspi im 10ms-Takt (künftig schneller) zum Arduino 32 Bytes schickt und dann, wenn sie angekommen sid, 32 neue Bytes von ihm zurück liest
    - und dass der Arduino so schnell wie möglich (also mindestens im 1ms- Takt) seinen Sende-Array zum Auslesen aktualisiert und bereitstellt?

    Der Arduino muss dies automatisch tun, so schnell wie möglich, es darf keine Anforderung vom Raspi nötig sein außer ein onRequest und/oder ein onReceive(), um sie zu empfangen oder weg zu "senden".

    Später in der "richtigen" Anwendung wird der Arduino seine digitalen und anlalogen Pins per Timer Interrupt (AVR) oder Task (DUE) (100µs) ständig (quasi im Hintergund bzw. per Parallel-Task) aktualisieren, damit sie beim Abruf immer in der am weitest aktualisiertesten Version zur Verfügung stehen. Kommt dann ein onRequest, kann abgerufen werden, was bis dahin bekannt ist.
    Genauso muss jederzeit alles angenommen werden können, was vom Master gesendet wurde, per onReceive Event. Eine gesonderte Funktion (ebenfalls per Timer-Interrupt oder Task) verarbeitet sie dann weiter.

    Der Arduino-Code soll dazu möglichst unverändert bleiben (außer clock-stretching vermeiden)
    und der Raspi-Code ebenfalls, außer dass er clock-stretching besser verträgt, d.h. die normalen read() und write() Befehle für I2C müssten durch andere, clock-tolerantere, erstetzt werden.

    Raspi:

    Code:
    //  Raspberry Pi Master code to send/receive byte arrays
    //  to an Arduino as an I2C slave
    // 
    //  ver. 0.002b
    
    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <wiringPi.h>
    #include <wiringPiI2C.h>
    
    #include <errno.h>
    #include <string.h>
    
    #define MSGSIZE 32
    
    
    #define  ARDU1_SLV_ADDR 0x04
    
    
    uint8_t  calcchecksum( uint8_t array[]) {   
      int32_t  sum=0;
      for(int i=2; i<MSGSIZE; ++i) sum+=(array[i]);
      return (sum & 0x00ff);
    }
    
    
    
    int main (void)
    {
       
      int fd, i ;
      uint8_t  test=0;
      uint8_t  data [MSGSIZE] ;
    
      if ((fd = wiringPiI2CSetup ( ARDU1_SLV_ADDR) ) < 0)
      {
        fprintf (stderr, "Can't open RTC: %s\n", strerror (errno)) ;
        exit (EXIT_FAILURE) ;
      }
    
    
      for (;;)
      {
        memset(data, 0, sizeof(data) );
        data[0]=  0xff;    // init for transmission error check
        read (fd, data, MSGSIZE) ;
        if( data[1] != calcchecksum( data )  ) {
             // handle transmission error !
        }   
        else {
           printf ("  read:  ");
           for (i = 0 ; i < 7 ; ++i)
              printf ("  %3d", data [i]) ;
           //printf ("\n") ;
           delay(10) ;
         
           memset(data, 0, sizeof(data) );
           data[5]=  test++;
           data[0]=  0xff;
           data[MSGSIZE-1]= ARDU1_SLV_ADDR ;
           data[1] = calcchecksum( data );
           
           write(fd, data, MSGSIZE) ;
           printf ("   write: ");
           for (i = 0 ; i < 7; ++i)
             printf ("  %3d", data [i]) ;
           printf ("\n\n") ;
           delay(10) ;     
        }
      }
    
      return 0 ;
    }
    Arduino:
    Code:
    //  Arduino code to send/receive byte arrays
    //  Arduino as an I2C slave
    //
    //  ver. 0.002b
    
    
    #include  <Wire.h>
    
    #define  SLAVE_ADDRESS 0x04
    #define  MSGSIZE  32
    byte     recvarray[MSGSIZE];  // 0=0xff; 1=chksum; ...data...; MSGSIZE-1=SLAVE_ADDRESS
    byte     sendarray[MSGSIZE];
    
    volatile int8_t  flag=0;
    
    
    //=====================================================================================
    //=====================================================================================
    void setup() {
       int32_t  i=0;
    
       // Serial terminal window
       i=115200;
       Serial.begin(i);
       Serial.print("Serial started, baud=");
       Serial.println(i);
    
       // Wire (i2c)
       Wire.begin(SLAVE_ADDRESS);     // start Arduino as a I2C slave, addr=0x04 (7-bit coded)
       
       Wire.onReceive(receiveData );  // event when master array is sent
       Wire.onRequest(sendData );     // event when master requests array to read
       
       memset(sendarray, 0, sizeof(sendarray) );  // init send- and recv arrays
       memset(recvarray, 0, sizeof(recvarray) );   
       
       Serial.print("I2C init: my slave address= ");
       Serial.println(SLAVE_ADDRESS);
       Serial.println("I2C init: done.");
       Serial.println();
       
       Serial.println("setup(): done.");   
    
    }
    
    
    //=====================================================================================
    
    
    uint8_t  calcchecksum(uint8_t array[]) {   
      int32_t  sum=0;
      for(int i=2; i<MSGSIZE; ++i) sum+=(array[i]);
      return (sum & 0x00ff);
    }
    
    //=====================================================================================
    
    void loop()
    {
       char sbuf[128];
    
       Serial.println(); Serial.println();
    
       // do something with the received data
       // and then do something to build the sendarray [3]...[MSG_SIZE-2]
       
       if (flag==1) {
           //debug
           sendarray[4] +=1;   
       }
    
       sendarray[0] = 0xff;                        // 0 = start: 0xff == msg start flag
       sendarray[2] = flag;                        // 2 = send back msg error flag   
       sendarray[MSGSIZE-1] = SLAVE_ADDRESS;       // end of array: ID check     
       
       sendarray[1] = calcchecksum(sendarray);     // 1 = calc new chksum
       flag=0;   
       
       // debug output
       sprintf(sbuf, "Sendarr[4]=%4d,   [5]=%4d,   Recvarr[4]=%4d,  [5]=%4d",
                      sendarray[4], sendarray[5],  recvarray[4],    recvarray[5]) ;
       Serial.println(sbuf);
    
       delay(1);                                     // short break for the cpu and the bus
    }
    
    
    //=====================================================================================
    
    void receiveData(int byteCount) {
        int32_t i;
        byte val;
    
        while(Wire.available()<MSGSIZE) ;           // wait for all bytes to complete
        i=0;                                        // init counter var
        while(Wire.available()&& (i<MSGSIZE) )      // read all recv array bytes
        {
          val=Wire.read();
          recvarray[i++]=val;
        }
       
        // check for transmission error
        if(  (recvarray[0]  == 0xff)
          && (recvarray[1]  == calcchecksum(recvarray))
          && (recvarray[MSGSIZE-1] == SLAVE_ADDRESS  ) )
             flag=1;        // data ok
        else
             flag=127;      // data faulty => handle rcv-error => flag =127
    }
    
    //=====================================================================================
    
    void sendData(){
      // Wire.write writes data from a slave device in response to a request from a master
      Wire.write(sendarray, MSGSIZE);    // send own byte array back to master..
    Geändert von HaWe (14.02.2016 um 08:57 Uhr)

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Hallo,

    ich habe nun die Funktion verstanden und den BitBAng Modus zum laufen zu bekommen.

    Die Ergebnisse sind ernüchternd. Daten zum AVR bekomme ich hin. Beim Lesen hakt es noch arg. 1 Byte kein Problem. Bei mehreren steht dann der Bus.

    Der Resync nach einem Fehler klappt nun nicht mehr.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  6. #6
    HaWe
    Gast
    hi,
    Mist.
    Ich denke fast, wir sollten es aufgeben, zuviel Aufwand. Vllt gibt ja irgendwann nen neuen Jessie-Kernel, der clock-stretching unterstützt, wie Gordon Henderson schrieb... irgendwann halt...
    Solange muss ich dann mit meinen DUEs vorlieb nehmen.

    - - - Aktualisiert - - -

    angeblich gibt es sogar schon etwas Bewegung in dieser Sache:

    https://github.com/raspberrypi/linux/pull/1241

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Hallo,

    es sieht nicht so gut aus. Anbei meine aktuellen Testcodes, wo 240 Bytes hin und zurück geschickt und verglichen werden.

    MEGA:
    Code:
    // Wire Slave Receiver
    // by Nicholas Zambetti <http://www.zambetti.com>
    
    // Demonstrates use of the Wire library
    // Receives data as an I2C/TWI slave device
    // Refer to the "Wire Master Writer" example for use with this
    
    // Created 29 March 2006
    
    // This example code is in the public domain.
    
    
    #include <Wire.h>
    
    #define REGSIZE 240
    
    byte rspeicher[REGSIZE];
    byte wspeicher[REGSIZE];
    byte puffer[32];
    byte Register=1;
    byte rdblock=0;
    byte wrblock=0;
    byte pos=0;
    byte fertig=0;
    long dg=0;
    long timeout=0;
    
    void setup() {
      Wire.begin(4);                // join I2C bus with address #8
      Wire.onReceive(receiveEvent); // register event
      Wire.onRequest(requestEvent); // register event
      Serial.begin(57600);           // start serial for output
    
      Serial.println();  
      Serial.println("Starte I2C-Test");  
    }
    
    void loop() {
      byte i=0;
      delay(100);
      timeout++;
      if (timeout==90){
          timeout=0;
          Wire.begin(4); 
          Serial.println("TimeOut!");
          dg=0;
      }
    
      if (fertig !=0){
        fertig=0;
        timeout=0;
        dg++;
        Serial.println(dg);
        
        for (i=0;i<REGSIZE;i++){
          wspeicher[i]=rspeicher[i];
    /*      Serial.print(rspeicher[i]);
          Serial.print (" ");*/
        }
    //    Serial.println();
      }
    }
    
    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEvent(int howMany) {
        byte x=0;
        
        if(howMany == 2){
          rdblock = Wire.read();
          if (rdblock<=240){
            rspeicher[rdblock]=Wire.read();
          }
          if (rdblock==REGSIZE-1){
            fertig=1;
          }
        }else{
          if (howMany == 1){
              x=Wire.read();
              if (x >=10 && x <=250){
                wrblock=x-10;
    /*            Serial.print("Lesebyte: ");
                Serial.println(wrblock);*/
              }
          }else{
            Serial.print ("Anzahl Daten: ");
            Serial.println(howMany);
            while (0 < Wire.available()) { //überflüssiges lesen
                x=Wire.read();
            }
          }
        }
    }
    
    // function that executes whenever data is requested by master
    // this function is registered as an event, see setup()
    void requestEvent() {
      //Wire.write(speicher[Register],1);
      puffer[0]=wrblock;
      puffer[1]=wspeicher[puffer[0]];
      Wire.write(puffer,2);
    /*  Serial.print("Sendebyte: ");
      Serial.println(puffer[0]);
    /*  Serial.print(", Wert: ");
      Serial.println(puffer[1]);*/
      
    }
    Raspi HW:
    Code:
    // GCC -Wall -pthread -o /var/scripte/i2cmaster01 /var/scripte/i2cmaster01.c -lpigpio -lrt
    // /var/scripte/i2cmaster01
    //I2C mit pipgio
    //peterfido
    //V0.0.2
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <pigpio.h>
    
    #define ADDRESS 0x04
    #define MSGSIZE  240
    char empfdata[MSGSIZE];  // 
    char senddata[MSGSIZE];
    char commando[32];
    
    int handle=0;
    int handles=-1;
    unsigned int laenge=0;
    
    volatile sig_atomic_t done = 0;
     
    void term(int signum)
    {
        done = 1;
    /*
        int res=0;
        int dl=0;
        if (handles >= 0){
            for (dl=0;dl<handles;dl++){
                res=i2cClose(dl);    
                printf("%d geschlossen: %d\n",dl, res);
            }
        }
        gpioTerminate();
        printf( "\nSIGINT wurde augeloest - Programm wird beendet\n" );
    
        exit( 1 );*/
    }
    
    void schreiben() {
        
        int res=0;
    //    int i=0;
        int wrblock=0;
        int Fehler=0;
        
        for (wrblock=0;wrblock<MSGSIZE;wrblock++){
    
            commando[0]=wrblock;
            commando[1]=senddata[wrblock];
            res=i2cWriteDevice(handle,commando,2);
            if (res!=0){
                printf("S I2C-Fehler: %d, Block: %d\n", res,wrblock);
                Fehler++;
    /*            wrblock--;
                usleep(15000); 
                if (Fehler==10){
                    break;
                }*/
                break;
            }
            usleep(15000);
        }
        
    /*    printf("Gesendet:\n");
        for(i=0;i<MSGSIZE;i++){
            printf("%d ",senddata[i]);
        }    
        printf("\n");
    */    
    }
    
    void lesen() {
        
        int res=0;
    //    int i=0;
        int rdblock=0;
        int Fehler=0;    
        
        for (rdblock=0;rdblock<MSGSIZE;rdblock++){
    
            commando[0]=rdblock+10;
            res=i2cWriteDevice(handle,commando,1);
            if (res==0){
                usleep(1000);
                res=i2cReadDevice(handle,commando,2);
                if (res==2){
                //    printf("Empfangene Daten: %d, Block: %d\n",res,rdblock);
                    if (rdblock==commando[0]){
                        empfdata[rdblock]=commando[1];
                    }
                }else{
                    printf("E Fehler beim Blockeinlesen: %d, Block: %d\n", res,rdblock);
                    Fehler++;
                    rdblock--;
                    usleep(15000);
                    if (Fehler==10){
                        break;
                    }
                    break;
                }
            }else{
                printf("E Fehler beim Leseblock schreiben %d, Block: %d\n", res,rdblock);
                break;
            }
        }    
    /*    
        printf("Empfangen:\n");
        for(i=0;i<MSGSIZE;i++){
            printf("%d ",empfdata[i]);
        }    
        printf("\n");    
    */    
    }
    
    int vergleichen()
    {
        unsigned int i=0;
        int ret=0;
        for (i=0;i<MSGSIZE;i++){
            if (empfdata[i]!=senddata[i]){
                ret=-1;
                break;
            }
        }
        return ret;
    }
    
    int main(int argc, char **argv)
    {
        int res=0;
        int i=0;
        long dg=1;
        long maxdg=0;
        unsigned int Fehler=0;
    
        struct sigaction action;
        memset(&action, 0, sizeof(struct sigaction));
        action.sa_handler = term;
        sigaction(SIGINT, &action, NULL);
        sigaction(SIGTERM, &action, NULL);
        
        if (gpioInitialise() < 0)
        {
            printf("Fehler beim Initialisieren von gpio!");
            gpioTerminate();
        }else{
            handle=i2cOpen(1,ADDRESS,0);
            if(handle>=0){
                handles ++;
                printf("\n\n\nStarte I2C-Test (%d)\n\n",handle);
                while (!done)
                {    
                    srand(time(NULL));
                    for(i=0;i<MSGSIZE;i++){
                         senddata[i]=rand() % 255;
                    }        
                    schreiben();
                    usleep(100000);
                    lesen();
                    usleep(100000);
                    if (vergleichen()==0){
                            printf("Daten OK %ld (%ld)\n",dg,maxdg);
                            Fehler=0;
                            dg++;
                    }else{
                        printf("***************************** Daten fehlerhaft %ld *****************************\n",dg);
                        Fehler++;
                        dg=0;
                        if (dg>maxdg){
                            maxdg=dg;
                        }
                        sleep(1);
                        if (Fehler==100){
                            break;
                        }
                    }
                }
            }else{
                printf("E Fehler beim Oeffnen: %d\n", handle);    
            }
        }
        res=i2cClose(handle);
        
        if (res!=0){
            printf("E Fehler beim Schliessen: %d\n", res);
        }else{
            handles--;
            printf("E Schliessen OK %d\n",handle);
        }
    
        gpioTerminate();
        
        return 0;
    }
    Raspi BitBang:
    Code:
    // GCC -Wall -pthread -o /var/scripte/bbi2cmaster /var/scripte/bbi2cmaster.c -lpigpio -lrt
    // /var/scripte/bbi2cmaster
    //I2C mit pipgio
    //peterfido
    //V0.0.2
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <pigpio.h>
    
    #define SDA 2
    #define SCL 3
    #define TAKT 100000
    #define PAUSEN 5000
    #define ADDRESS 0x04
    #define MSGSIZE  240
    
    
    
    char empfdata[MSGSIZE];  // 
    char senddata[MSGSIZE];
    char commando[64];
    char puffer[12];
    
    unsigned int laenge=0;
    
    volatile sig_atomic_t done = 0;
     
    void term(int signum)
    {
        done = 1;
    }
    
    int I2CResetBus(void)
    {
        char i;
        int res=0;
        if(gpioRead(SDA) && gpioRead(SCL)) {
            return 0;
        }
        gpioSetMode(SCL, PI_INPUT);
        gpioSetMode(SDA, PI_INPUT);
        gpioSetPullUpDown(SDA, PI_PUD_UP);   // Sets SDA pull-up.
        gpioSetPullUpDown(SCL, PI_PUD_UP);   // Sets SDA pull-up.       
        usleep(50);
        if(!gpioRead(SCL)) {
            return -1; /* SCL wird extern auf Low gehalten, nix zu machen */
        }
        for(i = 0; i<9; i++) { 
            gpioSetMode(SCL, PI_OUTPUT);
            gpioWrite(SCL, 0);
            usleep(50);
            gpioSetMode(SCL, PI_INPUT);
            gpioSetPullUpDown(SCL, PI_PUD_UP);   // Sets SDA pull-up.       
            usleep(50);
            if(gpioRead(SDA)) {
                break; /* SDA ist high STOP */
            }
        } /* for */
        if(!gpioRead(SDA)) {
            return -1; 
        }
        commando[0]= 3;    //stop
        commando[1]= 0;    // Fertig
        res=bbI2CZip(SDA,commando,2,NULL,0);
        if (res!=0){
            printf("Fehler beim Reset!\n");
        }
        if(gpioRead(SDA) && gpioRead(SCL)){  
            return 0;
        }else{
            return -1;  
        }
    }
    
    
    void schreiben() {
        
        int res=0;
    //    int i=0;
        int wrblock=0;
        int Fehler=0;
        
        for (wrblock=0;wrblock<MSGSIZE;wrblock++){
    
            commando[0]= 4;    //'Adresse setzen ankündigen
            commando[1]= ADDRESS;    //'Adresse übergeben
            commando[2]= 2;    //start
            commando[3]= 7;    //'Bytes senden
            commando[4]= 2;    //'Anzahl 
            commando[5]= wrblock;    //Block
            commando[6]= senddata[wrblock];   //Wert
            commando[7]= 3;    //stop
            commando[8]= 0;    //keine weiteren Parameter
            res=I2CResetBus();
            res=bbI2CZip(SDA,commando,9,NULL,0);
            res=I2CResetBus();
            if (res!=0){
                printf("S I2C-Fehler: %d, Block: %d\n", res,wrblock);
                Fehler++;
                wrblock--;
                usleep(PAUSEN*3); 
                if (Fehler==10){
                    break;
                }
            }
            usleep(PAUSEN);
        }
    /*    
        printf("Gesendet:\n");
        for(i=0;i<MSGSIZE;i++){
            printf("%d ",senddata[i]);
        }    
        printf("\n");
    */
    }
    
    void lesen() {
        
        int res=0;
    //    int i=0;
        int rdblock=0;
        int Fehler=0;    
        
        for (rdblock=0;rdblock<MSGSIZE;rdblock++){
    
            commando[0]= 4;    //'Adresse setzen ankündigen
            commando[1]= 4;    //'Adresse übergeben
            commando[2]= 2;    //start
            commando[3]= 7;    //'Bytes senden
            commando[4]= 1;    //'Anzahl 
            commando[5]= rdblock+10;    //Byte
            commando[6]= 2;    //start
            commando[7]= 6;    //Bytes lesen
            commando[8]= 2;    //Anzahl
            commando[9]= 3;    //stop
            commando[10]= 0;    //keine weiteren Parameter
            res=I2CResetBus();
            res=bbI2CZip(SDA,commando,11,puffer,12);    
            res=I2CResetBus();
            
            if (res==0){
                if (puffer[0]==rdblock){
                    empfdata[rdblock]=puffer[1];
                    Fehler=0;
                }else{
                    printf("E Falsche Blocknummer. Erwartet: %d, bekommen: %d, Wert: %d\n",rdblock,puffer[0],puffer[1]);
                    Fehler++;
                    rdblock--;
                    if (Fehler==10){
                        break;
                    }
                }
            }else{
                printf("E Fehler beim Blockeinlesen. Block: %d\n",rdblock);
                Fehler++;
                rdblock--;
                if (Fehler==10){
                    break;
                }
            }
            usleep(PAUSEN);
        }    
        
        printf("Empfangen:\n");
    /*    for(i=0;i<MSGSIZE;i++){
            printf("%d ",empfdata[i]);
        }    
        printf("\n");    
    */    
    }
    
    int vergleichen()
    {
        unsigned int i=0;
        int ret=0;
        for (i=0;i<MSGSIZE;i++){
            if (empfdata[i]!=senddata[i]){
                ret=-1;
                break;
            }
        }
        return ret;
    }
    
    int main(int argc, char **argv)
    {
        int res=0;
        int i=0;
        long dg=1;
        long maxdg=0;
        unsigned int Fehler=0;
    
        struct sigaction action;
        memset(&action, 0, sizeof(struct sigaction));
        action.sa_handler = term;
        sigaction(SIGINT, &action, NULL);
        sigaction(SIGTERM, &action, NULL);
        
        if (gpioInitialise() < 0)
        {
            printf("Fehler beim Initialisieren von gpio!");
            gpioTerminate();
        }else{
            res=bbI2COpen(SDA,SCL,TAKT);
            res=res+gpioSetMode(SDA, PI_INPUT);  // Set SDA as input.
            res=res+gpioSetMode(SCL, PI_INPUT);  // Set SDA as input.
            res=res+gpioSetPullUpDown(SDA, PI_PUD_UP);   // Sets SDA pull-up.
            res=res+gpioSetPullUpDown(SCL, PI_PUD_UP);   // Sets SDA pull-up. 
    
            if(res==0){
                printf("\n\n\nStarte I2C-Test\n\n");
                while (!done)
                {    
                    srand(time(NULL));
                    for(i=0;i<MSGSIZE;i++){
                         senddata[i]=rand() % 255;
                    }        
                    schreiben();
                    usleep(5000);
                    lesen();
                    usleep(5000);
                    if (vergleichen()==0){
                            printf("Daten OK %ld (%ld)\n",dg,maxdg);
                            Fehler=0;
                            dg++;
                    }else{
                        printf("***************************** Daten fehlerhaft %ld *****************************\n",dg);
                        Fehler++;
                        dg=0;
                        if (dg>maxdg){
                            maxdg=dg;
                        }
                        sleep(1);
                        if (Fehler==100){
                            break;
                        }
                    }
                }
            }else{
                printf("E Fehler beim Oeffnen\n");    
            }
        }
        res=bbI2CClose(SDA);
        
        if (res!=0){
            printf("E Fehler beim Schliessen: %d\n", res);
        }else{
            printf("E Schliessen OK\n");
        }
    
        gpioTerminate();
        
        return 0;
    }
    Mein Fazit:
    Ich bleibe bei UART.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

Ähnliche Themen

  1. Raspi mit Arduino per USB verbinden
    Von HaWe im Forum Raspberry Pi
    Antworten: 4
    Letzter Beitrag: 11.11.2015, 16:26
  2. [ERLEDIGT] Raspi Club?
    Von pofoklempner im Forum Raspberry Pi
    Antworten: 16
    Letzter Beitrag: 09.07.2015, 06:20
  3. Antworten: 1
    Letzter Beitrag: 12.06.2015, 14:50
  4. Antworten: 5
    Letzter Beitrag: 24.08.2014, 16:36
  5. Schnelle(!) Objekterkennung mit Raspi+USB-Cam
    Von phantom111 im Forum Sensoren / Sensorik
    Antworten: 19
    Letzter Beitrag: 20.02.2014, 12:18

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen