Передача данных в Arduino и с него на Raspberry Pi

Я пытаюсь передать данные акселерометра MPU6050 + данные с 3 потенциометров с Arduino на Raspberry Pi. Я выполняю постобработку здесь (на Raspberry Pi), а затем передаю данные обратно в Arduino для перемещения исполнительных механизмов. Однако моя проблема заключается в том, что когда я пытаюсь записать обработанные данные обратно в Arduino, я вижу, что даже поток входящих данных из Arduino начинает повреждаться, и все становится очень медленным. Даже если я просто считываю последовательные данные с Arduino, все происходит медленнее, чем если бы я выполнял обработку непосредственно на Arduino. Кроме того, данные акселерометра, похоже, перестают отвечать на запросы, т.Е. Их значение не меняется, если я перемещаю акселерометр. Все просто работает нормально, если вся обработка выполняется на Arduino. Я не знаю, что происходит не так. Ниже приведены мои функции / коды Arduino и Python.

Код Arduino:

void send_rec_data(){

    Serial.print(Kp);
    Serial.print(",");
    Serial.print(Kd);
    Serial.print(",");
    Serial.print(Ki);
    Serial.print(",");
    Serial.println(Theta_x);

    delay(20);    

  if (Serial.available()>0){ // Считывать данные, отправленные Raspberry Pi / Piserial

    str_data = Serial.readString();    

    int firstCommaIndex = str_data.indexOf(',');

    cmd = str_data.substring(0, firstCommaIndex); // Здесь хранится масштабированный вывод из Raspberry Pi

    param1 = str_data.substring(firstCommaIndex+1); // Здесь сохраняется ошибка от Raspberry Pi для определения направления вращения двигателя

    Output = cmd.toFloat(); my_error = param1.toFloat(); // Измените выходные данные со string на float

    blink_led(); // Мигающие светодиоды, если данные получены от Raspberry Pi



  }

}

Код на Python:

while 1:

    data = cont.get_serial_data(arduino)

    time.sleep(0.02)

    if data is not None:

        Kp, Kd, Ki, Theta_x = data

        print(" \n Arduino sent Kp = ", Kp , "Kd = ",Kd , "Ki = ", Ki, "Theta_x = ", Theta_x)

        cont.set_tunings(Kp, Kd, 0)

        Output_scaled = cont.Compute_PID_Output(Input = Theta_x) # Compute the output of PID Algorithm

        ff = str(Output_scaled)+','+str(cont.error)

        arduino.write(ff.encode())

        print("\n Computed data sent TO ARDUINO Output_scaled = ", Output_scaled, "Error = ", cont.error)

arduino.close()

Я потратил некоторое время на то, чтобы решить проблему, отключив задержки и очистив буфер, но пока ничего не получалось. Может кто-нибудь, пожалуйста, помочь.

Спасибо.

, 👍0

Обсуждение

Вам следует начать с серьезного обдумывания необходимых вам сроков общения: Сколько байтов вы хотите отправить в каждом направлении? С какой скоростью передачи данных? Как часто? Затем прочитайте [Моргайте без промедления] (https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay ), просто чтобы узнать, как писать неблокирующий код, затем [Чтение серийного номера на Arduino] (https://hackingmajenkoblog.wordpress.com/2016/02/01/reading-serial-on-the-arduino /)., @Edgar Bonet


2 ответа


Лучший ответ:

0

Спасибо вам всем. Я прочитал этот форум, и там также говорится о тех же вещах, которые вы, ребята, также предложили. Я сделал то же самое, и теперь все происходит быстро.

Serial.readString()

это действительно проблема.

,

1

Хорошо, не переписывая весь ваш код, одна вещь, которую я вижу здесь, - это множество строковых функций sloooow.

Например, функция печати Pythons работает чрезвычайно медленно. Вы должны вставить несколько таймеров в свой код и посмотреть, сколько времени все это займет. Я думаю, вы будете удивлены.

Для приложения реального времени, которое, похоже, таковым и является, вам нужно быть очень осторожным и использовать тайм-ауты и неблокирующий код, чтобы убедиться, что все неожиданно не остановится.

Вам действительно нужно переписать весь этот код заново, но я укажу на несколько конкретных проблем.

delay(20); 
if (Serial.available()>0){
   ...
}

Это неаккуратно. Если ваш код python не обрабатывает и не возвращает данные до истечения 20 мс, все будет синхронизировано.

str_data = Serial.readString();

Взгляд на документацию показывает, что это будет возвращаться только по тайм-ауту, так что это гарантированно блокируется на 1 секунду (я думаю, это значение по умолчанию), так что есть еще одна проблема с остановкой показа. Смотрите Этот вопрос для получения дополнительной информации.

cmd = str_data.substring(0, firstCommaIndex);

Этого тоже недостаточно. Между pi и arduino нет синхронизации, поэтому у вас нет гарантии, что вы не получите половину предыдущей передачи, прикрепленной к передней части строки данных (или хуже). Вам нужно создать свой собственный буфер и выполнить синтаксический анализ для обработки данных. Или сделайте тщательную очистку буфера и используйте щедрые тайм-ауты.

Итак, TLDR; вот что вы хотите сделать (предполагая, что вы хотите заблокировать, пока происходит этот обмен)

  1. Очистите буфер приема arduino.
  2. Отправьте пакет данных с arduino.
  3. Начните получать. Добавьте полученные байты в буфер символов.
  4. Постоянно выполняйте поиск в этом буфере для вашего полного пакета данных.
  5. Тайм-аут после x мс. Как-то справьтесь с отсутствием возвращенных данных.
  6. Если вы все-таки найдете полный пакет данных, то обработайте его.

О Пи:

  1. Опрос для получения последовательных данных. Добавьте его в буфер по мере поступления.
  2. Начните удалять самые старые символы из буфера, если он длиннее в 2 раза самого длинного пакета данных
  3. Непрерывно выполняйте поиск в буфере вашего пакета данных. Если вы найдете его, то продолжайте ниже.
  4. удалите пакет данных из буфера приема.
  5. обработайте данные.
  6. Отправьте обратный пакет данных в arduino.
,