如何在20元小板子上跑Python
如今物联网技术风生水起,Python也要多凑热闹。
=========================================================================================================================================================================================================
MicroPython项目自2014年启动,旨在低廉嵌入式系统上以固件形式运行Python。MicroPython的官方开发板是一块基于STM32的SoC,然而,这块开发板的价格一直居高不下,在某宝上买要将近200块。然而,最新的树莓派Zero也才150块钱,而树莓派是支持通用Linux的,比嵌入式固件不知道高明到哪里去了。
2014年8月,位于上海的乐鑫公司推出了针对物联网终端应用的ESP8266 SoC,这款芯片自带WiFi和硬件加速的TCP/IP协议栈,价格非常低廉。连同开发板(NodeMCU)在淘宝上的零售价不超过20元,价格直逼Arduino小板。除了官方提供的基于C语言的SDK外,NodeMCU项目提供了基于Lua语言的脚本式开发环境。此外,这块芯片也可以烧录AT协议的固件,在系统中充当一块无线网卡。
虽然Lua是一门很棒的语言,但和TIOBE常年top10的Python相比,依然相对小众。2016年5月,1.8版本的MicroPython开始提供对ESP8266芯片的支持,这意味着,更多的开发者可以使用自己熟悉的语言,以极低成本制作一套物联网终端。
本文简单介绍如何在ESP8266开发板上运行MicroPython。
1. 购买开发板
在某宝上以NodeMCU为关键字,即可发现ESP8266开发板。因为它太便宜,往往不抵运费合算。所以可以选择一些大一点的商家,根据自己的需要配置一些发光二极管、面包板、杜邦线之类的配件。当然也可以购买一些板载继电器、温度传感器之类的实验板供把玩。
2. 安装驱动程序
如果你购买了NodeMCU,或者NodeMCU兼容的开发板,首先需要安装串口转USB的驱动。如果你用的是Linux或者macOS,系统通常自带了驱动。如果你的系统是Windows,则需要根据转换器的型号去官网下载驱动程序。比如通常买的这款NodeMCU,其转换器型号为CP2102,则去Silicon Lab的官网下载。
USB to UART Bridge VCP Drivers
安装完驱动后,把开发板用Micro USB线连接到电脑上。然后用
这篇文章
的方法找到开发板对应的串口名称。下文中以
<serial_port>
代之。
3. 安装工具软件
在电脑上安装Python,或者利用系统自带的Python。如今NodeMCU的开发工具已经在pip中。执行以下命令即可
pip install esptool -U
此外,还需要一个串口终端。在Linux下可以使用系统自带的minicom,macOS下可以使用系统自带的screen,或者安装一个minicom,Windows下可以使用putty
4. 烧录MicroPython固件
在 此处 可以得到官方最新发布的MicroPython/ESP8266固件。笔者下载的是esp8266-20161110-v1.8.6.bin
运行以下命令可以将固件下载到开发板中
$ esptool.py --port <serial_port> erase_flash
$ esptool.py --port <serial_port> --baud 460800 write_flash --
flash_size=detect 0 esp8266-20161110-v1.8.6.bin --verify
这个下载命令与官方命令稍有区别。笔者强烈的建议:
- 在烧录固件之前erase_flash,尤其是对于一些烧录过其他固件的旧开发板。
- 烧录命令增加 --verify选项进行校验。
5. 连接开发板,得到Python Shell
使用minicom的用户,运行以下命令
sudo minicom -s
在其后的菜单里,选择串口为连接开发板的串口,波特率115200
使用screen的用户,运行以下命令
screen <serial_port> 115200
使用putty的用户,按以下设置:
连接完成后,按开发板的复位键,得到Python Shell
6. 硬件操作实战
虽然,在树莓派里也可以通过gpio库操作树莓派的IO,但这里与树莓派的区别是,MicroPython是 实时 的,也就是说,从下达软件指令到硬件电路做出响应,其时间是确定的。
使用MicroPython操作IO的时候需注意,MicroPython的固件是针对ESP8266的,不是针对NodeMCU的,因此,其Pin的编号是ESP8266的GPIOx,而不是NodeMCU板子上的Dx。下面的例子就是对板载LED进行操作。NodeMCU文档有这样一个表格:
对于LED,若用Lua操作,则需要操作Pin 0,若用MicroPython操作,则需要操作Pin 16。
7. WiFi温度传感器
下面利用MicroPython/ESP8266制作一个WiFi温度传感器。
我们需要准备的硬件除了NodeMCU开发板之外,还需要一个温度传感器。DHT系列是一种比较常用的廉价温度传感器模组,笔者手头有一只DHT11模组,大概4块钱买的。
DHT11是单线数字信号,其协议并不是I2C、SPI之类的标准协议。好在MicroPython内建了DHT协议的支持。像这样就可以读温度传感器的值了:
import dht
PIN_DHT = 14 #(GPIO14/D5)
d = dht.DHT11(machine.Pin(PIN_DHT))
d.measure()
print(d.temperature())
这样的代码量,少得几乎不能再少。
下面把完整的代码贴出来,保存为 dht_server.py
import dht
import machine
import usocket as socket
import network
SSID = 'YOUR_WIFI_SSID'
SSID_PW = 'YOUR_WIFI_PASSWORD'
def do_connect():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
wlan.connect(SSID,SSID_PW)
while not wlan.isconnected():
return wlan.ifconfig()
def read_dht():
PIN_DHT = 14
d = dht.DHT11(machine.Pin(PIN_DHT))
d.measure()
return d.temperature()
def do_server(ip,port):
CONTENT = """\
HTTP/1.0 200 OK
Content-Type: application/json
"data" : %d
ai = socket.getaddrinfo(ip,port)
addr = ai[0][4]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(addr)
s.listen(5)
while True:
res = s.accept()
client_s = res[0]
client_addr = res[1]
req = client_s.recv(4096)
parts = req.decode('ascii').split(' ')
if parts[1] == '/temperature':
client_s.send(bytes(CONTENT % read_dht(), "ascii"))
client_s.close()