简体   繁体   中英

Raspberry Pi I2C

I have multiple arduino's that talk back and forth using I2C. The master write two bytes and then reads 1 byte response back. Everything worked great and horray. But now I've been working on switching my master to a Raspberry Pi. The code that I have written works with no problems but 1 in every 200 read/write, it returns an occasional wrong reading which would be a huge set back on the system's reliability. I'm attaching my code just in case someone see anything that I am doing wrong or if anyone else have ran into similar issue before.

RPi C++ Code:

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "../HaMiD_Lib/StopWatch.h"

using namespace std;

int file_i2c;
int length;
uint8_t buffer[2] = {0};

int timingLoopFreq = 500;       
int timingLoopMicroSeconds = 1000000 / timingLoopFreq;      //500 us
StopWatch loopTime(timingLoopMicroSeconds);                 // My own stopwatch livrary
uint8_t addr = 0x11;

using namespace std;

int main(void)
{
         //-------------- OPEN THE I2C BUS--------------------------
        char *filename = (char*)"/dev/i2c-1";
        if((file_i2c = open(filename, O_RDWR))< 0 ){
                //ERROR HANDLING: you can check errno to see what went wrong;
                cout << "Failed to open the i2c bus" << endl;
                return 0;
        }

        while(1){
                if (loopTime.check()) {
                        loopTime.reset();

                        if (ioctl(file_i2c, I2C_SLAVE, addr) < 0){
                                cout << "Failed to acquire bus access and/or talk to slave" << endl;
                                //ERROR HANDLING: you can check errno to see what went wrong;
                        }

                        // ------------- WRITE BYTES -------------
                        buffer[0] = 4;
                        buffer[1] = 0;
                        length = 2;                 //<<<<< Number of bytes to write
                        if (write(file_i2c, buffer, length) != length){                    // write() returns the number of bytes actually written, if it doesn't match then an error occurred (e.g. no response from the device)
                        // ERROR HANDLING: i2c transaction failed
                                cout << "Failed to write to the i2c bus " << endl;
                        } else {
                                    // ------------ READ BYTES -------
                                    length = 1;
                                    if (read(file_i2c, buffer, length) != length){              // read() returns the number of bytes actually read, if it doesn't match then an error occurred (e.g. no response from the device)
                                        //ERROR HANDLING: i2c transaction failed
                                        cout <<"Failed to read from the i2c bus" << endl;
                                    } else {
                                            cout << "Data read:" << buffer[0] << endl;
                                }
                        }
                }
        }
        cout << "exiting" << endl;
        return 0;
}

Arduino I2C Snippet:

//I2C functions
void receiveEvent(int byteCount) {
    while (Wire.available()) {
        I2C_cmd_1st = Wire.read(); // 1 byte (maximum 256 commands)
        I2C_cmd_2nd = Wire.read(); // 1 byte (maximum 256 commands)
    }
}

void slavesRespond() {
    byte returnValue = 0;

    switch (I2C_cmd_1st) {
    case status_cmd:   // 40
        returnValue = module;
        if (module == DONE) {
            module = STOP;                  //reset the machine
        }
        break;
    case test_cmd:
        returnValue = ID;
        break;
    }
    Wire.write(returnValue);          // return response to last command
}

And here is a small section of the output from cout. The Data read should always return 2 but once a while (1 in 100) it fails to read or write from i2c bus and sometimes (1 in 500) it returns a wrong value (in below example it should return 2 but it sometimes return 3 by accident or it could be 97 or etc).

Data read:2
Data read:3    //This is wrong!
Data read:2
Failed to read from the i2c bus
Failed to read from the i2c bus
Data read:3    //This is wrong!
Data read:2

Any help would be appreciated. Has anyone else seen something similar with RPi and Arduino? The wiring is pretty straight forward cause RPi is the master.

Have you tried to read at receive event only as my data as it was actually available. Code takes into account that byteCount in receiveEvent is divisible by 2.

for the failed to read i2c bus problem try

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=2,bus=1

insted of

dtparam=i2c_arm=on

in /boot/config.txt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM