- Заметки о Linux, электронике, радиолюбительстве
- воскресенье, 27 июля 2014 г.
- Работа с последовательным портом из консоли Linux
- Собираем плату
- Создаем приложение
- Собираем форму
- Добавляем обработчик нажатия на кнопку
- Выводим значение из txtPort
- Посылаем сообщение arduino
- Пробуем зажечь светодиод
- Правим красную кнопку
- Читаем значения датчика освещённости
- Обновляем значения датчика освещённости в режиме реального времени
- БОНУС
Заметки о Linux, электронике, радиолюбительстве
Личный блог Вадима Кузнецова, RA3XDH
воскресенье, 27 июля 2014 г.
Работа с последовательным портом из консоли Linux
В предыдущем посте было показано как запустить UART на отладочной плате Launchpad для MSP430. Теперь рассмотрим как общаться с платой при помощи средств командной строки Linux. Используется плата с прошивкой из предыдущего поста. Для подробностей — см. под кат
Как известно, все устройства последовательных портов представлены файлами устройств в каталоге /dev.Через эти файлы и происходит общение ОС Linux с внешним устройством на последовательном порту. Чтобы передать что-то на внешнее устройство нужно записать данные в файл устройства, а чтобы считать информацию из устройства — прочитать данные из файла устройства. Это можно делать при помощи команд cat и echo так же как для обычных файлов на диске. Или внутри программы на С при помощи вызовов ioctl(), read() и write() или библиотеки termios.
Физическим последовательным портам RS232, к которым подключались диалапные модемы на старых компьютерах, соответствуют файлы устройств /dev/ttyS*, начиная с /dev/ttyS0. Виртуальным последовательным портам, которые создаются различными конвертерами USB UART соответствуют файлы устройств /dev/ttyUSB* и /dev/ttyACM*. Ядро Linux автоматически разпознаёт подключенное устройство, загружает для него драйвер и создаёт файл устройства. Вручную устанавливать драйвер, как в ОС Windows не требуется. Например, если подключить к USB преобразователь USB UART FT232, то создаётся файл устройства /dev/ttyUSB0, с которым можно работать также как и с обычным последовательным портом. На плате Launcpad находится микросхема TUSB3410, которая тоже представляет собой конвертер USB UART. Если подключить её к USB, то создаётся файл устройства /dev/ttyACM0. Чтобы общаться с платой нужно что-либо писать/читать с этого файла.
Чтобы пользователь мог читать или писать в файл устройства последовательного порта, его нужно добавить в группу dialout. Иначе работать с последовательным портом сможет только администратор root.
Простейшим приложением с графическим интерфейсом, которое работает с последовательным портом, является CuteCOM. Он обычно уже есть в вашем дистрибутиве Linux. Его можно установить из репозиториев. При помощи CuteCOM мы работали с платой в предыдущем посте. Выглядит CuteCOM вот так:
Работать с ним крайне просто. Указываем нужное устройство, если его нет в списке, то его можно впечатать вручную. Затем указываем скорость и параметры и нажимаем OpenDevice. В окне видим данные, которые пришли от устройства. В поле ввода в нижней части можем печать строку символов, которые предаются на устройство. Чтобы передать данный нажимаем Enter и смотрим ответ устройства в окне.
Теперь рассмотрим как работать с COM-портом из командной строки. Для этого служат три команды: stty, cat и echo.
Команда stty устанавливает параметры и скорость COM-порта. Её формат:
stty -F
Чтобы установить параметры для платы Launchpad для соединения на скорости 9600 нужно выполнить:
$ stty 9600 -F /dev/ttyACM0 raw -echo
Параметр raw устанавливает, что данные в компьютер передаются байт за байтом так же как приходят в порт без преобразований. Аппаратное управление потоком отключено. Подробнее о том, что включает и выключает raw — см. man stty. Если не включить raw, то скорее всего ничего работать не будет.
Теперь в той же консоли нужно набрать
$ cat /dev/ttyACM0
И можно смотреть данные, которые приходят от платы. Выход — нажать Ctrl+C.
Теперь нажимаем на плате RESET и видим, что в консоди напечатался текст.
Чтобы передать в плату данные, в другой консоли нужно использовать команду echo и перенаправление вывода в файл устройства. Наберём в другой консоли:
$ echo "1">/dev/ttyACM0
Видим, что на плате загорелся красный светодиод и в первой консоли было выдано сообщение об этом. Чтобы убрать конец строки в передаваемых данных, то нужно использовать запуск echo -n, а чтобы интерпретировать 16-ричные коды — нужно echo -e. Ключи можно комбинировать.
В итоге должно получиться так:
Чтобы увидеть 16-ричные коды данных, приходящих от устройства, нужно использовать команду hexdump:
$ cat /dev/ttyACM0|hexdump -C
Получится вот так:
Чтобы иметь вывод данных от устройство на экран и в текстовый файл нужно использовать tee:
Источник
Собираем плату
Значит сделал я такую схемку (да простят меня ардуинщики и физики и вообще…). Короче не будем вдаваться в подробности ее корректности. По крайне мере она работает.
Короче на ней есть два светодиода подключенный к цифровым портам и фоторезистор подключенный к аналоговому порту. Будем писать интерфейс который позволит переключать светодиоды и считывать значения фоторезистора.
Для управления ардуино я буду использовать следующую схему
- Если я отправил символ ‘r’ – значит я хочу чтобы зажегся красный светодиод (англ. r
red)
Если я отправил символ ‘b’ – значит я хочу чтобы зажегся синий светодиод (англ. b
blue)
Вот такая у меня получилась программа для ардуино
Создаем приложение
И так открываем Qt Creator и создаем новый проект
выбираем тип приложения
ну и все собственно
увидим что-то такое
чтобы ошибки ушли. Надо один раз запустить приложение. Для этого кликаем на зеленый треугольник (либо жмем Ctrl+R)
запустится наше интерфейс, который пока выглядит вот так:
Собираем форму
закрываем его и начинаем править. Для этого переключимся на форму двойным щелчком на mainwindow.ui
собственно, увидим нашу форму:
Теперь начнем перетаскивать на нее элементы формы. Сначала я хочу, чтобы у меня было поле в котором можно ввести порт к которому я буду коннектиться для общения с ардуино.
Делается это так:
- Label – это просто метка, не редактируемый текст.
- LineEdit – поле для редактирования однострочного текста
Не смотрите что пока все криво, мы в конце добавим немного магии чтобы все выровнять.
Теперь сделаем две кнопки для включения красного и синего светодиодов
и еще поле где будем показывать показания с датчика освещённости
а, ну и еще лог, в который будем писать, что отвечает нам ардуинка
А теперь чуток магии чтобы все это выровнялось
если немного разъяснить, то тут я объединяю компоненты в горизонтальные группы (чтобы выбрать несколько элементов я удерживаю Ctrl)
А потом кликаю на последнюю кнопку, чтобы выровнять группы по сетке.
Можно запустить (Ctrl+R) и проверить как все работает
теперь нам присвоить имена нашим полям для ввода, чтобы была возможность обратится к ним из кода программы. Кликаем на поле для ввода порта, и справа в списке свойств находим в самом верху свойство objectName
меняем его на txtPort
у остальных полей поменяем потом.
Добавляем обработчик нажатия на кнопку
Теперь давайте добавим реакцию на клик кнопки “Включить синий” для этого кликаем на нее правой кнопкой мыши и выбираем “Перейти к слоту”
в Qt используется так называемый механизм сигналов (signal) и слотов (slot) это расширений C++, которое позволяет связывать событие с реакцией на событие более-менее естественный образом.
В общем открывается такое окно где виден список сигналов, которые может послать кнопка. Например, когда вы просто нажали на кнопку, но еще не отпустили кнопку мышь, генерируется сигнал pressed, а если же вы отпустил мышь, то сгенерируется сигнал clicked.
Короче суть в том, что мы к этому сигнал сейчас привяжем функцию (или если мыслить в рамках Qt – слот)
выбираем clicked и жмем OK:
нас кидает в редактор кода
не будем мудрствовать и для начала давайте просто выведем какое-нибудь сообщение, правим функцию
скорее всего вы увидите, что QMessageBox подчеркнуто и выдается ошибка:
это потому что мы не подключим заголовочный файл с этим классом, ставим курсор на QMessageBox и жмем Alt+Enter
и видим, как вверху добавился необходимый include
теперь давайте запустим приложение и проверим что кнопка действительно заработала.
Жмем Ctrl+R и кликаем на кнопку
Выводим значение из txtPort
Давайте теперь попробуем сделать так чтобы по нажатию на кнопку выводилось содержимое поля для ввода порта. Подправим функцию:
Посылаем сообщение arduino
Для работы с COM портом у QT есть класс QSerialPort, давайте подправим функцию чтобы она отправил символ “b” в порт и тем самым зажгла светодиод:
он опять будет ругаться на QSerialPort (ставьте курсор на него, жмите Alt+Enter, выбирайте #include , ну либо руками сами добавляйте)
Пробуем запустить. Жмем Ctrl+R
И видим кучу ошибок:
дело в том, что QSerialPort специализированная библиотечка, и чтобы ее начать использовать надо попросить QT использовать ее dll файл.
Как это сделать. Для этого есть документация!) В ней указано что надо прописать класс заработал.
У QtCreator встроенная документация по Qt, так что ставим курсор на QSerialPort и жмем F1
собственно, тут видно какой заголовочный файл (Header) достаточно указать, и еще что-то про qmake
qmake – это такой себе компилятор QT, который делает из QT C++ кода обычный C++ код, его поведение настраивается в *.pro файле
Кликаем в левом меню Редактор
далее выбираем GuiController.pro – собственно pro файл, ну или проще говоря project файл
в самом верху в нем строчка:
добавим к ней снизу
пробуем запустить снова (Ctrl+R)
уже по крайней мере запустилось!) Попробуем нажать на кнопку
Ну да мы ведь порт не указали, так что логично
Пробуем зажечь светодиод
Собираем и подключаем нашу ардуинку. Заливаем на нее программу, за одно проверяем какой порт использовать
запускаем нашу программу, вводим порт COM3 и смотрим:
Давайте теперь добавим то что вернет arduino в ответ на зажжение светодиода, как мы помним там у нас есть:
а в нашем обработчике мы в холостую читаем данные:
попробуем сохранить результат в какую-нибудь переменную и вывести ее в наше большое поле для текста.
Только сначала дадим ему осознанное имя. Переключаемся на mainwindow.ui
теперь идем обратно в mainwindow.cpp и правим on_pushButton_clicked:
у нас в программе никаких “Blue is on” так что можно с чистой совестью заявить, что это отправило нам ардуино.
Правим красную кнопку
По аналогии с синей кнопкой добавим обработчик на красную.
запускаем и проверяем:
в общем показывать, что диоды у меня действительно переключаются мне чего-то лень, но вот сообщения по крайне мере точно приходят с ардуино =)
Читаем значения датчика освещённости
Дадим осознанное имя поля для значения фоторезистора
И добавим обработчик кнопке обновить:
и пишем код (по сути копипастим с правкой в двух местах):
Обновляем значения датчика освещённости в режиме реального времени
Тыкать все время на кнопку обновить не очень интересно. Лучше, чтобы это делалось на автомате. При чем не именно кликанье на кнопку, а просто команда запроса значения и вывода его на форму. Допустим раз в секунду или чаще.
Для этого есть возможность добавить таймер, ему можно указать вызывать некоторую функцию с каким-то промежутком.
Делается это так. В конструкторе добавляем таймер
Теперь как только мы укажем правильный порт, начнут приходить значения:
Вот собственно и все!
БОНУС
Писать порт все время лениво. Есть возможность получить список всех доступных портов. Делается это так.
Сначала идем на mainwindow.ui и удаляем txtPort, на место него ставим Combo Box
правим ему свойства
- objectName меняем на cmbPort
- кликаем дважды на sizePolicy и в свойстве Горизонтальная политика ставим Expanding, чтобы этот комбо бокс как и lineEdit занимал все свободное место
возвращаемся к коду mainwindow.cpp и в конструкторе добавляем:
Прикольно, что прям сразу подключается! Такие дела =)
Источник