-         

Seite 1 von 7 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 64

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

  1. #1
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.559

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

    Anzeige

    hallo,
    hat oder kennt hier jemand funktionierenden Code in C für den Raspi, um via I2C einen Arduino als Multiplexer Board zu nutzen?
    Es müssen vom Raspi als Master nur "rohe" byte arrays (Größe bis 30 bytes) auf den Arduino übertragen (abwechselnd geschrieben/gelesen) werden.

    Per UART habe ich es problemlos hinbekommen (sowohl Arduino/Arduino als auch Raspi/Arduino),
    und per I2C klappt auch Arduino zu Arduino einwandfrei.
    Auch Auslesen eines I2C Sensors (CMPS11) klappt wunderbar mit dem Raspi, und ntl auch mit dem Arduino.

    Nur leider scheitert es mit Raspi als i2c-Master zum Arduino, und mir fehlen leider die C- und device tree- Kenntnisse für den Raspi, um das umzusetzen. So schöne einfache Dinge wie
    Wire.requestFrom(address, count)
    Wire.beginTransmission(address)
    Wire.endTransmission()
    Wire.send()
    Wire.available()
    Wire.receive()
    Wire.onReceive(handler)
    Wire.onRequest(handler)
    etc. gibt es ja beim Raspi nicht.

    Hat oder kennt wer fertigen Code, den ich dafür verwenden könnte?


    edit:
    dies ist der Arduino Slave code, der ansonsten gut mit dem entsprechenden Arduino-Master-Code zusammen funktioniert
    - jetzt soll ein passender Raspi-Master-Code her:

    Code:
    //  Arduino code to send/receive byte arrays
    //  Arduino as an I2C slave
    //  compiles for MEGA and DUE, IDE 1.6.5
    //  ver. 0.001
    
    
    #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]
    
       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(2);                                     // 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 (04.02.2016 um 12:06 Uhr)
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von m.a.r.v.i.n
    Registriert seit
    24.07.2005
    Ort
    Berlin
    Beiträge
    1.247
    Hallo HaWe,
    WiringPi unterstützt auch I2C. https://projects.drogon.net/raspberr...i/i2c-library/ . Damit sollte es klappen.

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.559
    ja, aber ich kriege keinen Code für die array- Kommunikation zum Arduino hin, weder mit dem normalen read() noch mit den WiringPi Funktionen
    wiringPiI2CReadReg8(addr, reg)
    denn der Arduino hat ja keine Register.
    normales wiederholtes read() liest aber immer nur das 1. array-byte aus (also array[0]), der Arduino incrementiert seinen Zähler (Lese-Buffer-Pointer) nicht.

    edit: einzelne Bytes schreiben + lesen funktioniert! Nur array-Zellen nacheinander auslesen nicht!

    Wird er von einem anderen Arduino als Master mit Wire.requestFrom(address, count) etc. wiederholt ausgelesen, dann liest er alle array[i] nacheinander aus, so wie es sein soll.

    Selbst Gordon Henderson hat aber bisher mit seiner eigenen Lib und Arduino-IDE-programmiereten Arduinos keine als slaves auslesen können/wollen - nur mit bare-metal-programmierten AVRs hat er es schon mal gemacht (also ohne die Arduino-Wire-Class).

    "...damit sollte es klappen" führt hier offenbar nicht weiter: Höchstwahrscheinlich ist wiringPi dafür eine Sackgasse.

    Daher brauche ich jemanden, der mir einen Code vorschlagen kann, der tatsächlich mit arrays zwischen Raspi und Arduino (Wire) funktioniert.
    Geändert von HaWe (05.02.2016 um 12:59 Uhr)
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  4. #4
    Erfahrener Benutzer Roboter Genie Avatar von m.a.r.v.i.n
    Registriert seit
    24.07.2005
    Ort
    Berlin
    Beiträge
    1.247
    Hast du mal so etwas probiert?
    Code:
      unsigned char rcvbuff[30];
      int fd = wiringPiI2CSetup(0x04);
      read(fd, rcvbuff, 30);
      close(fd);
    und zum senden:
    Code:
      unsigned char sndbuff[30];
      int fd = wiringPiI2CSetup(0x04);
      write(fd, sndbuff, 30);
      close(fd);

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.559
    ich habe diesen Code probiert von http://blog.retep.org/2014/02/15/con...-pi-using-i2c/

    Code:
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <linux/i2c-dev.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <unistd.h>
     
    // The PiWeather board I2C address
    #define ADDRESS 0x04
     
    // The I2C bus: This is for V2 pi's. For V1 Model B you need i2c-0
    static const char *devName = "/dev/i2c-1";
     
    int main(int argc, char** argv) {
     
      if (argc == 1) {
        printf("Supply one or more commands to send to the Arduino\n");
        exit(1);
      }
     
      printf("I2C: Connecting\n");
      int file;
     
      if ((file = open(devName, O_RDWR)) < 0) {
        fprintf(stderr, "I2C: Failed to access %d\n", devName);
        //fprintf( stderr, “I2C: Failed to access %s : %s\n”, devName, strerror (errno) );
        exit(1);
      }
     
      printf("I2C: acquiring buss to 0x%x\n", ADDRESS);
     
      if (ioctl(file, I2C_SLAVE, ADDRESS) < 0) {
        fprintf(stderr, "I2C: Failed to acquire bus access/talk to slave 0x%x\n", ADDRESS);
        exit(1);
      }
     
      int arg;
     
      for (arg = 1; arg < argc; arg++) {
        int val;
        unsigned char cmd[16];
     
        if (0 == sscanf(argv[arg], "%d", &val)) {
          fprintf(stderr, "Invalid parameter %d \"%s\"\n", arg, argv[arg]);
          exit(1);
        }
     
        printf("Sending %d\n", val);
     
        cmd[0] = val;
        if (write(file, cmd, 1) == 1) {
     
          // As we are not talking to direct hardware but a microcontroller we
          // need to wait a short while so that it can respond.
          //
          // 1ms seems to be enough but it depends on what workload it has
          usleep(10000);
     
          char buf[1];
          if (read(file, buf, 1) == 1) {
            int temp = (int) buf[0]; 
            printf("Received %d\n", temp);
          }
        }
     
        // Now wait else you could crash the arduino by sending requests too fast
        usleep(10000);
      }
     
      close(file);
      return (EXIT_SUCCESS);
    }
    und den Teil
    Code:
    char buf[1];
          if (read(file, buf, 1) == 1) {
            int temp = (int) buf[0]; 
            printf("Received %d\n", temp);
          }
    geändert in

    Code:
    char buf[30];
          if (read(file, buf, 30) == 1) {
            for (int  j = 0; j<30; ++j) {
               temp=buf[j]; 
               printf("Received %d\n", temp);
            }
          }
    aber er liest hier nur 30x das erste byte in array[0] und nicht den Rest des arrays.

    Ich denke auch, es macht keinen Sinn an diesem beispiel rumzudoktern, man braucht völlig neu aufgesetzten Raspi- Code zum abwechselnen wiederholten array- schreiben und lesen.

    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 (05.02.2016 um 16:57 Uhr) Grund: syntax typo berichtigt
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  6. #6
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    24.06.2004
    Ort
    Berlin
    Alter
    52
    Beiträge
    377
    for (int j = 0; j<30; j++) {
    das leben ist hart, aber wir müssen da durch.

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.559
    for (int j = 0; j<30; j++)
    ja, klar, daran liegt es nicht, das war ein typo und war hier nur blind eingefügt gewesen.

    ansonsten, wie gesagt,
    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).
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.559
    update:
    habe jetzt einen ersten Testcode als Arbeitsgrundlage: mein eigener Arduino Slave code und ein zusätzlicher Raspi Master code (eine einfache Raspi-Mustervorlage dafür hatte Gordon Henderson gepostet und wurde entsprechend angepasst) - ist aber noch extrem langsam und muss noch dringend schneller gemacht werden:

    http://www.mindstormsforum.de/viewto...tart=15#p67908


    Verbesserungs- und Beschleunigungs-Tipps von Raspi-Profis werden gern entgegengenommen!
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    60
    Beiträge
    2.435
    Hallo,
    Zitat Zitat von morob Beitrag anzeigen
    for (int j = 0; j<30; j++) {
    ++j und j++

    Sind hier identisch: j = j+1

    Unterschiede gibt es, wenn j verwendet wird.
    c[j++] --> c[j]; j=j+1;
    c[++j] --> c[j+1]; j=j+1;

    a = c[--i]; und c[i++] = a; können eigentlich alle CPUs als jeweils einzelnen Assembler-Befehl ausführen (PUSH und POP). Manchmal auch als a = c[i--]; und c[++i] = a; implementiert.
    Bei manchen CPUs beschränkt sich diese Adressierungsart nicht nur auf den Stack und kann auch symmetrisch sein.

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

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.559
    danke, aber was soll das jetzt? Die Frage war nicht nach pre- oder post-increment, das ist mir sonnenklar, sondern nach einem Code, der eine schnelle I2C Verbindung zwischen Raspi-Master und Arduino-Slave herstellt.
    Ausgangsbasis kann der obige Code im oben verlinkten Post sein
    - immerhin gibt es ja inzwischen einen, der zumindest funktioniert, wenn auch extremst langsam - :
    http://www.mindstormsforum.de/viewto...tart=15#p67908

    aber wenn Vorschläge, dann bitte selbst getestet: es ist das exakte Zusammenspiel der beiden i2c-Protokolle, das Probleme macht!
    (Und bitte erst recht keine OT-Posts.)

    Denn, wie gesagt:
    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).
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

Seite 1 von 7 123 ... LetzteLetzte

Ähnliche Themen

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

Berechtigungen

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