Я делаю небольшой проект для моей учебы.Это почти закончено, но я столкнулся с небольшой проблемой, и на самом деле я не знаю, что происходит.
Главное - это связь между Raspberry Pi и Arduino с использованием USB и pyserial.И это работало, по крайней мере, в течение 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
, но Raspberry Pi и теперь также в Windows 10, я получаюпустой байтовый ответ (b ''), в обоих случаях - при попытке прочитать с помощью serialRead()
или read_all()
функции
Вот как это выглядело: http://prntscr.com/mmaglv
итеперь просто остановимся.
Кроме того, я заметил, что когда Rpi посылает команду, то на Arduino светит только RX, ведомый для чтения, но никогда не светит 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 останавливается во время 3-й итерации (3-я строка выше) после 99:99
Снимок экрана с последовательного монитораhttps://prnt.sc/mqzyf5
Я немного запутался
Есть идеи?