У меня Raspberry Pi 3, модель B, подключенная к Arduino Mega 2560 через I2C с использованием сдвига уровня из-за различных напряжений GPIO.
Raspberry Pi --- 3.3V --- Shifter уровня -- 5V --- Arduino Mega
В моем коде Arduino считывает аналоговое значение потенциометра и отправляет его Raspberry Pi в 2 байта (максимальное значение = 1023).Raspberry Pi получает 2 байта и объединяет их в 16 бит и делит значение на 4, чтобы получить максимальное значение 255.
Raspberry Pi отправляет это значение обратно в Arduino, который устанавливаетЗначение ШИМ светодиода для его затемнения.
Код работает нормально, но только если у меня задержка 2 секунды на главном цикле Raspberry Pi.Пока я его удаляю, код работает всего 1-2 секунды, прежде чем замораживает шину I2C.Если я запускаю i2cdetect на терминале после того, как I2C перестает работать, я не могу больше видеть его адрес, пока не удалю Соединения I2C и не соберу его заново, прежде чем снова запустить Программу.
Наименьшее значение для сна, в котором работает кодбез потери I2C Соединение ist 5 мс.
Мастер-код (RPi):
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
using namespace std;
int file_i2c;
int length_rcv = 30;
int length_snd = 9;
unsigned char buffer_rcv[30] = {0};
unsigned char buffer_snd[9] = {0};
uint8_t addr = 0x06;
using namespace std;
uint16_t ang;
int main(void)
{
char *filename = (char*)"/dev/i2c-1";
if((file_i2c = open(filename, O_RDWR))< 0 ){
cout << "Failed to open the i2c bus" << endl;
return 0;
}
while(1){
//Acquires buss access
if (ioctl(file_i2c, I2C_SLAVE, addr) < 0){
cout << "Failed to acquire bus access and/or talk to slave" << endl;
}
//Reads buffer
if (read(file_i2c, buffer_rcv, length_rcv) != length_rcv){
cout <<"Failed to read from the i2c bus" << endl;
} else {
cout << "Data read:" << buffer_rcv[0] << endl;
}
//Combine Bytes in 16 Bits and divide by 4
ang = ((uint16_t)buffer_rcv[0] << 8 | (uint16_t)msg_rcv[1];
ang = ang/4;
cout << ang << endl;
buffer_snd[0] = ang;
//Writes buffer
if (write(file_i2c, buffer_snd, length_snd) != length_snd){
cout << "Failed to write to the i2c bus " << endl;
}
}
usleep(50000);
return 0;
}
Slave Code (Arduino):
#include <Wire.h>
//Input Pins
int angPin = 8;
//Output Pins
int pwmVLPin = 10;
//Input Values
volatile int ang;
//Byte Values
volatile byte ang_H, ang_L;
//Output Values
volatile byte pwmVL;
//Buffer for receiving I2C
volatile byte msg_rcv[9];
//Counter
volatile int i = 0;
void setup() {
//I2C
Wire.begin(6);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
//Serial.begin(9600);
//Input Pins
pinMode(angPin, INPUT);
//Output Pins
pinMode(pwmVLPin, OUTPUT);
}
void loop() {
//Read Inputs
ang = analogRead(angPin);
//Write Outputs
analogWrite(pwmVLPin, pwmVL);
}
void receiveData(int HowMany) {
//Read bytes
while (1 <= Wire.available()) {
byte c = Wire.read();
msg_rcv[i] = c;
i++;
}
//Assings each byte of the incoming message to each output variable
pwmVL = msg_rcv[0];
//Serial.println(pwmVL);
i = 0;
}
void sendData() {
//Split the values in bytes
ang_H = (ang >> 8) & 0xFF;
ang_L = ang & 0xFF;
//Serial.println(ang);
//Save Inputs into the message
byte msg_snd[30] = {ang_H, ang_L, ...};
//Send the message
Wire.write(msg_snd,30);
}
Кто-нибудь знает, как это исправить?Он должен иметь возможность общаться без большой задержки в main ().
PS: отправляемое сообщение обычно больше (30 байт), но я удалил те, которые не важны.
поздравил.