我试图从连接到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之后,该值再次开始。毫无疑问,有一种更精确的方式可以说我只获得一个字节的数据或类似的东西。最后,我希望将两个连接到Arduino的读数连接到RPi中。
答案 0 :(得分:1)
在Arduino上,analogRead
返回0-1023范围内的int
值。在此硬件上,int
是两个字节。
但是,您在Wire.write
函数中使用的sendData
形式只会写入单个字节,从而丢弃整数的一部分。
基本上有两种解决方案。
最简单的方法是取analogRead
的返回值,除以4并将其转换为一个字节。使用Wire.write
发送出去。这确实降低了电位计的值的分辨率,但这是一个非常简单的解决方案。
另一个是通过线路发送整数值。由于您正在读取RPi上的字节,因此您无法知道是否正在读取整数的第一个或第二个字节。所以你可能不得不使用一个信号来指示一个双字节序列的开始。您还必须考虑两个平台的endian-ness。总而言之,这要复杂得多。
答案 1 :(得分:0)
感谢您的反馈。它帮助我思考了这一点,并做了更多的挖掘。这就是我的工作。
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延迟值,因为我收到了错误&#34; IOError:[Errno 5]输入/输出错误&#34;几分钟后。现在也许我会回去为每个锅写2个字节并读取4个字节,这样我就不会失去和解决。