Python & Arduino. Просто, быстро и красиво
Очень часто, у начинающих и не только разработчиков возникают вопросы. Как управлять с Arduino с компьютера? А если компьютер — не Raspberry Pi, а обычный домашний компьютер? А если не хочется мучится с ESP8266 и управлять через веб интерфейс? Неужели надо каждый раз открывать Arduino IDE и отправлять команды через Монитор порта? Именно о том, как создать своё собственное приложение с графическим интерфейсом для управления Arduino я сейчас и расскажу.
Оборудование
Недавно я заполучил очень интересную плату: Arduino SS Micro. Эта плата, внешне напоминающая Digispark Attiny 85, тем не менее является китайской версией Arduino Micro, с выведенным выходом USB.
Подробно рассказывать о ней я не буду, ведь это уже сделал пользователь YouTube с ником iomoio, и его обзор можно посмотреть здесь.
Как мне кажется — это довольно крутое и удобное устройство для небольших домашних проектов, ведь у проводов есть супер-свойство: теряться в самый неподходящий момент.
В качестве управляющего компьютера был использован MacBook Pro с операционной системой macOS Mojave, но не надо закрывать статью, если вы используете Windows или Linux — всё описанное в статье будет работать без изменений на любой операционной системе.
Скетч для Arduino
В качестве примера будет использоваться скетч, включающий и выключающий светодиод, по команде из Serial-порта.
WARNING
Светодиод в Arduino SS Micro весит на порте SS, и поэтому он автоматически выключается. Не смотря на это, стандартный пример Blink — мигающий светодиод работает.
char inChar;
#define LED_PIN SS
void setup() {
pinMode(LED_PIN, OUTPUT); // Инициализация светодиода
Serial.begin(115200); // Инициализация Serial - порта
}
void loop() {
if (Serial.available() > 0)
{
inChar = Serial.read();
if (inChar=='e') // e - Enable - включить
{
digitalWrite(LED_PIN,HIGH);
}
}
else if (inChar=='d') // d - Disable - выключить
{
digitalWrite(LED_PIN,LOW);
}
else if (inChar=='b') // b - Blink - выключить режим мигания
{
while (true){
digitalWrite(LED_PIN,HIGH);
delay(1000);
digitalWrite(LED_PIN,LOW);
delay(1000);
}
}
}
Если вы будете использовать другую Arduino — не забудьте сменить пин светодиода.
Код для компьютера
Одним из достоинств Python, кроме его кроссплатформенности — наличие гигантского числа библиотек. Нам понадобятся:
- PySerial — библиотека для работы с Serial-портом
- PyQT5 — библиотека для создания графического интерфейса
Установка
Для установки, воспользуемся встроенным менеджером пакетов — pip.
pip install pyserial pyqt5
Для удобства создания GUI можно установить программу QTDesigner.
Интерфейс
Поскольку данная программа предназначена скорее, для демонстрации возможностей, пользователь может выбрать порт из предложенных, а так же скорость, с которой будет происходить общение.
Исходный код
Вся работа с устройством происходит благодаря библиотеке PySerial. Но есть несколько нюансов. Например, как узнать, в какой из портов подключено устройство?
На всем прекрасно известном сайте stackoverflow, пользователь с ником Thomas предложил уже готовое решение, которое я и использовал.
def serial_ports():
""" Lists serial port names
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result
Кроме этого необходимо хранить список доступных скоростей:
speeds = ['1200','2400', '4800', '9600', '19200', '38400', '57600', '115200']
А теперь соберём вместе дизайн(созданный в QtDesigner и сконвертированный с помощью утилиты pyuic5 в .py файл), функции для сканирования портов и основной код программы.
Основной класс, содержащий в себе всю логику программы
class LedApp(QtWidgets.QMainWindow, design.Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
self.Port.addItems(serial_ports())
self.Speed.addItems(speeds)
self.realport = None
self.ConnectButton.clicked.connect(self.connect)
self.EnableBtn.clicked.connect(self.send)
def connect(self):
try:
self.realport = serial.Serial(self.Port.currentText(),int(self.Speed.currentText()))
self.ConnectButton.setStyleSheet("background-color: green")
self.ConnectButton.setText('Подключено')
except Exception as e:
print(e)
def send(self):
if self.realport:
self.realport.write(b'b')
Переменные self.Port и self.Speed — это выпадающие списки, содержащие в себе значения доступных портов и скоростей.
При нажатии на кнопку self.ConnectButton вызывается функция connect, в которой производится попытка подключения к заданному порту с заданной скоростью. Если подключение успешно, то кнопка окрашивается в зелёный цвет, и меняется надпись.
Функция send отправляет в наш порт байтовую строку — заставляющую включить режим мигания.
Таким образом можно управлять различными устройствами, подключёнными к USB.
Данная статья является вводной и обзорной, более полную информацию можно найти например тут:
Полный исходный код, как скетча для Arduino, так и программы размещён на GitHub.