简体   繁体   中英

I want to receive multiple data from arduino to raspberry pi using I2C

Thank you to whoever is kind enough to look into this question.

I want to receive multiple data from arduino to raspberry pi using I2C.

I can obtain 1 data from arduino, but once I move to more than one data, it fails to do so.

I have tried multiple methods so far, and I found this method to work the best to obtain data from Arduino.

My previous attempt in obtaining data from arduino is as follows: I want to read from Arduino using I2C using Raspberry Pi Raspberry Pi's terminal response has weird font that cannot be recognized

Which are all solved by now. Got Massive Help from link below https://area-51.blog/2014/02/15/connecting-an-arduino-to-a-raspberry-pi-using-i2c/

Arduino Code

#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++ Code

//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;
}

What I would expect from the c++ code would be as follows

15
doh
Why No Work?
15

But I get

15
doh
weird font can't be recognized
255
Wire.write(distance);

wants to write a long onto the I2C bus. For an Arduino This is 32 bits, 4 bytes, of data. I'm not sure exactly what wire.write does because the documentation I can find is substandard to the point of being garbage, but the documentation looks like it's going to send exactly 1 of the 4 bytes you wanted to send. In order to send more than one byte, it looks like you need to use the array version: Wire.write(&distance, sizeof (distance)); , but even this may not be sufficient. I'll get back into that later.

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

writes a null-terminated string (specifically a const char[13] ) onto the I2C bus. I don't know arduino well enough to know if this also sends the terminating null.

so

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

needed to write at least 4 + 12 + 4 bytes onto the I2C bus. and probably only wrote 1 + 12 + 1.

On the Pi side,

read(file,buf, 3);

read out 3 bytes. This isn't enough to get the whole of distance , let alone the array of characters and second write of distance . You need to read all of the data you wrote, at least 20 bytes.

In addition,

char buf[0];

defines an array of 0 length. There isn't much you can do with it as there is no space to store anything here. It cannot hold 3 characters, let alone the 20 or 21 necessary. read of 3 bytes wrote into invalid memory and the program can no longer be counted on for sane results .

This means that at best

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

got only one byte of the four bytes of distance and it's dumb luck that the result was the same as expected. dd got exactly one character, not the whole string, and this is turning out to be nonsense because of one of the preceding mistakes. dist is similarly garbage.

To successfully move data from one machine to another, you need to establish a communication protocol. You can't just write a long onto a wire. long doesn't have the same size on all platforms, nor does it always have the same encoding . You have to make absolutely certain that both sides agree on how the long is to be written (size and byte order) and read.

Exactly how you are going to do this is up to you, but here are some pointers and a search term, serialization , to assist you in further research.

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