[英]How to read pot connected to arduino from Rpi using python and i2c
I'm trying to write analog readings from a potentiometer connected to an Arduino and read those values using I2C from python on an RPi. 我正在尝试从连接到Arduino的电位计中写入模拟读数,并使用RPi上的python使用I2C读取这些值。 I have gotten Arduino to Arduino to work using the code below.
我已经将Arduino转到Arduino,以使用下面的代码工作。 What I cannot seem to do correctly is write two bytes from the Arduino and read two bytes from the RPi.
我似乎无法正确执行的操作是从Arduino写入两个字节,并从RPi读取两个字节。
Arduino Master code: 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 Slave code: 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
}
The closest I have gotten reading from an RPi is: 我从RPi读取的最接近的是:
RPi Master code: 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 slave code: 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);
}
I seem to be able to get 0-255, but after 255 the value starts again. 我似乎能够获得0-255,但在255之后,该值再次开始。 No doubt there is a more precise way to say I am only getting one byte of data or something along those lines.
毫无疑问,有一种更精确的方法可以说我仅沿这些行获取一个字节的数据或其他内容。 Ultimately I want to have 2 pots connected to the Arduino feeding readings into the RPi.
最终,我想将2个电位器连接到Arduino,将读数馈送到RPi。
On Arduino, analogRead
returns an int
value in the range 0-1023. 在Arduino上,
analogRead
返回的int
值在0-1023范围内。 On this hardware, an int
is two bytes. 在此硬件上,一个
int
是两个字节。 However, the form of Wire.write
that you use in the sendData
function only writes a single byte, discarding part of the integer. 然而,形式
Wire.write
您在使用sendData
功能只写一个字节,丢弃的整数部分。
There are basically two solutions. 基本上有两种解决方案。
The simplest would be to take the return value of analogRead
, divide it by 4 and cast it into a byte. 最简单的方法是取
analogRead
的返回值,将其除以4,然后将其转换为一个字节。 Send that out with Wire.write
. 使用
Wire.write
发送出去。 This does reduce the resolution of the value of the pot-meter, but is it a very simple solution. 这确实降低了电位计值的分辨率,但这是一个非常简单的解决方案。
The other was is to send an integer value over the wire. 另一个是通过电线发送一个整数值。 Since you're reading bytes on the RPi, you cannot know if you are reading the first or second byte of an integer.
由于您正在读取RPi上的字节,因此您不知道要读取整数的第一个还是第二个字节。 So you would probably have to use a signal to indicate the start of a two-byte sequence.
因此,您可能必须使用信号来指示两个字节序列的开始。 You would also have to take the endian-ness of both platform into account.
您还必须考虑两个平台的字节序。 All in all, this is much more complicated.
总而言之,这要复杂得多。
Thanks for the feedback. 感谢您的反馈。 It helped me think through this a bit more and do more digging.
它帮助我进行了更多思考,并进行了更多挖掘。 This is what I have working.
这就是我的工作。
Arduino side for writing: 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 side for reading: 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)
As you can see I am reading 2 pots, converting the output to 0-255, writing to the I2C bus and then reading the 2 bytes on the RPi side. 如您所见,我正在读取2个电位器,将输出转换为0-255,写入I2C总线,然后在RPi侧读取2个字节。 I did have to change the Arduino delay value during testing because I was getting the error "IOError: [Errno 5] Input/output error" after a few minutes.
我确实必须在测试期间更改Arduino延迟值,因为几分钟后出现错误“ IOError:[Errno 5]输入/输出错误”。 Now maybe I will go back and write 2 bytes per pot and read 4 bytes so I don't lose and resolution.
现在也许我会回去为每个锅写入2个字节并读取4个字节,这样我就不会丢失和解析。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.