Борьба при обработке данных из последовательного порта (Arduino) с помощью Python

Я пытаюсь переместить курсор с помощью джойстика, подключенного к Arduino Uno через скрипт Python, поскольку на этой плате нет библиотеки для перемещения мыши, как у Arduino Leonardo. Поэтому мне нужна помощь с проблемой, которую я представляю ниже. Вы можете увидеть, как работает код, и проблема заключается в комментариях к моему коду. Пожалуйста, я буду благодарен за решение.

import serial
import pyautogui
import time
#I import the libraries.
arduino_port = "/dev/ttyACM0" #Serial port for comunication(ubuntu).
baud=9600#frecuency

ser=serial.Serial(arduino_port, baud)# Connect to /dev/ttyACM0 at 9600 bauds
print("Connected to the arduino port at ", baud, "bauds") # Confirm connection

while True:#I'm using a while because I want it to run while the program is running, forever.
    data=ser.readline().decode('utf-8').rstrip() # Decode the data printed by arduino in the serial port.
    xyValues=data.split(",")# creates an array like this: ['x','y']
    final_xyValues=[]# declaration of a new array
    for i in xyValues:
        final_xyValues.append(int(i))
    #When the loop has finished, I have this array: [x, y], where x and y are integers.
    print(final_xyValues)
    #to check the problem uncomment the code below:
    """
    if len(final_xyValues)==2:
        pyautogui.moveRel(final_xyValues[0], final_xyValues[1])
        time.sleep(0.2)
    """

"""
Here is where I need help. I want to move the cursor with the values that
the program is constantly receiving and converting to an array called
final_xyValues. The array final_xyValues's first value is the x axis and the
second the y axis.

Take in count that the variable data is a string like this: '405,678', which is
transform to an array with two integers as values. Now, you must know that the values
of final_xyValues are from an analog input of a joystick connected to an Arduino Uno
and read in from the serial port. I want to move the cursor with the analog inputs of the
joystick.

ISSUE: when I uncomment the code from line 21 to 25 the first values of the joystick x and y
position in that moment are ok but after that the data continues identical to the first values
read. The values are correctly and constantly been updated if I comment this part of the code,
if I move the joystick the data changes.
"""

Вы можете увидеть проблему со значениями джойстика в последнем комментарии кода Python ниже. Где написано "ПРОБЛЕМА". Я искал решение несколько дней, и ничего не получалось.

#define VRX_PIN  A0 // Arduino pin connected to VRX pin
#define VRY_PIN  A1 // Arduino pin connected to VRY pin

void setup() {
  Serial.begin(9600) ;
}

void loop() {
  int xValue = analogRead(VRX_PIN);//Read the analog value of A0 pin, x axis.
  int yValue = analogRead(VRY_PIN);//Read the analog value of A1 pin, y axis.
  // read analog X and Y analog values
  Serial.print(xValue);
  Serial.print(",");
  Serial.println(yValue);
  //Result: 'x,y'
}

Код Arduino похож на интермедию в этом вопросе. Он и тег C++, вероятно, не нужны. Тем не менее, намного лучше, чем в последний раз, когда я видел этот вопрос.

user4581301 17.01.2023 00:23

Просто предполагаю: ПК считывает только пять значений в секунду (из-за спящего режима), но Arduino отправляет гораздо больше, поэтому они буферизуются, а старые обрабатываются ПК. Решения: Создайте поток на стороне ПК, который постоянно считывает значения и предоставляет основному потоку только самые последние значения после каждого сна. Или вы уменьшаете выход Arduino за счет сна на этой стороне.

Michael Butscher 17.01.2023 00:31

Примечание: каждый вопрос, который вы задаете в Stackoverflow, используется для определения того, когда вам разрешено задавать следующий вопрос, даже удаленный. Задавайте вопросы, которые хорошо принимаются сообществом, наберите 1 балл или выше, и вы сможете задавать их чаще. Имейте историю плохо полученных вопросов, наберите 0 или меньше баллов, и скорость замедляется, пока не достигнет 1 вопроса каждые 6 месяцев (также известный как запрет вопросов). Трудно выйти из бана, когда тебе редко разрешают задавать вопросы, поэтому не в твоих интересах удалять и заменять вопросы. Вместо этого исправьте их.

user4581301 17.01.2023 00:31

