Я пытаюсь переместить курсор с помощью джойстика, подключенного к 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 отправляет гораздо больше, поэтому они буферизуются, а старые обрабатываются ПК. Решения: Создайте поток на стороне ПК, который постоянно считывает значения и предоставляет основному потоку только самые последние значения после каждого сна. Или вы уменьшаете выход Arduino за счет сна на этой стороне.
Примечание: каждый вопрос, который вы задаете в Stackoverflow, используется для определения того, когда вам разрешено задавать следующий вопрос, даже удаленный. Задавайте вопросы, которые хорошо принимаются сообществом, наберите 1 балл или выше, и вы сможете задавать их чаще. Имейте историю плохо полученных вопросов, наберите 0 или меньше баллов, и скорость замедляется, пока не достигнет 1 вопроса каждые 6 месяцев (также известный как запрет вопросов). Трудно выйти из бана, когда тебе редко разрешают задавать вопросы, поэтому не в твоих интересах удалять и заменять вопросы. Вместо этого исправьте их.
@user4581301 user4581301 Спасибо за ваш комментарий, я удалю тег C++. Когда вы говорите «намного лучше, чем в прошлый раз, когда я видел этот вопрос», не могли бы вы передать мне ссылку? Так что я могу увидеть возможное решение там.
Незачем. Вы задали и быстро удалили другой вопрос около часа назад.
Хорошо, спасибо, теперь я буду осторожнее задавать вопросы. Хороший совет. Я все еще буду искать решение, оно будет полезно для моего текущего проекта.
@MichaelButscher, вы рекомендуете мне удалить «time.sleep (0.2)». Я уже попробовал это, и все еще не работает должным образом. Эта задержка предназначена только для повышения удобочитаемости при просмотре результатов с терминала. Спасибо за ваш вклад.
Ваш код Arduino настроен на отправку текущей позиции снова и снова. Если положение джойстика не изменилось, arduino будет продолжать повторно отправлять одни и те же значения. Чем это отличается от того, что вам нужно?
Также лучше иметь какую-то синхронизацию между ардуино и компьютером. В идеале, arduino отправляет сообщение, компьютер подтверждает его до того, как arduino будет разрешено отправить следующее сообщение (или после тайм-аута для безопасности).
@ScottC: я пробовал то, что вы сказали, все еще не работает. Хотя это полезно, потому что предоставляет ресурсы, если я попытаюсь переместить мышь с помощью программы python, она застрянет с неизменяющимися значениями.
@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. Спасибо.
Спасибо и вам, @tedz2usa.
Код Arduino похож на интермедию в этом вопросе. Он и тег C++, вероятно, не нужны. Тем не менее, намного лучше, чем в последний раз, когда я видел этот вопрос.