这是一年前做的笔记,用WEMOS D1做了一个WIFI温度计。现在又要用到WEMOS D1了,赶紧拿出来温习一下。
相较于UNO R3,由于ESP8266无线网络功能的加持,WEMOS D1和WEMOS D1 mini迅速成为既好玩又实用arduino开发板。虽然价格亲民,在各大电子卖家处都能买到,但市场上的产品良莠不齐,信息混乱,容易让人陷入各种坑。为了避免走弯路,我梳理了一下思路,分享一些入门经验。
★头道关:让arduino IDE支持WEMOS D1
Arduino IDE自带库函数不支持ESP8266,需要打开菜单“文件/首选项”,将开发板添加到IDE里,键入这个地址http://arduino.esp8266.com/stable/package_esp8266com_index.json,点击“好”。
★二道关:选择开发板
在“开发板管理器”,选择“esp8266 by ESP8266 Community”,安装。
如果安装失败,就要下载离线安装包。如果安装过其他版本的esp8266sdk,请先删除,再使用本安装包。删除方法:进入 %LOCALAPPDATA%/Arduino15/packages文件夹,删除掉其中的esp8266文件夹。
百度搜到离线安装包,下载后双击运行即可解压,解压完成后,再打开Arduino IDE,在“菜单栏>工具>开发板”中找到你使用的esp8266开发板。
ESP8266使用版本3.1.1的安装包可能会出现无法上传的问题,改成3.0.2即可。
安装包示例:
★三道关:安装CH340串口驱动。
WEMOS D1官方使用CH340G芯片,它是常用的USB与RSS32串口转换器。驱动程序手头有两种:win11环境下旧的CH341SER.EXE可用,新的官网下载的3.5版没有试。
驱动安装完设备管理器显示如下:
★四道关:点亮板载LED
打开Arduino IDE,先选择工具->开发板->ES8266->LOLIN(Wemos)D1 R1,端口选择上图所示COM3。
然后,打开文件->示例-> LOLIN(Wemos)D1 R1的示例->ESP8266->Blink,编译上传即可。
从代码提示可以看出,板载LED管脚号为2,这与UNO R3的板载LED管脚号13不同。
实际编程时,不要直接用数字编号来标注IO口,要用D??,下图是芯片管脚号与UNO板引脚号对应关系的定义,这是与UNO最大的区别之一。
注意有5对引脚是短路的,即D3=D15、D4=D14、D5=D13、D6=D12、D7=D11。因为ESP8266规格里只有11个数字IO口。板载LED对应D9。为减少不必要的麻烦,程序里只用D0~D10罢了。
还有,除了D0口,都是全功能口(PWM、I2C、OneWire、中断)。模拟输入口只有一个A0。
特别要注意的是,板载LED是低电平点亮,高电平熄灭!这与大部分Arduino开发板不同。
digitalWrite(LED_BUILTIN, LOW);//LED ON
这看原理图可知:
★五道关:测试ESP8266网络功能,获得开发板IP地址
WiFi.mode、WiFi.begin、WiFi.status和init_wifi_sta四个函数是ESP8266WiFi.h里最常用的函数。其中STA模式即终端模式(信号接收模式),将设备变为一个无线网络的客户端。电脑、手机连接WiFi时就用的是STA模式。
#include <ESP8266WiFi.h>
char *ssid = "ssid";
char *passwd = "pass";
void init_wifi_sta()
{
WiFi.mode(WIFI_STA); //设置STA模式
WiFi.begin(ssid,passwd); //连接网络
while(WiFi.status() != WL_CONNECTED) //等待连接
{
Serial.print(".");
delay(500);
}
Serial.println(WiFi.localIP()); //通过串口打印ESP8266的ip地址
}
void setup() {
Serial.begin(9600); //串口初始化,设置波特率9600
init_wifi_sta(); //启动接入wifi
}
void loop() {
}
程序上传成功,ping开发板IP地址成功!
★六道关:启动WebServer功能,让其它设备能访问WEMOS D1
能被ping通只是第一步,要想开发板被访问,需要启用Web Server。示例代码如下:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
const char* ssid = "ssid";
const char* password = "pass";
ESP8266WebServer server(80);
const int led = D9;
void handleRoot() {
digitalWrite(led, 0);
server.send(200, "text/plain", "Hello from esp8266!");
digitalWrite(led, 1);
}
void LedOff() {
digitalWrite(led, HIGH);
server.send(200, "text/plain", "LED...");
}
void LedOn() {
digitalWrite(led, LOW);
}
void handleNotFound(){
digitalWrite(led, 1);
String message = "File Not Foundnn";
message += "URI: ";
message += server.uri();
message += "nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "nArguments: ";
message += server.args();
message += "n";
for (uint8_t i=0; i<server.args(); i++){
message += " " + server.argName(i) + ": " + server.arg(i) + "n";
}
server.send(404, "text/plain", message);
digitalWrite(led, 0);
}
void setup(void){
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.on("/inline", [](){
server.send(200, "text/plain", "this works as well");
});
server.on("/off", LedOff);
server.on("/on", LedOn);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop(void){
server.handleClient();
}
不同于客户端,D1作为服务器需要用到库ESP8266WebServer.h。
ESP8266WebServer - 建立ESP8266WebServer对象,指定访问HTTP服务的端口号,一般是80。
begin() – 启动服务器。启动前先以STA模式连接到WiFi网络,这里只调用WiFi.begin没有调用WiFi.mode,则系统默认使用STA模式。
stop() – 停止服务器。
最关键的是on()函数,只有它可以起到桥梁的作用,将网络指令转成单片机动作的硬件指令。但要注意的是,这座桥是靠函数传递信息的,即on()函数第二个参数传递的是动作函数的地址,是不能带参数的;比如点亮和关闭LED要写两个不同的动作函数,在此server.on("/off", LedOff)和server.on("/on", LedOn)不能写成server.on("/led", Led(on))或server.on("/led", Led(off))。
这个例子上传成功后,浏览器输入“http://板子的IP地址/on”则LED点亮,/off则熄灭。
★七道关:实战DS18B20温度计
DS18B20是一款为单片机设计的温度传感器集成电路,不同于热敏电阻和LM35温度传感器都输出模拟信号而接收端需要进行计算,DS18B20直接输出数字信号的温度值,简单明了,易于使用。
DS18B20有三个引脚,电源、信号输出、地。实际应用时,信号输出端接板子的数字IO口,同时还通过一个4.7k电阻连接电源端。
本示例用D3口连接信号输出端,做一个WiFi温度计,让手机、电脑都能查看温度。
由于外接电路只有两个元件,因此我没用面包板,计划将电阻一端接到D15口,前面讲了,WEMOS D1板子的D3与D15是相连的,因此电阻就连到了DS18B20信号输出端;电阻另一端接5V口,同样的,D1板子有两个5V口,另一个5V正好给传感器供电。
第一次用Frizting画示意图就遇到wemos的一个坑,网上找到一个WEMOS D1的管脚图和我买的不一样,不但IO口错位,还只有一个5V,如下图。
再去找,有目前最常用的D1板子,管脚一致了。由于wemos官网已经没有D1的规格和文档了,查阅其它资料,估计上图是D1 R1版,市面上常用是D1 R2版,如下图。
另外发现,网友aixinaxc说,Wemos板读取DS18B20不需要特意绑定一个电阻。而且5V和3.3V都可以读到数据。但是在5V的时候数据不稳定,所以必须使用3.3V输入。
但是,The Chewett blog表示仍然需要4.7k电阻:“This is also connected to a 4.7k resistor between the data pin and the 3.3 volt line on the breadboard. This pull-up resistor ensures that the line is pulled up when floating.”
由于手头只有一个DS18B20,为保证实验顺利完成,还是用电阻连接3.3V吧。因此后一张电路示意图改了,电阻和传感器都连在同一个3.3V端口上。
DS18B20之所以只用一个管脚进行通讯,靠的是单总线协议,名为OneWire,或1-Wire。与其它两线、三线通讯一样,需要通讯双方握手,原理比较复杂,不用管它, OneWire库已经把复杂功能封装好了,直接用就是了。
从Arduino IDE的库管理菜单,选择OneWire库和DallasTemperature库(包含DS18B20功能)下载即可。
下面示例代码通过串口监视器每隔2秒显示温度。
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into digital pin 2 on the Arduino
#define ONE_WIRE_BUS D3
// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);
void setup(void) {
sensors.begin(); // Start up the library
Serial.begin(9600);
}
void loop(void)
{
// Send the command to get temperatures
sensors.requestTemperatures();
//print the temperature in Celsius
Serial.print("Temperature: ");
Serial.print(sensors.getTempCByIndex(0));
Serial.print("℃\n");
delay(2000);
}
好了,把前面服务端程序与这个传感器程序有机结合起来,就可以做成一个WiFi温度计,手机、电脑输入WEMOS D1开发板的网址就能看到温度了。
参考资料:
https://www.wemos.cc/en/latest/tutorials/d1/get_started_with_arduino_d1.html
https://chewett.co.uk/blog/1412/using-the-ds18b20-temperature-sensor-with-a-wemos-d1-mini-esp8266/