- Labornetzteil AliExpress         
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,

    ja, ich werde auf die Pullups warten. Die sollten demnächst eintrudeln.

    Wenn die stören, opfere ich ein USB-Kabel und führe die 5V über eine 3V3 Regelplatine zum ARDUINO.

    Das Protokoll habe ich gestern schon bissel bearbeitet, ist aber noch nicht fertig. Zumindest klappt die Sync noch nicht.

    Edit:
    Danke für die Recherche mit den Pullups. Da sich ein Raspi vor einiger Zeit schon verabschiedet hat, messe ich jetzt immer doppelt und dreifach, bevor ich was verbinde
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  2. #2
    HaWe
    Gast
    klasse, wär ja super, wenn wir da was gemeinsam auf die Beine stellen könnten.
    Ich hab gestern abend/nacht schon einen älteren Levelshifter bei mir probiert, damit gings nicht. ich hab aber noch einen neueren, ungebrauchten, mal gucken, was der sagt.
    heute abend weiß ich mehr...

    ps:
    wie man I2C buffer_size beim Arduino vergrößert, weiß ich zwar, aber nicht wie's beim Raspi geht.
    64 bytes wären schön auf beiden Seiten, dann kann man sogar jede menge long-int Encoder-Werte oder floats übertragen...

    Haste du da evtl auch ne Idee?

  3. #3
    HaWe
    Gast
    klappt bei mir nicht mit Mega und Levelshifter:
    für die ersten 10 bis 30 Arrays werden vom Slave Daten ausgetauscht, dann passiert am Mega plötzlich nichts mehr;
    auch der Raspi kriegt keine neuen Daten mehr: I2C tot.

    i2cdetect -y l zeigt anschließend keinen i2c-slave mehr an 0x04 an.

    Code:
    pi@raspberrypi ~ $ i2cdetect -y 1
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    Jetzt hab ich noch einen 3. Levelshifter gefunden, da sind aber noch keine Pins dran....: morgen also....


    Der Raspi-Code muss übrigens noch etwas abgeändert werden, dass er nur dann seine Test-Variable weiterzählt, wenn er vorher einen korrekten Array vom Slave bekommen hat - er ist jetzt schon besser, aber noch nicht 100% ok:


    Code:
    //  Raspberry Pi Master code to send/receive byte arrays
    //  to an Arduino as an I2C slave
    // 
    //  ver. 0.002
    //
    //  protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
    //  http://creativecommons.org/licenses/by-nc-sa/3.0/   //   
    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <wiringPi.h>
    #include <wiringPiI2C.h>
    
    #include <errno.h>
    #include <string.h>
    
    #define MSGSIZE 30
    
    
    unsigned char  calcchecksum( unsigned char array[]) {   
      int32_t  sum=0;
      for(int i=2; i<MSGSIZE; ++i) sum+=(array[i]);
      return (sum & 0x00ff);
    }
    
    
    
    int main (void)
    {
       
      int fd, i ;
      unsigned char test=0;
      unsigned char data [MSGSIZE] ;
    
      if ((fd = wiringPiI2CSetup (0x04) ) < 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 < MSGSIZE ; ++i)
              printf ("  %3d", data [i]) ;
           printf ("\n") ;
           delay(10) ;
         
           memset(data, 0, sizeof(data) );
           data[5]=  test++;
           data[0]=  0xff;
           data[MSGSIZE-1]= 0x04;
           data[1] = calcchecksum( data );
           
           write(fd, data, MSGSIZE) ;
           printf ("write: ");
           for (i = 0 ; i < MSGSIZE ; ++i)
             printf ("  %3d", data [i]) ;
           printf ("\n\n") ;
           delay(10) ;     
        }
      }
    
      return 0 ;
    }
    dann alles wieder umgesteckt auf 3,3V Due...:
    fluppt.

    - - - Aktualisiert - - -

    ps,

    im Augenblick re-synced er sogar automatisch:
    nach Rausnehmen einer i2c-Leitung stoppt die Transmission auf dem Slave

    (blöderweise zählt der Raspi trotzdem weiter...: to do: error handling),

    aber nach wiedereinstecken machen Raspi und Arduino wieder ganz normal weiter.
    Geändert von HaWe (09.02.2016 um 22:33 Uhr)

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    67
    Beiträge
    2.435
    Hallo,
    Zitat Zitat von HaWe Beitrag anzeigen
    klappt bei mir nicht mit Mega und Levelshifter:
    für die ersten 10 bis 30 Arrays werden vom Slave Daten ausgetauscht, dann passiert am Mega plötzlich nichts mehr;
    auch der Raspi kriegt keine neuen Daten mehr: I2C tot.
    Für so etwas gibt es eigentlich nur eine Ursache: Störungen.

    Entweder ist es ein Hardware-Problem, dann muss man am Error-Handlich arbeiten. Es sollte zumindest eine Störungsmeldung auftreten, welche eine Neu-Synchronisation ermöglicht. Wenn die Störung allerdings einen Latch-Up erzeugt, hilft nur Aus/Einschalten

    Oder es liegt an der Software. Typische Fehlerquellen sind Interrupts, weil sie ganz einfach das Timing "versauen", der Stack zu klein ist, ein Pointer in die Irre zeigt oder ein Register nicht gerettet/gestört wird.
    Vor allem den Stack (Auto Variablen) muss man sich sehr genau ansehen. Zugriffe ausserhalb von Array-Grenzen führen zu sehr lustigen Effekten.

    Bei einem meiner ersten Projekte(6502 @1MHz, Assembler) hatte ich im Schnitt 1x in der Wochen einen Programmabsturz. Manchmal, auch wiederholt, schon mach 1-2 Minuten. Die Ursache war dann, dass der Interrupt 1x pro Sekunde für einen Takt fälschlicherweise offen war, Wahrscheinlichkeit 1:1'000'000.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  5. #5
    HaWe
    Gast
    wie gesagt: Tipps aus dem Blauen wieder ins Blaue bingen nichts.........:
    Für alle Tipps bin ich natürlich offen, aber der, der sie vorschlägt, müsste schon in der Lage sein, die Verbindung ebenfalls herzustellen und bei sich selber vor Ort zu testen (d.h. er müsste auch einen Raspi und einen Arduino besitzen und sie entsprechend verbinden und seinen eigenen - bzw. unseren gemeinsamen, auf einander abgestimmten - Code testen können).

  6. #6
    HaWe
    Gast
    update:
    nicht nur mit dem Mega scheint es Probleme zu geben sondern auch mit anderen AVRs.
    Uno habe ich keinen, aber ich habe jetzt einen Nano getestet:

    Auch mit dem Nano (keine Pullups eingebaut, daher braucht er keine Levelshifter) dasselbe Phänomen wie beim Mega MIT Levelshiftern:

    er überträgt eine Handvoll Zyklen lang (mal 2, mal 10, mal bis zu 30) und dann blockiert die Übertragung. Der Raspi erkennt dann auch hier den Arduino nicht mehr als Slave, Adresse 0x04 ist leer.

    Nach resetten des Nanos geht es erst wieder kurz, dann wieder Schicht.

    Jetzt bräuchte man wen, der ein Oszi hat (wenn man das überhaupt nachmessen kann). Es scheint vllt doch am Clock-Stretching zu liegen, was evtl besonders die AVRs betrifft, scheinbar weniger die ARMs.


    hab jetzt die Datenausgabe auf dem Pi ein wenig geändert, um es besser verfolgen zu können:
    Beim Lesen bleibt der Pi beim AVR (Nano und Mega) recht schnell hängen, beim Schreiben zählt er weiter - aber beim AVR kommt nichts mehr an.

    Code:
    //  Raspberry Pi Master code to send/receive byte arrays
    //  to an Arduino as an I2C slave
    // 
    //  ver. 0.002a
    
    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <wiringPi.h>
    #include <wiringPiI2C.h>
    
    #include <errno.h>
    #include <string.h>
    
    #define MSGSIZE 30
    
    
    unsigned char  calcchecksum( unsigned char array[]) {   
      int32_t  sum=0;
      for(int i=2; i<MSGSIZE; ++i) sum+=(array[i]);
      return (sum & 0x00ff);
    }
    
    
    
    int main (void)
    {
       
      int fd, i ;
      unsigned char test=0;
      unsigned char data [MSGSIZE] ;
    
      if ((fd = wiringPiI2CSetup (0x04) ) < 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]= 0x04;
           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 ;
    }
    Code:
    //  Arduino code to send/receive byte arrays
    //  Arduino as an I2C slave
    //
    //  ver. 0.002
    
    
    #include  <Wire.h>
    
    #define  SLAVE_ADDRESS 0x04
    #define  MSGSIZE  30
    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..
    }
    Nach kurzem Lauf wieder kein AVR-slave mehr dann an I2C detektiert
    Code:
    pi@raspberrypi ~ $ i2cdetect -y 1
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    erst nach Resetten ist 0x04 wieder da - beim nächsten Programmstart aber schnell wieder rausgekickt.

    Wie gesagt, wie bisher aber kein Problem mit dem Due.

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

    die Pegelwandler sind da. Damit funktioniert der letzte Code. Da auch mein Raspi nach einiger Zeit den Slave nicht mehr finden konnte, habe ich doch noch ein USB-Kabel geopfert und die 5V-Ader durchtrennt, sodass der ARDUINO mit 3V3 läuft. Flashen und Seriell funktioniert alles. Bei der I2C-Verbindung nach einiger Zeit das gleiche Problem.

    Solange die beiden miteinander 'reden' bleibt die Verbindung stabil. Beende ich das Master-Programm auf dem Raspi, erlischt nach einiger Zeit die LED auf dem ARDUINO und dann ist der Slave nicht mehr zu finden. Resete ich den ARDUINO, ohne das Masterprogramm am Raspi zu starten, erlischt oft, aber nicht immer, die LED auch wieder nach einiger Zeit und der Slave ist wech. Scheint, als ob der Slave-Code es nicht mag, wenn der Master nicht da ist.

    Ich musste die BAUD-Rate auf dem ARDUINO auf 57600 runtersetzen. Bei 115200 BAUD kommt sowohl bei 3V3 als auch bei 5V nur Müll im Terminal an.

    Beschäftigt man den ARDUINO zusätzlich noch etwas, gehen Daten verloren. Viel Luft ist also nicht. Wenn dieser als Gateway / 'Relaisstation' dienen soll, muss da ein gutes Protokoll her.


    Das wars für Heute. Morgen Abend geht es weiter.

    Gruß
    Peterfido
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  8. #8
    HaWe
    Gast
    Die Masseleitungen sind in beiden Fällen exakt gleich lang - es sind sogar dieselben Kabel, sie wurden nur umgesteckt. Die Masseleitungen der beiden Boards sind direkt miteinander verbunden, genau wie die i2c-Leitungen.
    Und der Fehler tritt bei 2 verschiedenen AVRs auf, nicht aber bei einem ARM - mehrfach hin- und hergesteckt. Und er tritt auch auf, wenn die AVRs stand-allone laufen.
    Auch andere User haben i.Ü, diesen AVR-spezifischen Fehler reproduziert - nicht nur in diesem Forum.

    Im übrigen bitte ich dich, zuerst den Aufbau zu nachzubauen, das jetzige Verhalten zu überprüfen und dann deine Theorie zu testen. Teste es also erst selber und DANN poste!

    Denn wie schon mehrfach gesagt: Tipps aus dem Blauen wieder ins Blaue bingen nichts.........:
    Für alle Tipps bin ich natürlich offen, aber der, der sie vorschlägt, müsste schon in der Lage sein, die Verbindung ebenfalls herzustellen und bei sich selber vor Ort zu testen (d.h. er müsste auch einen Raspi und einen Arduino besitzen und sie entsprechend verbinden und seinen eigenen - bzw. unseren gemeinsamen, auf einander abgestimmten - Code testen können).
    Geändert von HaWe (11.02.2016 um 15:33 Uhr)

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

    so wie es aussieht, liegt es am MEGA, wenn die Kommunikation zusammenbricht. Mal hält dieser dann SCL auf Low und mal reagiert er einfach nicht mehr. Allerdings immer nach unterschiedlicher Zeit. Mal läuft es minutenlang durch und mal klemmt es nach wenigen Sekunden. Egal ob mit Pegelwandler oder direkt verbunden und 3V3 Versorgung des MEGA. Der MEGA hängt sich allerdings nicht weg. Die Hauptschleife läuft weiter.


    Die Pegelwandler sind 1A. Selbst bei 24MHZ erkennt mein LA keine Verzögerung.

    An einem Protokoll brauchen wir noch nicht zu arbeiten, solange die Verbindung unzuverlässig ist.
    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
  •  

Labornetzteil AliExpress