我正在尝试从连接到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 个字节,这样我就不会丢失和分辨率。