@user4581301 user4581301 Спасибо за ваш комментарий, я удалю тег C++. Когда вы говорите «намного лучше, чем в прошлый раз, когда я видел этот вопрос», не могли бы вы передать мне ссылку? Так что я могу увидеть возможное решение там.

whoAsked 17.01.2023 00:34

Незачем. Вы задали и быстро удалили другой вопрос около часа назад.

user4581301 17.01.2023 00:36

Хорошо, спасибо, теперь я буду осторожнее задавать вопросы. Хороший совет. Я все еще буду искать решение, оно будет полезно для моего текущего проекта.

whoAsked 17.01.2023 00:45

@MichaelButscher, вы рекомендуете мне удалить «time.sleep (0.2)». Я уже попробовал это, и все еще не работает должным образом. Эта задержка предназначена только для повышения удобочитаемости при просмотре результатов с терминала. Спасибо за ваш вклад.

whoAsked 17.01.2023 00:51

Ваш код Arduino настроен на отправку текущей позиции снова и снова. Если положение джойстика не изменилось, arduino будет продолжать повторно отправлять одни и те же значения. Чем это отличается от того, что вам нужно?

ScottC 17.01.2023 00:53

Также лучше иметь какую-то синхронизацию между ардуино и компьютером. В идеале, arduino отправляет сообщение, компьютер подтверждает его до того, как arduino будет разрешено отправить следующее сообщение (или после тайм-аута для безопасности).

ScottC 17.01.2023 00:55

@ScottC: я пробовал то, что вы сказали, все еще не работает. Хотя это полезно, потому что предоставляет ресурсы, если я попытаюсь переместить мышь с помощью программы python, она застрянет с неизменяющимися значениями.

whoAsked 17.01.2023 09:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
10
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

@michael-butscher написал хороший комментарий:

Просто предполагаю: ПК считывает только пять значений в секунду (из-за спящего режима), но Arduino отправляет гораздо больше, поэтому они буферизуются, а старые обрабатываются ПК. Решения: Создайте поток на стороне ПК, который постоянно считывает значения и предоставляет основному потоку только самые последние значения после каждого сна. Или вы уменьшаете выход Arduino за счет сна на этой стороне.

@michael-butscher освещает тот факт, что за одну короткую секунду у вас может быть сто строк 0,0 или 511,510, или в зависимости от того, что является аналоговым значением напряжения. Например.,

511,510
511,510
511,510
511,510
511,510
511,510
511,510
511,510
511,510
511,510
511,510
511,510
511,510
...

Это связано с тем, что Arduino очень быстро зацикливается и быстро заполнит ваш входной буфер pyserial одним и тем же значением.

С другой стороны, ваш цикл Python зацикливается очень медленно (по сравнению с Arduino). Таким образом, он будет тратить время на каждую строку, одну за другой, каждые 0,2 секунды. Так что он просто застрянет в начале вашего последовательного ввода, читая эти многочисленные повторяющиеся начальные значения.

Вам не нужно удалять задержку time.sleep(0.2). Я согласен, улучшенная читабельность, когда цикл Python замедляется до управляемой скорости, полезна.

На мой взгляд, простым решением на стороне Python является очистка буфера последовательного ввода, когда вы готовы прочитать новое измерение, сообщаемое Arduino.

Я рекомендую вам попробовать следующий бесконечный цикл while:

while True:

    # Clear entire serial input buffer
    ser.reset_input_buffer()

    # Read and ignore the next line.
    # This solves the issue that if you start reading now, you 
    # may be starting in the middle of a line. So we'll discard
    # this possibly incomplete line.
    ser.readline()

    data=ser.readline().decode('utf-8').rstrip()
    print(data)

    # 'data' is now guaranteed to be a most recent, complete
    # line of measurement data from the Arduino.

    time.sleep(0.2)

Вы должны заметить, что вывод теперь всегда показывает последние аналоговые измерения, о которых сообщает Arduino. Как только это будет подтверждено, вы можете выполнить синтаксический анализ строки необработанных данных, который вы делали ранее (приведение к int, проверка размера массива и т. д.).

Я прошу прощения за то, что не сделал хорошо то, что вы сказали, @michael-butscher. Спасибо.

whoAsked 17.01.2023 23:44

Спасибо и вам, @tedz2usa.

whoAsked 17.01.2023 23:45

Другие вопросы по теме