Я хочу получить несколько данных из Arduino Raspberry Pi с помощью I2C - PullRequest
1 голос
/ 07 октября 2019

Спасибо всем, кто достаточно любезен, чтобы разобраться с этим вопросом.

Я хочу получить несколько данных от Arduino до Raspberry Pi с помощью I2C.

Я могу получить 1 данные из Arduino,но как только я перехожу к нескольким данным, это не удается сделать.

До сих пор я пробовал несколько методов, и я нашел, что этот метод работает лучше всего для получения данных из Arduino.

Моя предыдущая попытка получить данные из arduino была следующей: Я хочу читать из Arduino, используя I2C, используя Raspberry Pi Ответ терминала Raspberry Pi имеет странный шрифт, который не может быть распознан

Которые все уже решены. Получил массивную справку по ссылке ниже https://area -51.blog / 2014/02/15 / соединение-ардуино с малиной-пи-использованием-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 Ответ

2 голосов
/ 07 октября 2019
Wire.write(distance);

хочет записать long на шину I2C. Для Arduino Это 32 бита, 4 байта данных. Я не совсем уверен, что именно делает wire.write, потому что документация, которую я могу найти, не соответствует стандартам и может быть мусором, но документация выглядит так, как будто она отправит ровно 1 из 4 байтов, которые вы хотелиОтправить. Для отправки более одного байта похоже, что вам нужно использовать версию массива: Wire.write(&distance, sizeof (distance));, но даже этого может быть недостаточно. Я вернусь к этому позже.

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

записывает строку с нулевым символом в конце (в частности, const char[13]) на шину I2C. Я недостаточно хорошо знаю arduino, чтобы знать, посылает ли это также завершающий ноль.

, поэтому

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, необходимых. read из 3 байтов, записанных в недопустимую память, и программа больше не может рассчитывать на нормальные результаты .

Это означает, что в лучшем случае

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

получил только один байт из четырех байтов distance, и это глупое счастье, что результат оказался таким же, как ожидалось. dd получил ровно один символ, а не всю строку, и это оказывается чепухой из-за одной из предыдущих ошибок. dist аналогично фигня.

Чтобы успешно переместить данные с одного компьютера на другой, вам необходимо установить протокол связи. Вы не можете просто написать long на провод. long не имеет одинакового размера на всех платформах и не всегда имеет одинаковую кодировку . Вы должны быть абсолютно уверены, что обе стороны согласны с тем, как записать long (размер и порядок байтов) и прочитать.

Как именно вы собираетесь это сделать, решать только вам, но вот несколько указателей и поисковый термин serialization , чтобы помочь вам в дальнейших исследованиях.

...