#python #arduino #pycharm #serial-port #pyserial
Вопрос:
Прежде чем я расскажу о том, что происходит, о проблеме и о шагах, которые я предпринял для ее устранения, вот краткое описание оборудования, которое я использую для своего проекта
Оборудование, которое я использую:
Инфракрасный кодер: https://www.amazon.ca/dp/B07B3PLZZ2/ref=cm_sw_r_oth_api_glt_i_NCFT5KHJBARTBC76XG7Y?_encoding=UTF8amp;psc=1
Адаптер питания Arduino Mega 2560 Вт/ 9 В 1A: https://www.amazon.ca/gp/product/B01H4ZDYCE/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8amp;psc=1
Компьютер: Macbook Pro 2020, чип M1, 8 ГБ оперативной памяти
IDE: Издание сообщества Pycahrm
Интерпретатор Python: Python 3.8
Фон:
У меня есть вентилятор, который вращается с постоянной скоростью. Перехват лопастей вентилятора-это мой инфракрасный кодер, подключенный к моему Arduino. когда лопасти вращаются через инфракрасный кодер, сценарий Arduino, который я написал, должен печатать «1», если датчик срабатывает, и «0», если это не так.
Это прекрасно работает.
Теперь я хочу иметь возможность использовать эти данные » 1 » и » 0 » в Python, потому что у меня есть идея для видеоигры, которую я хочу создать прототипом с помощью Pygame.
На Pycharm я установил pyserial, чтобы иметь доступ ко всем данным. Чтобы зафиксировать 1 и 0 в Pycharm, вот код, который я написал:
Переменные
serialInst = serial.Serial()
serialInst.port = '/dev/cu.usbmodem11301'
serialInst.baudrate = 9600
serialInst.timeout = 0.5
serialInst.open()
Функция Считывания Данных
def readData(self):
if serialInst.inWaiting():
packet = serialInst.readline()
if int(packet.decode('utf').rstrip('n')) == 1:
print('1')
elif int(packet.decode('utf').rstrip('n')) == 0:
print('0')
Способ, которым это работает, довольно прост. Как я описывал ранее, если вентилятор запускает датчик, Arduino выводит «1», а затем Python считывает данные и подтверждает их с помощью оператора if.
Та же операция выполняется, когда датчик не срабатывает.
The Problem
This function is the first function called in the main while loop of my python code. There are other functions that are called afterward before it loops around to the readData function however when those functions are called, it’s almost as if the Arduino data stops checking to see if there have been any changes.
What the problem looks like
No matter if the fan’s blades go through the sensor, the output is always 0
If I comment out any function that’s used in the main while loop, everything works 100% fine. The issue only happens when I start to introduce other functions into the main while loop.
What I’ve tried
I currently have 9 other tabs open with similar Pyserial issues people have reported here on StackOverflow and here are some of the things I’ve read about and tried:
- Adding a serialInst.timeout value. I played with a variety of numbers from 0.01 to 0.5 and haven’t found success
- Использование serialInst.reset_output_buffer(), serialInst.flushOutput(), serialInst.reset_input_buffer () или serialInst.flushInput() в различных местах
- И я перепробовал еще много потенциальных решений, однако это было тогда, когда моя проблема была еще хуже… Раньше у меня была функция ReadData как часть класса в другом, однако каждый раз, когда я пытался запустить ее из основного цикла while, она пропускала данные, не выдавала никаких данных, показывала очень странные символы… это был просто кошмар.
Теперь у меня есть функция ReadData в основном игровом классе, и мне просто нужно решить эту последнюю проблему, и все будет работать.
Краткие сведения
У меня есть функция python под названием ReadData, которая считывает данные, поступающие с Arduino, которые имеют значение » 1 » или «0». Когда ReadData является единственной функцией, вызываемой в основном цикле while моей программы, все работает нормально; есть «1», когда должно быть, и «0», когда должно быть.
Проблема возникает, когда я раскомментирую другие функции в цикле while, которые я должен использовать.
Программа определенно проходит весь цикл while, однако, когда она достигает функции ReadData, она «застревает» при чтении только «0»… даже когда должно быть «1».
Что мне нужно
Функция ReadData, если операторы должны правильно выводить » 1 » или «0», независимо от того, закомментированы ли другие функции в основном цикле while или нет.
Мне нужно «разморозить» все, что задерживает эту часть программы.
Пожалуйста, дайте мне знать, если вам понадобится дополнительная информация. Я действительно ценю ваше время.
Обновить
Кажется, что когда вызываются другие функции, все работает нормально, однако, когда я могу pygame.display.update (), именно тогда данные arduino начинают «зависать».
Я не уверен, почему обновление экрана для моей игры приведет к тому, что программа перестанет работать…
Я также добавил Serial.flush() в код Arduino… если это поможет…
Комментарии:
1. Разделяй и властвуй — как насчет написания пары простых тестовых программ? На мгновение забудьте об игре, которую вы пытаетесь написать; просто сосредоточьтесь на ЭТОЙ проблеме. Вы говорите, что можете заставить его работать с основным циклом, в котором больше ничего нет. Хорошо, покажите нам эту полную программу. Теперь вы говорите, что если вы добавите другие функции в цикл, это не сработает. Добавьте какую-нибудь глупую маленькую функцию, чтобы сделать временную задержку, или напечатать время суток, или что-то в этом роде. Если ваша функция чтения фанатов перестает работать, покажите нам эту программу. В противном случае продолжайте добавлять функции, пока они не сломаются. Тогда покажи нам это.
Ответ №1:
Исправлена проблема
Я ошибался, думая, что проблема была в других функциях, которые я вызывал в цикле while.
Оказывается, когда я раскомментировал другие функции, мой код работал так, как ожидалось:
Было 1, когда вентилятор активировал датчик, и 0, когда датчик не работал.
Так в чем же именно заключалась проблема?
Это было несколько вещей:
1. pygame.отображение.обновление()
Когда я раскомментировал pygame.display.update(), это произошло, когда моя функция realData () (функция, которая должна выводить 1 и 0)»зависала».
Это выглядело так:
0
0
0
0
0
0
0
Он никогда не набирал «1», даже если вентилятор явно попадал в датчик.
О причине этого я до сих пор понятия не имею… но я нашел способ обойти это.
Чтобы исправить это, я добавил следующее:
serialInst.reset_input_buffer()
до конца функции realData ().
После этого я столкнулся с новой проблемой:
Данные выводили 1, 0 и кучу пробелов, которые мне не нужны. Это выглядело бы так:
1
0
0
0
0
0
0
0
1
0
1
Мне не нужны были эти пробелы, потому что моя функция realData() была запрограммирована с определенными операторами if, которые выполняли бы определенные задачи, если бы было 1 ИЛИ 0… не новая строка/пробел.
Причина, по которой это произошло, заключалась в Arduino.
Вот код на стороне Arduino, который вызвал проблему:
void loop() {
// read the state of the pushbutton value:
x = digitalRead(sensor);
// check if the fan hit the sensor. If it is, the sensor is HIGH:
if (sensor == HIGH) {
Serial.print(1);
} else {
Serial.print(0);
}
}
Проблема была в том, что я использовал:
Serial.println(1)
// and
Serial.println(0)
Это сообщило бы Pycharm, что я хотел отправить 1, 0 и новые строки. Поэтому я изменил этот код на:
Serial.print(1)
// and
Serial.print(0)
Это исключило возможность получения Pycharm случайных новых строк
После этого на стороне Pycharm все еще оставались две последние проблемы, которые было легко исправить:
Вместо того, чтобы записывать данные в Pycharm с помощью:
packet = serialInst.readline()
Я использовал:
packet = serialInst.read()
Заключительная часть состояла в том, чтобы просто декодировать сообщение, потому что оно выводило бы такие вещи, как:
b'0'
b'0'
b'0'
b'1'
b'0'
b'0'
Поэтому я просто использовал:
x = int(packet.decode('utf'))
Конечный продукт выглядел так:
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
И т.д…
Теперь я могу использовать операторы if для дальнейшего развития своей игры в зависимости от того, находится ли «1» в выводе или «0».
Теперь все идеально. Я искренне надеюсь, что это поможет всем, кто испытывает те же проблемы, что и я.