简体   繁体   English

树莓派 I2C

[英]Raspberry Pi I2C

I have multiple arduino's that talk back and forth using I2C.我有多个使用 I2C 来回通话的 arduino。 The master write two bytes and then reads 1 byte response back.主机写两个字节,然后读回 1 个字节的响应。 Everything worked great and horray.一切都很顺利。 But now I've been working on switching my master to a Raspberry Pi.但现在我一直在努力将我的主人切换到 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.我编写的代码没有问题,但每 200 次读/写中就有 1 次,它偶尔会返回错误读取,这将对系统的可靠性造成巨大影响。 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: RPi C++ 代码:

#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: Arduino I2C 代码段:

//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.这是 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).读取的数据应始终返回 2,但有时(100 分之一)无法从 i2c 总线读取或写入,有时(500 分之一)返回错误值(在下面的示例中,它应返回 2,但有时返回 3偶然或可能是 97 等)。

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?有没有其他人看到过与 RPi 和 Arduino 类似的东西? The wiring is pretty straight forward cause RPi is the master.接线非常简单,因为 RPi 是主控。

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.代码考虑到了byteCount中的receiveEvent可以被 2 整除。

for the failed to read i2c bus problem try对于无法读取 i2c 总线问题,请尝试

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在 /boot/config.txt

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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