我想使用I2C从arduino到raspberry pi接收多个数据

时间:2019-10-07 06:22:42

标签: c++ arduino raspberry-pi i2c

感谢任何有心研究这个问题的人。

我想使用I2C从arduino到树莓派接收多个数据。

我可以从arduino获取1个数据,但是一旦移至多个数据,它就无法这样做。

到目前为止,我已经尝试了多种方法,并且发现该方法最有效地从Arduino获取数据。

我以前从arduino获取数据的尝试如下: I want to read from Arduino using I2C using Raspberry Pi Raspberry Pi's terminal response has weird font that cannot be recognized

到现在所有问题都解决了。 从下面的链接获得了大量帮助 https://area-51.blog/2014/02/15/connecting-an-arduino-to-a-raspberry-pi-using-i2c/

Arduino代码

#include <Wire.h>

#define echoPin 7
#define trigPin 8

int number=0;
long duration;
long distance;

void setup()
{
  //Join I2C bus as slave with address 8
  Wire.begin(8);

  //Call SendData & Receive Data
  Wire.onRequest(SendData);
  //Setup pins as output and input to operate ultrasonic sensor
  Serial.begin(9600);
  pinMode(echoPin,INPUT);
  pinMode(trigPin,OUTPUT);
}

void loop ()
{
  digitalWrite(trigPin,LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin,HIGH);
  delayMicroseconds(2);

  digitalWrite(trigPin,LOW);

  duration=pulseIn(echoPin,HIGH);

  distance=duration/58.2;

  Serial.print(distance);
  Serial.println(" cm");
}

void SendData()
{
  Wire.write(distance);
  Wire.write("Why No Work?");
  Wire.write(distance);
}

C ++代码

//Declare and Include the necessary header files
#include <iostream>
#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>

//Define Address of Slave Address
#define ADDRESS 0x08

//Eliminate the Used of std in the future
using namespace std;

static const char *devName="/dev/i2c-1";

int main(int argc, char **argv)
{
    //Check to see if C++ works
    cout<<"Hello, World!\n";
    cout<<"I2C: Connecting"<<endl;
    int file;

    if ((file = open(devName, O_RDWR))<0)
    {
        fprintf(stderr, "I2C: Failed to access");
        exit(1);
    }

    if (ioctl(file, I2C_SLAVE, ADDRESS)<0)
    {
        cout<<"Failed to Access"<<endl;
    }
    char buf[0];
    char dd;
    for (int i=0; i<100;i++)
    {
        read(file,buf, 3);
        float distance= (int) buf[0];
        dd= buf[1];
        float dist=(int) buf[2];

        cout<<distance<<endl;
        usleep(10000);
        cout<<"doh"<<endl;
        cout<<dd<<endl;
        cout<<dist<<endl;
    }
    return 0;
}

我对C ++代码的期望如下

15
doh
Why No Work?
15

但是我明白了

15
doh
weird font can't be recognized
255

1 个答案:

答案 0 :(得分:2)

Wire.write(distance);

想将long写入I2C总线。对于Arduino,这是32位4字节的数据。我不确定wire.write到底是做什么的,因为我可以找到的文档在垃圾处理方面是不合标准的,但是the documentation似乎恰好会发送您要发送的4个字节中的1个。为了发送多个字节,您似乎需要使用数组版本:Wire.write(&distance, sizeof (distance));,但即使这样可能也不足够。我稍后再讲。

Wire.write("Why No Work?");

将一个以空值结尾的字符串(特别是const char[13])写入I2C总线。我对arduino不太了解,无法确定它是否还会发送终止null。

如此

Wire.write(distance);
Wire.write("Why No Work?");
Wire.write(distance);

需要将至少4 + 12 + 4个字节写入I2C总线。可能只写了1 + 12 +1。

在Pi方面,

read(file,buf, 3);

读出3个字节。这还不足以得到整个distance,更不用说字符数组和第二次写入distance了。您需要读取您写入的所有数据,至少20个字节。

此外

char buf[0];

定义一个长度为0的数组。您无能为力,因为这里没有空间存储任何东西。它不能容纳3个字符,更不用说20或21个字符了。 3个字节中的read被写入无效的内存和程序can no longer be counted on for sane results

这意味着充其量

    float distance= (int) buf[0];
    dd= buf[1];
    float dist=(int) buf[2];

distance的四个字节中仅得到一个字节,很遗憾,结果与预期的相同。 dd仅得到一个字符,而不是整个字符串,由于前面的错误之一,这被证明是胡说八道。 dist同样是垃圾。

要成功地将数据从一台计算机移动到另一台计算机,您需要建立通信协议。您不能只将long写到电线上。 long并非在所有平台上都具有相同的大小,也不总是具有same encoding。您必须绝对确定双方在long的写入方式(大小和字节顺序)和读取方式上都达成共识。

具体如何执行取决于您,但是here are some pointers和搜索词序列化可帮助您进行进一步的研究。