我正在为我的学习做一个小项目。已经快完成了,但是我遇到了一个小问题,实际上我不知道发生了什么。
最主要的是使用USB和pyserial在树莓派和arduino之间进行通信。那至少工作了1个月才停止。
我正在使用Raspberry Pi 3模型B(带有python 2.7 / 3.5)和arduino UNO板。 Arduino代码还通过Windows 10使用python 3.7进行了测试
Raspberry-python代码:
read_all来自https://stackoverflow.com/a/47614497/4946344,用于检查我的函数是否没有丢失
def read_all(port, chunk_size=200):
"""Read all characters on the serial port and return them."""
if not port.timeout:
raise TypeError('Port needs to have a timeout set!')
read_buffer = b''
while True:
# Read in chunks. Each chunk will wait as long as specified by
# timeout. Increase chunk_size to fail quicker
byte_chunk = port.read(size=chunk_size)
read_buffer += byte_chunk
if not len(byte_chunk) == chunk_size:
break
return read_buffer
def ArduinoConnection(portName):
global ser
try:
ser = Serial(
port = portName,
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout=2, # IMPORTANT, can be lower or higher
inter_byte_timeout=0.1 # Alternative
)
print("Successfully connected with Arduino board with speed of 9600 bounds")
return None
except:
print("Can not connect with Arduino board, please contact with the system administrator")
print("press a key to exit ...")
input()
return exit()
def serialRead():
global ser
return ser.read(ser.in_waiting).decode()
def serialWrite(command):
global ser
print("sended {0}".format(command))
ser.write(command.encode())
return None
while True:
lc = time.localtime()
sec = lc.tm_sec
if sec != prev_sec:
prev_sec = sec
print(str(lc.tm_hour) + ":" + str(lc.tm_min) + ":" + str(sec))
if sec == 50:
board_cfg = getCfg()
serialWrite(board_cfg)
elif sec == 0:
serialWrite("112:112")
time.sleep(2)
print(serialRead())
elif sec == 5:
serialWrite("11:11")
time.sleep(2)
setMeasures(serialRead())
我认为arduino方面是正确的。我在两个Arduino Uno板上检查了这一点。 当我直接在串行监视器中键入命令时,我会得到预期的输出,例如112:112命令,我应该得到类似的东西:
===== config #0 =====
@ sensor id -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0
===== config #1 =====
@ sensor id -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0
===== config #2 =====
@ sensor id -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0
===== config #3 =====
@ sensor id -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0
但是在树莓派以及现在的Windows 10上,在两种情况下-当尝试使用serialRead()
或read_all()
函数进行读取时,我都得到了一个空字节响应(b'')>
那是什么样子:http://prntscr.com/mmaglv
现在停下来。
我还观察到,当Rpi发送命令时,在Arduino上,只有RX led发光以进行读取,而从没发出TX二极管进行响应。
但是正如我所说的,它可以在arduino IDE的串行监视器上直接工作,并且两个二极管都发光。 (屏幕截图:http://prntscr.com/mmajih)
我有点困惑。
任何提示可能有什么问题吗?
NEW EDIT 27.02:
我发现通讯错误。
问题是缓冲区的大小为600个字符,并且Serial.readBytes()
函数阻塞了Arduino线程(我不知道为什么直接在串行监视器上可以正常工作)。我使用Serial.readBytes()
而不是Serial.readBytesUntil()
。
关于arduino的最后一个奇怪的问题
Arduino sread()
函数
void sread (){
int cfgnr = -1;
int INPUT_SIZE = 600;
char input[INPUT_SIZE + 1];
byte size = Serial.readBytesUntil('>', input, INPUT_SIZE);
input[size] = 0;
bool writeConfig = false;
String a = String(input);
if (a != "")
log(a);
char* command = strtok(input, "&");
while (command != 0)
{
char* separator = strchr(command, ':');
if (separator != 0)
{
*separator = 0;
int a = atoi(command);
++separator;
int b = atoi(separator);
if(writeConfig){
_config[cfgnr][a] = b;
}
if(a == 99 && b == 99){
writeConfig = true;
cfgnr++;
}
else if(a == 11 && b == 11){
writeConfig = false;
log(responseMeasures());
}
else if(a == 112 && b == 112){
typeConfig();
}
}
command = strtok(0, "&");
}
}
void log(String s){
Serial.println(s);
}
我正在使用strtok()
和strchr()
拆分字符串以读取并设置配置
这是一个示例字符串(为了更好的可读性,我将其分成几行)
99:99&0:2&1:2&2:1&3:4&4:6000&
99:99&0:1&1:2&2:1&3:3&4:4000&
99:99&0:5&1:2&2:1&3:1&4:5000&
99:99&0:6&1:2&2:1&3:2&4:5000
while循环在99:99
之后的第三次迭代(上面的第三行)期间停止
来自串行监视器https://prnt.sc/mqzyf5的屏幕截图
我有点困惑
有什么想法吗?