ブログ:
嵌入式 Arm 平台使用Python和PyQT开发界面应用程序

2019年10月21日月曜日

简介

随着 Python 在互联网人工智能领域的流行,大家也慢慢感受到 Python 开发的便利,本文就基于嵌入式 Arm 平台,介绍使用 Python 配合 PyQt5 模块来开发图形化应用程序。

本文所演示的 Arm 平台来自于Toradex 基于 NXP i.MX6 Arm 处理器的 Apalis iMX6 Arm 嵌入式平台。 

准备

Apalis iMX6Q Arm  核心版配合 Apalis Evaluation Board 载板,连接调试串口 UART1(载板X29)到开发主机方便调试。更多关于 Apalis iMX6 配合 Apalis Evaluation Board 载板的说明请参考 Datasheet开发上手指南

Apalis iMX6Q 默认的 Linux BSP 是不包含 Python,Qt 等支持的,需要重新编译。

基于Toradex Linux BSP release V2.8

参考这里搭建 Openembedded 编译环境,然后适配下面 patch,用于使本文测试需要的 libsoc 适配 Python3。

https://github.com/simonqin09/libsoc-examples/blob/master/python/0005-libsoc-python3-support.patch

修改 build/conf/local.conf 文件,增加需要的组件

IMAGE_INSTALL_append = " python3 python3-pip python3-libsoc python3-pyqt5 rng-tools "

适配下面patch,在标准 image bb 文件中增加 Qt5 的支持

https://github.com/simonqin09/libsoc-examples/blob/master/python/0003-angstrom-qt5-lxde-image.patch

重新编译 image

$ bitbake -k angstrom-qt5-lxde-image

新生成的 image 位于 deploy/images/apalis-imx6/ 目录,参考这里的说明更新到 Apalis iMX6 模块上面

Python GPIO中断测试程序

首先我们先不包含图形界面,单独通过Python来完成简单的 GPIO中 断测试程序,本程序通过调用 libsoc 来完成 GPIO 控制,关于libsoc的使用和说明请参考这里

Apalis Evaluation Board 载板硬件连接配置如下,X4 GPIO05(MXM3_11)对应系统中的 GPIO 号码是 170,作为按键输入使用;X4 GPIO06(MXM3_13) 对应系统中的GPIO 号码是 169,作为输出驱动 LED 使用。

  • X4 GPIO05 <-> X34 SW5
  • X4 GPIO06 <-> X34 LED1

源代码请参考如下,分别实现了阻塞模式和非阻塞模式中断相应,实现功能就是按键交替点亮和关闭 LED 灯。

main 函数作为主函数,实现打开 GPIOs,同时设定初始化状态为高电平输出;test_interrupt_handler 函数实现中断相应,采用 gpio_in.wait_for_interrupt 为阻塞式中断,捕获中断才会继续进行,捕获中断后做了简单的防误触处理。

main 函数作为主函数,实现打开GPIOs,同时设定初始化状态为高电平输出;另外,在 main 函数里面采用 gpio_in.start_interrupt_handler 来使能中断相应,为非阻塞式;在 main 函数最后通过 while 来接收键盘输入实现退出应用;gpio_in.wait_for_interrupt 依然作为中断处理函数相应中断并驱动LED状态改变。

将 Python 代码直接复制到 Apalis iMX6 上面测试运行结果如下:

阻塞模式下,最后是通过Ctrl-C强制退出程序

root@apalis-imx6:~# ./gpiotest_block.py
The LED initial status is ON
The LED turns OFF
interrupt times is 1
The LED turns ON
interrupt times is 2
^Clibsoc-gpio-debug: Interrupted system call
Traceback (most recent call last):
File "./gpiotest_block.py", line 54, in <module>
  main(gpio_input_id, gpio_output_id)
File "./gpiotest_block.py", line 45, in main
   test_interrupt_handler(gpio_in, gpio_out)
File "./gpiotest_block.py", line 12, in test_interrupt_handler
   gpio_in.wait_for_interrupt(-1)
File "/usr/lib/python3.5/site-packages/libsoc/gpio.py", line 118, in wait_for_interrupt
   if api.libsoc_gpio_wait_interrupt(self._gpio, timeout) != 0:
KeyboardInterrupt

非阻塞模式下

root@apalis-imx6:~# ./gpiotest_nonblock.py
The LED initial status is ON
please enter 'Q' to quit
The LED turns OFF
The LED turns ON
The LED turns OFF
Q
Do you really want to quit? yes or no
yes
root@apalis-imx6:~#

使用 PyQt5 实现图形化界面 GPIO 中断程序

硬件配置和连接和上面的测试场景一致。

为了方便开发 PyQt5 界面,首先通过 Qtcreator 创建如下 QWidget 项目UI界面

LED Status 右边的 QFrame 方框以及 QLable 用于显示 LED 当前的状态。

‘Turn ON’ 和’Turn OFF’ 两个 PushButton 用于通过界面控制 LED 状态,’Exit’ PushButton用于退出程序。

最终的UI源代码参考如下,将对应的 mainwindow.ui 文件复制到 Apalis iMX6 Python 应用相同路径下

https://github.com/simonqin09/libsoc-examples/blob/master/python/mainwindow.ui

程序源代码参考如下:

https://github.com/simonqin09/libsoc-examples/blob/master/python/gpiotest_pyqt5.py

说明如下:

class ApplicationWindow 用于实现 Qt5 界面以及相关按键操作

  • 首先通过 loadUi 函数来加载之前制作好的UI文件 mainwindow.ui,然后初始化界面显示,连接各个按键对应的处理程序
  • 最后开启一个新的Qthread线程self.thread,用于处理外部GPIO按键中断相应,连接新线程反馈信号的处理程序,最后启动新线程
  • LedStatusChange 函数为处理新线程反馈回来的LED状态变化信号而同步改变界面显示状态的函数
  • Button_On_clicked 和 Button_Off_clicked 函数用于根据界面按键的点击来对应改变LED GPIO输出以及界面显示的函数
  • Button_Exit_clicked 和 closeEvent 函数用于处理退出程序包括子线程的退出等相关的函数

class gpioInterrupt 为用于处理 GPIO中 断同时对于改变 LED GPIO 输出以及将LED状态变化反馈给界面主程序

  • 首先定义反馈信号,并初始化所需要使用的 GPIO 引脚
  • run 函数部分基本就是上面第3章节的阻塞模式 Python 应用的代码,这里就不做赘述了

测试运行结果如下:

root@apalis-imx6:~# ./gpiotest_pyqt5.py
The LED initial status is ON
set LOW
set HIGH
The LED turns OFF
button clicked for setting LOW
The LED turns ON
button clicked for setting HIGH
root@apalis-imx6:~#

总结

如上述示例,使用 Python 和 PyQt 5非常方便了创建一个嵌入式界面应用程序示例,相对于传统 C 语言开机要配置交叉编译环境,整个流程更加快捷方便,同时在实现比较简单的控制的时候其运行效率也是可以接受的,另外 Python 还可以集成大量的组件方便开发,就更加简化了比如设计机器视觉、人工智能等领域的嵌入式应用开发流程。

記者: 秦海,技术销售工程师,韬睿(上海)

コメントを投稿

Please login to leave a comment!
Have a Question?