1. 项目概述:在Edison平台上迈出Python第一步
如果你手头有一块Intel Edison开发板,正琢磨着怎么让它跑起来,特别是想用它来写点Python程序,那这篇分享就是为你准备的。Edison这块板子,当年出来的时候定位很明确,就是给物联网和嵌入式原型设计用的,它集成了Atom处理器和Quark微控制器,性能比传统的Arduino强不少,能跑完整的Linux系统。这就意味着,我们能在上面玩转很多在PC上熟悉的工具,比如Python。对于刚接触嵌入式Linux开发,或者想用Python快速实现物联网设备逻辑的朋友来说,在Edison上配置Python环境,是连接硬件世界和高级编程语言非常关键的一步。这不仅仅是安装一个软件,更是理解如何在资源受限的嵌入式环境中,搭建一个稳定、可用的开发工作流。
我最初接触Edison时,也走了些弯路,比如纠结于系统自带的Python版本太老,或者网络安装包慢得让人抓狂。这次,我就把整个从零开始,在Edison上搭建一个顺手Python开发环境的过程,以及写第一个脚本、调试的心得,系统地梳理一遍。目标很直接:让你拿到板子后,能快速上手,把想法用Python代码在真实的硬件上跑起来,避开那些我踩过的坑。整个过程会涉及系统连接、包管理、环境配置、基础脚本编写和简单调试,适合有一定Linux命令行基础,但可能是第一次在嵌入式设备上玩Python的开发者。
2. Edison开发板基础准备与系统连接
在开始写Python代码之前,我们得先和Edison板子“搭上话”。Edison默认运行的是基于Yocto Project构建的Linux系统,我们需要通过命令行来操作它。
2.1 硬件连接与串口通信配置
最可靠、最基础的连接方式是使用串口(UART)。你需要一根Micro USB线(用于供电和调试),以及一个USB转TTL串口模块(比如常见的FT232RL、CH340等)。将串口模块的RX、TX、GND分别连接到Edison的J3-1 (RX)、 J3-2 (TX) 和 J3-6 (GND)。注意,这里是交叉连接:模块的TX接Edison的RX,模块的RX接Edison的TX。
在电脑上,你需要一个串口终端工具。在Windows上,PuTTY或MobaXterm是不错的选择;在macOS或Linux上,screen或minicom更常用。关键是要找到正确的串口端口号(在Windows设备管理器中查看COM号,在Linux/macOS下通常是/dev/ttyUSB0或/dev/tty.usbserial-*)并设置正确的参数:波特率115200,数据位8,停止位1,无奇偶校验,无流控制。
注意:很多新手会忽略流控制(Flow Control),一定要设置为“None”或“XON/XOFF”,否则你输入字符可能没有回显,误以为板子没启动。
连接成功后,给Edison上电,终端里会滚动启动日志,最后出现root@edison:~#这样的登录提示符。默认用户名是root,没有密码。成功登录后,你就拥有了板子的完整控制权。这是所有后续操作的基础,务必确保这一步稳定可靠。
2.2 网络配置与软件源更新
为了能顺利安装Python和相关工具,给Edison配置网络几乎是必须的。Edison可以通过USB OTG模拟网络,或者连接USB WiFi模块(如Edison Arduino扩展板上自带的)来联网。
通过USB OTG联网(推荐给有线环境):用另一根Micro USB线连接Edison的OTG口(通常是靠近SD卡槽的那个)到电脑。在Edison系统里,这个接口通常会枚举为usb0网络设备。在Edison终端里执行ifconfig usb0 up,然后使用udhcpc -i usb0自动获取IP(如果你的主机配置了共享网络)。更常见的是在主机端配置网络共享,然后在Edison上设置静态IP,例如:
ifconfig usb0 192.168.2.2 netmask 255.255.255.0 up route add default gw 192.168.2.1 echo "nameserver 8.8.8.8" > /etc/resolv.conf这样,Edison的IP是192.168.2.2,网关是192.168.2.1(你的电脑)。
通过WiFi联网:如果你的Edison接了Arduino扩展板并插上了WiFi模块,可以使用configure_edison --setup命令进行交互式WiFi配置(旧版镜像),或者直接编辑/etc/wpa_supplicant/wpa_supplicant.conf文件添加你的WiFi信息,然后用ifconfig wlan0 up和udhcpc -i wlan0来连接。
网络通畅后,第一件事是更新软件包列表。Edison的Yocto系统通常使用opkg包管理器。执行:
opkg update这个命令会从配置的软件源同步可安装包的列表。由于Edison的官方源可能已经停止维护或访问缓慢,有时需要寻找可用的社区镜像源,更新/etc/opkg/base-feeds.conf文件中的源地址。这是保证后续能安装到软件的前提。
3. Python环境部署与版本管理策略
Edison自带的系统镜像里,很可能已经有一个Python 2.7版本。但Python 2早已停止维护,且很多现代库只支持Python 3。因此,我们的核心任务是安装一个较新的Python 3版本。
3.1 安装Python 3及其包管理工具pip
直接使用opkg安装是最简单的方法。先搜索一下可用的Python 3包:
opkg list | grep python3你可能会看到类似python3、python3-core、python3-pip这样的包。安装它们:
opkg install python3 python3-pip这个过程会自动处理依赖。安装完成后,运行python3 --version和pip3 --version来验证。如果opkg源里没有合适的版本,或者版本太旧,我们就需要考虑从源代码编译。
从源代码编译安装(获取最新版本):这是一条更灵活但也更复杂的路。首先安装编译所需的工具链和依赖库:
opkg update opkg install gcc g++ make libffi-dev openssl-dev zlib-dev ncurses-dev readline-dev sqlite3-dev bzip2-dev xz-dev然后去Python官网下载源代码包(例如Python 3.8.10)。用wget下载到Edison上,或者先下载到电脑再通过scp传过去。接着解压、配置、编译:
tar -xzf Python-3.8.10.tgz cd Python-3.8.10 ./configure --enable-optimizations --prefix=/usr/local/python3.8 # --prefix指定安装目录 make -j2 # Edison是双核,可以用-j2加速编译,但注意内存可能不足 make altinstall # 使用altinstall避免覆盖系统默认的python3命令make altinstall会将Python安装到/usr/local/bin/python3.8,而pip则对应pip3.8。这样做的好处是保留了系统可能存在的其他Python 3版本,便于管理。
实操心得:在Edison上编译Python是个耗时且考验耐心的事情,内存不足可能导致编译失败。如果遇到
gcc: internal compiler error: Killed这类错误,通常是内存耗尽。可以尝试不适用-j参数单线程编译,或者先创建一个足够大的swap交换分区(例如512MB)来缓解:dd if=/dev/zero of=/swapfile bs=1M count=512 && mkswap /swapfile && swapon /swapfile。
3.2 配置环境变量与创建虚拟环境
安装好Python 3后,为了让python3和pip3命令能方便地调用,最好将它们链接到/usr/bin下,或者将安装目录加入PATH环境变量。例如,如果你编译安装到了/usr/local/python3.8,可以:
ln -sf /usr/local/python3.8/bin/python3.8 /usr/bin/python3 ln -sf /usr/local/python3.8/bin/pip3.8 /usr/bin/pip3强烈建议使用虚拟环境(virtual environment)。在嵌入式设备上,这同样是个好习惯。它能将项目依赖与系统Python环境隔离,避免包冲突,也便于管理。安装virtualenv:
pip3 install virtualenv为你的项目创建一个虚拟环境,比如在/home/root/my_project目录下:
cd /home/root/my_project python3 -m venv venv # 或者 virtualenv venv激活虚拟环境:
source venv/bin/activate激活后,命令行提示符通常会变化,前面多出(venv)字样。此时,所有pip install操作都只影响当前虚拟环境。退出虚拟环境用deactivate命令。对于资源有限的Edison,虚拟环境会占用一些磁盘空间,但带来的依赖清晰管理的优势是值得的。
4. 开发工具链搭建与代码编辑
在Edison上写代码,主要有两种模式:一是在板子上直接编辑(适合简单脚本);二是在PC上开发,然后同步或部署到板子上(推荐,效率高)。我们分别看看。
4.1 板载简易编辑与执行
对于快速的测试和小脚本,可以直接在Edison终端里使用文本编辑器。系统可能自带vi或nano。nano对新手更友好:
nano hello.py然后输入你的第一行Python代码:print("Hello from Edison!"),按Ctrl+O保存,Ctrl+X退出。运行它:
python3 hello.py如果一切正常,终端会打印出问候语。这是最直接的验证方式。
4.2 基于VSCode的远程开发配置(高效推荐)
在PC上使用强大的IDE进行开发,然后远程同步和调试,是更专业高效的做法。Visual Studio Code (VSCode) 配合其远程开发扩展是绝佳选择。
首先,在Edison上需要确保SSH服务已开启并允许root登录(仅限开发环境,生产环境慎用)。通常Edison的SSH是默认开启的。在PC的VSCode中,安装“Remote - SSH”扩展。然后通过“远程资源管理器”添加新的SSH主机,格式为root@<你的Edison IP地址>,例如root@192.168.2.2。首次连接会提示你保存主机密钥,并可能需要输入密码(Edison默认root无密码,直接回车)。
连接成功后,VSCode会在Edison上自动安装一个轻量级的服务器端,之后你就可以像操作本地文件夹一样,在侧边栏打开Edison上的远程目录。接着,在VSCode的扩展商店里安装“Python”扩展(由Microsoft发布),这个扩展会识别远程环境中的Python解释器。
点击VSCode左下角的Python版本显示区域,可以选择解释器。你应该能看到我们之前安装的Python 3路径,或者虚拟环境venv下的python。选择它,VSCode就会利用这个远程解释器进行代码补全、语法检查、调试等所有功能。你可以在PC上编写代码,保存后直接在VSCode的集成终端里运行,这个终端实际上就是Edison的Shell。这种体验几乎和本地开发无异,却是在真实的硬件环境中执行。
注意事项:确保Edison和PC在同一个局域网,且防火墙没有阻断SSH端口(22)。如果通过USB OTG网络连接,PC需要能路由到Edison的IP。使用VSCode远程开发时,所有项目文件实际存储在Edison上,所以要注意Edison的存储空间。
5. Python基础应用实例与硬件交互
环境搭好了,工具也备齐了,现在来点实际的。我们通过几个由浅入深的例子,看看Python在Edison上能做什么。
5.1 基础脚本:系统信息获取与文件操作
一个简单的脚本,收集Edison的系统信息并写入文件,这能练习文件操作和系统命令调用。
import os import platform import subprocess from datetime import datetime def get_system_info(): info = {} info['时间'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') info['Python版本'] = platform.python_version() info['系统'] = platform.system() info['处理器'] = platform.processor() # 使用uname命令获取更详细的系统信息 try: uname_result = subprocess.check_output(['uname', '-a']).decode().strip() info['Uname'] = uname_result except Exception as e: info['Uname'] = f"获取失败: {e}" # 获取内存信息 try: with open('/proc/meminfo', 'r') as f: for line in f: if 'MemTotal' in line: info['总内存'] = line.strip() break except Exception as e: info['内存信息'] = f"获取失败: {e}" return info def write_info_to_file(info, filename='edison_info.txt'): with open(filename, 'w') as f: f.write("=== Edison系统信息 ===\n") for key, value in info.items(): f.write(f"{key}: {value}\n") print(f"信息已写入文件: {filename}") if __name__ == "__main__": sys_info = get_system_info() for k, v in sys_info.items(): print(f"{k}: {v}") write_info_to_file(sys_info)这个脚本展示了如何使用platform模块获取Python环境信息,用subprocess调用系统命令,以及基本的文件读写操作。在Edison上运行,你能看到具体的硬件和系统信息。
5.2 硬件交互:控制GPIO点亮LED
这才是嵌入式开发的精髓。Edison的GPIO可以通过mraa或python-periphery这样的库来控制。mraa是Intel官方推荐的库,对Edison的引脚映射支持很好。首先安装它:
pip3 install mraa或者通过opkg安装:opkg install mraa python3-mraa。
假设我们在GPIO引脚12(对应Edison的物理引脚,具体需查阅引脚映射图)上连接了一个LED(阳极接GPIO,阴极通过一个220Ω电阻接地)。下面是一个闪烁LED的程序:
import mraa import time print("MRAA版本:" + mraa.getVersion()) # 初始化GPIO 12 为输出 led_pin = mraa.Gpio(12) led_pin.dir(mraa.DIR_OUT) print("开始LED闪烁...按Ctrl+C停止") try: while True: led_pin.write(1) # 输出高电平,LED亮 print("LED ON") time.sleep(0.5) led_pin.write(0) # 输出低电平,LED灭 print("LED OFF") time.sleep(0.5) except KeyboardInterrupt: print("\n程序被用户中断") finally: led_pin.write(0) # 确保退出时LED熄灭 print("清理完毕")关键点解析:
mraa.Gpio()初始化时需要传入的是MRAA库定义的引脚编号,而不是物理引脚号。你需要查阅Edison的MRAA引脚映射图来确认。例如,Intel Edison for Arduino扩展板上的数字引脚D13,对应的MRAA编号可能是13。使用前务必确认,否则无法控制。另外,务必为LED串联一个限流电阻(通常220Ω-1kΩ),直接连接GPIO到LED可能会损坏引脚。
5.3 数据采集:读取模拟传感器
Edison的Arduino扩展板提供了模拟输入引脚。我们可以用Python读取模拟传感器的值,比如一个电位器或光敏电阻。这里需要用到mraa的Aio(模拟输入)功能。
import mraa import time # 初始化模拟输入引脚 A0 (MRAA编号对应为0) sensor_pin = mraa.Aio(0) print("开始读取模拟传感器值...") try: while True: # 读取原始值(例如,10位ADC返回0-1023) sensor_value = sensor_pin.read() # 假设参考电压为5V,转换为电压值 voltage = (sensor_value / 1023.0) * 5.0 print(f"原始值: {sensor_value:4d}, 电压: {voltage:.2f} V") time.sleep(1) except KeyboardInterrupt: print("\n数据采集停止")这个例子展示了如何连续读取模拟量并做简单的转换。你可以根据传感器的特性,将电压值转换为具体的物理量,如光照强度、角度等。
6. 项目组织、依赖管理与简单部署
当你的代码从一个脚本成长为一个有多个模块的小项目时,良好的组织结构和管理依赖就变得重要了。
6.1 项目结构与管理依赖
一个典型的简单项目结构可能如下所示:
my_iot_project/ ├── requirements.txt ├── src/ │ ├── __init__.py │ ├── sensor_reader.py # 负责读取传感器的模块 │ └── data_logger.py # 负责记录数据的模块 ├── configs/ │ └── settings.yaml # 配置文件 ├── scripts/ │ └── main.py # 主程序入口 └── tests/ └── test_sensor.py # 单元测试在项目根目录的requirements.txt文件中,列出所有依赖:
mraa==2.0.0 pyyaml>=5.1 pyserial==3.5在激活的虚拟环境中,一键安装所有依赖:
(venv) pip install -r requirements.txt这样做的好处是,当你需要在另一台Edison或新环境中复现项目时,只需要git clone代码,创建虚拟环境,然后pip install -r requirements.txt即可,极大地保证了环境的一致性。
6.2 将脚本设置为系统服务(开机自启)
对于需要长期运行的后台程序(比如一个环境监测器),我们通常希望它能开机自动启动,并且在崩溃后能自动重启。在Linux系统上,最常用的方法是使用systemd服务。
首先,编写一个可靠的Python脚本,确保它能在后台持续运行。例如,/home/root/my_project/scripts/monitor.py。然后,创建一个systemd服务单元文件,例如/etc/systemd/system/edison-monitor.service:
[Unit] Description=Edison Python Monitoring Service After=network.target [Service] Type=simple User=root WorkingDirectory=/home/root/my_project ExecStart=/home/root/my_project/venv/bin/python /home/root/my_project/scripts/monitor.py Restart=on-failure RestartSec=10 StandardOutput=syslog StandardError=syslog SyslogIdentifier=edison-monitor [Install] WantedBy=multi-user.target关键参数解释:
WorkingDirectory: 服务启动时的工作目录,影响相对路径。ExecStart: 启动命令。这里使用了虚拟环境中的Python解释器,确保依赖正确。Restart=on-failure: 当进程非正常退出时自动重启。RestartSec=10: 重启前等待10秒。
保存文件后,执行以下命令启用并启动服务:
systemctl daemon-reload # 重新加载systemd配置 systemctl enable edison-monitor.service # 启用开机自启 systemctl start edison-monitor.service # 立即启动服务 systemctl status edison-monitor.service # 查看服务状态使用journalctl -u edison-monitor.service -f可以实时查看该服务的日志输出。这种方式让你的Python应用变得像系统原生服务一样可靠。
7. 常见问题排查与性能优化技巧
在实际操作中,你肯定会遇到各种各样的问题。这里记录一些典型问题的排查思路和解决方法。
7.1 安装与依赖问题
问题1:opkg install或pip install速度极慢甚至失败。
- 排查:这通常是网络连接或软件源的问题。
- 解决:
- 检查网络:
ping 8.8.8.8测试基本连通性。对于opkg,可以尝试更换更快的软件源镜像,编辑/etc/opkg/base-feeds.conf文件。 - 使用国内镜像加速pip:在Edison上创建或编辑
~/.pip/pip.conf,写入:[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn - 离线安装:在联网的电脑上,用
pip download -d ./packages package_name下载包及其依赖的whl文件,然后拷贝到Edison上,用pip install --no-index --find-links=./packages package_name安装。
- 检查网络:
问题2:导入模块时提示ImportError: No module named 'xxx'。
- 排查:首先确认你是否在正确的Python环境和路径下。运行
python3 -c "import sys; print(sys.path)"查看模块搜索路径。 - 解决:
- 确保已用
pip安装了该模块。使用pip3 list | grep xxx检查。 - 如果你在虚拟环境中,确认虚拟环境已激活(命令行提示符有
(venv))。 - 如果是自己编写的模块,确保包含模块的目录在
sys.path中,或者通过设置PYTHONPATH环境变量添加。
- 确保已用
7.2 硬件与权限问题
问题3:运行GPIO控制脚本时报错Permission denied或error performing sysfs operation。
- 排查:访问GPIO等硬件资源需要root权限,或者用户属于特定的组(如
gpio)。 - 解决:
- 最简单的方式:直接以root用户运行脚本(Edison默认就是root)。
- 如果出于安全考虑想用非root用户,需要将用户添加到
gpio组:usermod -a -G gpio your_username,然后重新登录。但Edison默认的Yocto系统用户和组管理可能比较精简,需要先确认相关组是否存在。
问题4:模拟输入读取的值始终为0或固定不变。
- 排查:
- 硬件连接错误:检查传感器是否接在正确的模拟引脚(A0-A5),电源和地线是否接好。
- 引脚编号错误:确认
mraa.Aio()中使用的引脚编号是否正确。对于Arduino扩展板,A0对应的MRAA编号通常是0。 - 传感器或ADC本身问题。
- 解决:先用一个简单的分压电路测试(例如,用一个电位器),排除传感器本身的问题。使用
mraa.getPinName(pin_number)可以打印引脚名称辅助调试。
7.3 性能与资源管理
Edison的资源(CPU、内存、存储)相对有限,编写代码时需要有优化意识。
技巧1:避免不必要的导入和全局变量。在循环中重复导入模块或初始化硬件(如mraa.Gpio())会消耗额外时间。正确的做法是在循环外初始化一次。
# 不佳的做法 while True: import mraa pin = mraa.Gpio(13) pin.write(1) time.sleep(1) # 推荐的做法 import mraa import time pin = mraa.Gpio(13) pin.dir(mraa.DIR_OUT) while True: pin.write(1) time.sleep(1)技巧2:谨慎使用time.sleep()。在需要精确计时或快速响应的循环中,长时间的sleep会阻塞整个线程。考虑使用time.sleep(0.01)这样的短延时,或者使用线程/异步编程来处理并发任务。对于简单的周期性任务,sched模块或threading.Timer可能更合适。
技巧3:监控资源使用情况。使用top或htop命令查看CPU和内存占用。使用df -h查看存储空间。养成定期清理/tmp目录和不再使用的pip缓存(~/.cache/pip)的习惯。如果程序需要处理大量数据,考虑将日志或数据存储到外接的SD卡或U盘上,而不是内置的有限eMMC存储中。
技巧4:处理异常,保持稳定。物联网设备可能面临不稳定的网络、传感器断连等问题。你的代码必须有良好的异常处理机制,避免因为一个未捕获的异常导致整个服务崩溃。特别是在while True主循环中,要用try...except包裹核心逻辑,并记录错误日志。
while True: try: # 主要的传感器读取、数据处理、网络发送逻辑 read_sensor_and_upload() except KeyboardInterrupt: raise # 让Ctrl+C能正常退出 except Exception as e: print(f"[ERROR] 主循环发生异常: {e}") log_error(e) # 记录到文件或系统日志 time.sleep(60) # 出错后等待一段时间再重试,避免疯狂刷日志这些技巧和问题排查经验,很多都是在实际项目中碰壁后总结出来的。嵌入式Python开发不同于PC,更贴近硬件,需要考虑更多的稳定性和资源约束。从简单的点灯开始,逐步尝试读取传感器、通过网络发送数据、设计状态机逻辑,你会逐渐发现,用Python在Edison这类平台上实现物联网应用原型,既快速又充满乐趣。