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.