如何使用python和i2c从Rpi读取连接到arduino的pot



我正在尝试从连接到Arduino的电位计写入模拟读数,并在RPi上使用python的I2C读取这些值。 我已经让Arduino到Arduino使用以下代码工作。 我似乎无法正确做的是从Arduino写入两个字节,从RPi读取两个字节。

Arduino 主代码:

#include <Wire.h>
#define SLAVE_ADDRESS 0x2a
void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}
void loop()
{
  Wire.requestFrom(SLAVE_ADDRESS, 2);    // request 2 bytes from slave
  byte loByte;
  byte hiByte;
  if(Wire.available() >= 2)    // slave may send less than requested
    { 
    hiByte = Wire.read();
    loByte = Wire.read();
    }
  int val = (hiByte << 8) + loByte;
  Serial.print("read value:");   
  Serial.println(val);
  delay(500);
}

Arduino 从站代码:

#include <Wire.h>
#include <stdlib.h>
#define SLAVE_ADDRESS 0x2a
//#define potPin 0  
int readVal;
byte hi;
byte lo;

void setup()
{
// Communication I2C
  Wire.begin(SLAVE_ADDRESS);                
  Wire.onRequest(requestEvent); // register event
  Serial.begin(9600);
}
void loop()
{
readVal = analogRead(A2);
Serial.println(readVal);
hi = highByte(readVal);
lo = lowByte(readVal);
}
void requestEvent()
{
byte buf [2];
  buf [0] = hi;
  buf [1] = lo;
  Wire.write(buf, sizeof buf);  // send 2-byte response
}

我从 RPi 获得的最接近的读数是:

RPi 主代码:

import smbus
import time
bus = smbus.SMBus(1)
address = 0x2a
while True:
    bus.write_byte(address, 1)
    number = bus.read_byte(address)
    print(number)
    time.sleep(1)   

Arduino 从站代码:

#include <Wire.h>
#define SLAVE_ADDRESS 0x2a
int number = 0;
void setup() {
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
  }
void loop() {
  }
void receiveData(int byteCount){
  while(Wire.available()) { 
    number = Wire.read();
    number = analogRead(A2);
  }
}
void sendData(){
  Wire.write(number);
  }

我似乎能够得到 0-255,但在 255 之后,该值再次开始。 毫无疑问,有一种更精确的方式来说我只得到一个字节的数据或类似的东西。 最终,我希望将 2 个电位器连接到 Arduino 将读数输入 RPi。

在 Arduino 上,analogRead 返回 0-1023 范围内的int值。在此硬件上,int为两个字节。但是,在 sendData 函数中使用的Wire.write形式仅写入单个字节,丢弃整数的一部分。

基本上有两种解决方案。

最简单的方法是取 analogRead 的返回值,将其除以 4 并将其转换为一个字节。用Wire.write发送出去。这确实降低了电位计值的分辨率,但这是一个非常简单的解决方案吗?

另一种是通过线路发送整数值。由于您正在读取 RPi 上的字节,因此您无法知道您是在读取整数的第一个还是第二个字节。因此,您可能必须使用信号来指示双字节序列的开始。您还必须考虑两个平台的字节序。总而言之,这要复杂得多。

感谢您的反馈。 它帮助我更多地思考这个问题并做更多的挖掘。 这就是我的工作。

用于书写的Arduino面:

#include <Wire.h>
#define SLAVE_ADDRESS 0x2a
#define pot1pin A2
#define pot2pin A3
byte pot1byte;
byte pot2byte;
void setup()
{
    Wire.begin(SLAVE_ADDRESS);
    Wire.onRequest(requestEvent);
}
void loop() {
    int pot1int = analogRead(pot1pin);
    int pot2int = analogRead(pot2pin);
    pot1byte = map(pot1int, 0, 1024, 0, 255);
    pot2byte = map(pot2int, 0, 1024, 0, 255);
}
void requestEvent()
{
    Wire.write(pot1byte);
    delay(30);
    Wire.write(pot2byte);
}

RPi 侧阅读:

import smbus
bus = smbus.SMBus(1)
address = 0x2a
while (1):
    block = bus.read_i2c_block_data(address, 0, 2) # Returned value is a list of 2 bytes
    print(block)

如您所见,我正在读取 2 个电位器,将输出转换为 0-255,写入 I2C 总线,然后读取 RPi 侧的 2 个字节。 我确实必须在测试期间更改Arduino延迟值,因为我在几分钟后收到错误" IOError:[Errno 5]输入/输出错误"。 现在也许我会回去每个锅写 2 个字节并读取 4 个字节,这样我就不会丢失和分辨率。

最新更新