связь между Raspberry Pi и Arduino с помощью Pyserial - PullRequest
0 голосов
/ 17 февраля 2019

Я делаю небольшой проект для моей учебы.Это почти закончено, но я столкнулся с небольшой проблемой, и на самом деле я не знаю, что происходит.

Главное - это связь между 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

Я немного запутался
Есть идеи?

...