NodeMCU
NodeMCU 是一个开源的物联网平台。 该平台基于eLua开源项目,底层使用ESP8266 sdk 0.9.5版本。 NodeMCU包含了可以运行在esp8266Wi-FiSoC芯片之上的固件,以及基于ESP-12模组的硬件。用 C 实现了 Lua、Python 的编程环境,可以很方便的实现一些物联网应用。
烧录固件
我对于 Lua 语言不太熟悉,所以这里采用 MicroPython 的方案,注意检查连接 NodeMCU 的数据线,如果只是充电线,电脑是无法识别的。插上后,如果没有反应,可以手动安装 CH340 驱动,这是一个 USB 转串口的驱动。最后,从设备管理器中,可以看到连接的是哪个串口。
下载固件
Windows 需要有 Python 环境,这里不再赘述如何安装 Python。
固件下载地址:http://www.micropython.org/download/esp8266/
下载:esp8266-20210418-v1.15.bin (elf, map) (latest)
烧录固件
这里采用 esptool 的脚本来进行烧录,esptool 通过 pip 来下载
python -m pip install esptool
通过“设备管理器”确认NodeMCU开发板的连接端口号,然后清除开发板固件信息
python -m esptool --port COM5 erase_flash
最后,刷入 MicroPython 固件
python -m esptool --port COM5 --baud 115200 write_flash --flash_size=detect 0 D:\InstallPackage\esp8266-20210418-v1.15.bin
串口工具连接NodeMCU
可以选择的工具很多,XShell、putty、Windows10的串口调试助手。
参数调整一下,都可以连接成功,选择正确的端口(我这里是COM5),波特率选择115200,其他不用动。点击打开串口,可以出现 python 脚本的界面。
点灯
需要注意的是,NodeMCU Dev kit引脚的编号与Nodemcu的内部GPIO编号不是一个编号。我之前以为板子上的D0对应0,D1对应1,结果怎么都不对。
这里给出映射关系:
NodeMCU开发板Pin | ESP8266 内部 GPIO Pin 编号 |
---|---|
D0 | GPIO16 |
D1 | GPIO5 |
D2 | GPIO4 |
D3 | GPIO0 |
D4 | GPIO2 |
D5 | GPIO14 |
D6 | GPIO12 |
D7 | GPIO13 |
D8 | GPIO15 |
D9/RX | GPIO3 |
D10/TX | GPIO1 |
D11/SD2 | GPIO9 |
D12/SD3 | GPIO10 |
把 LED 正极连接上 D3,负极接地,然后通过命令行点亮 LED,根据上面的表格可以知道,D3 对应 GPIO0
>>> from machine import Pin
>>> led = Pin(0, Pin.OUT)
>>> led.on()
>>> led.off()
on 就是点亮,off 就是熄灭
联网
通过内置的 network 库,可以连接上 WiFi
>>> import network
>>> wlan.connect("djhxiaomi", "0987654321")
>>> wlan.isconnected()
True
DHT11
DHT11 DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5-95%RH, 温度0~+50℃。三个引脚,VCC 接 NodeMCU的3v,GND 接地,信号线接某个引脚,这里我接的是 D2,对应 GPIO4。
>>> import dht
>>> dh = dht.DHT11(machine.Pin(4))
>>> dh.measure()
>>> dh.temperature()
30
>>> dh.humidity()
56
发送请求
通过内置的 urequests 库,可以发送 HTTP 请求,这里简单说下 GET 和 POST
GET
>>> import urequests
>>> response = urequests.get("http://api.com/test")
>>> print(response.text)
POST
>>> import urequests
>>> import json
>>> api_url = "http://api.com/test"
>>> sensor_data = {"name" : "koril", "status" : 100}
>>> headers = {"Content-type" : "application/json"}
>>> response = urequests.post(api_url, data = json.dumps(sensor_data), headers = headers)
>>> print(response.text)
上传代码到NodeMCU
在命令行下一行行编写很麻烦,所以我们可以直接写好代码,上传到 NodeMCU 里,这里用的工具是 MicroPython File Uploader,一个小巧的 GUI 软件
下载地址:https://www.wbudowane.pl/download/
编写好 main.py,文件名一定得是 main.py
import time
from machine import Pin
led = Pin(0, Pin.OUT)
def blink():
while True:
led.on()
time.sleep(1)
led.off()
time.sleep(1)
blink()
然后直接通过软件,打开串口,选中 main.py 文件,直接 send 即可。
将DHT11数据发送到树莓派上
首先 NodeMCU 和树莓派都需要联网,将树莓派当作服务器,接收来自 NodeMCU 的数据,我将树莓派的端口映射到了公网 IP 上,这样 NodeMCU 就可以直接向公网 IP 发送请求,如果没有进行内网穿透,也可以将 NodeMCU 和树莓派置于同一个局域网内,通过局域网来收发数据。
NodeMCU 的 main.py
import network
import urequests
import time
import machine
import dht
import json
dh = dht.DHT11(machine.Pin(4))
# 树莓派上的服务端口
api_url = "http://korilweb.cn:8090/data"
# 因为有时候带到不同的地方,学校,家里,还有公司
# 所以用一个 dict 存放所有的 WiFi 信息
wifi_dict = {
"home" : ["TP-LINK_832B", "sqf1226lhw"],
"phone" : ["djhxiaomi", "0987654321"]
}
# 对某个WiFi进行连接
def do_connect(SSID, PASSWORD):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print("connecting to " + SSID)
wlan.connect(SSID, PASSWORD)
start = time.time()
while not wlan.isconnected():
time.sleep(1)
# 超过5秒,认为连接超时
if time.time() - start > 5:
print("connect timeout!")
break
# 连接成功,返回 True,打印 wlan 信息
if wlan.isconnected():
print('network config:', wlan.ifconfig())
return True
# 连接失败,返回 False
return False
# 对 WiFi 字典进行遍历,某一个连接成功,就发送数据
def connect_wifi(wifi_dict):
for wifi_info in wifi_dict:
is_connected = do_connect(wifi_dict[wifi_info][0], wifi_dict[wifi_info][1])
if is_connected:
time.sleep(1)
while True:
send_data()
time.sleep(1)
print("no wifi")
# 发送传感器数据
def send_data():
tempAndHumidity = getTempAndHumidity()
sensor_data = {
"temperature" : tempAndHumidity[0],
"humidity" : tempAndHumidity[1]
}
headers = {
"Content-Type" : "application/json"
}
response = urequests.post(
api_url,
data = json.dumps(sensor_data),
headers = headers
)
print(response.text)
# 获取 DHT11 的数据,温度和湿度,以元组的形式返回
def getTempAndHumidity():
dh.measure()
return (dh.temperature(), dh.humidity())
connect_wifi(wifi_dict)
树莓派服务端代码
package com.example.raspberry.controller;
import com.example.raspberry.entity.Sensor;
import org.springframework.web.bind.annotation.*;
@RestController
public class HelloController {
@PostMapping(value = "/data")
public String data(@RequestBody Sensor sensor) {
System.out.println("temp: " + sensor.getTemperature());
System.out.println("humidity: " + sensor.getHumidity());
return "get data";
}
}
Sensor 是 DHT11 的类
package com.example.raspberry.entity;
public class Sensor {
// 温度
private Integer temperature;
// 湿度
private Integer humidity;
public Integer getTemperature() {
return temperature;
}
public void setTemperature(Integer temperature) {
this.temperature = temperature;
}
public Integer getHumidity() {
return humidity;
}
public void setHumidity(Integer humidity) {
this.humidity = humidity;
}
@Override
public String toString() {
return "Sensor{" +
"temperature=" + temperature +
", humidity=" + humidity +
'}';
}
}
运行
树莓派上:
java -jar raspberry-0.0.1-SNAPSHOT.jar
然后将 main.py 上传到NodeMCU,可以看到树莓派打印的日志信息,显示了传感器的温湿度。
参考
https://blog.csdn.net/niupipiniupipi/article/details/80956404
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-micropython/micropython-nodemcu-firmware/
https://blog.csdn.net/wzy15965343032/article/details/101768710
http://docs.micropython.org/en/latest/esp8266/quickref.html#
https://www.wbudowane.pl/
https://www.basemu.com/nodemcu-gpio-interface.html