在阅读本篇文章之前,你已经阅读了:
软硬结合-导读 本篇学习内容
认识、购买NodeMCU开发板
安装Arduino IDE、ESP8266扩展开发板
实现NodeMCU开发板LED灯闪烁例子
实现NodeMCU开发板串口通信的例子
本篇视频
NodeMCU简介 NodeMCU本质就是把ESP8266的引脚都引出来,配合USB转串口芯片,使其能快速开发验证想法。 在我的毕业设计里,ESP8266模块只是充当WIFI通信模块的作用,只做消息转发不做业务处理,传感器与STM32通信,STM32再与ESP8266模块通信。而在这个教程里,使用NodeMCU,省去了STM32这个中间商,传感器与STP8266直接相连,此时ESP8266芯片既是WIFI通信芯片,也做业务处理。NodeMCU的引脚如下:
淘宝价大约在十几块钱,如果是第一次玩硬件,自己没有USB线的话,记得还要额外买 一条线 :
先买一块NodeMCU(超便宜的,最便宜十几块钱就能在淘宝上买到),安装驱动精灵(用于安装串口驱动的),安装Arduino-1.8版本以上Arduino1.8.7(百度网盘)
特别注意:NodeMCU分V2与V3版本(非官方承认),两者略有不同,其中V3略便宜且LED引脚略有不同,写代码需要另外定义引脚:#define LED_BUILTIN 2
。别问我买哪个版本的,买便宜的那一个!!!(好像是V3便宜些)
验证硬件是否正常 把NodeMCU接上USB线插上电脑,如果发现没有识别到端口的话,可能是线有问题,也有可能是板子有问题。如果你怀疑是板子有问题,请联系客服要求换货。 在演示时我的新电脑没有提示,如果需要安装串口驱动可看以下的视频。USB转串口芯片有些用cpXX,有些是CHxx,插上NodeMCU后让驱动精灵来安装对应驱动即可。
使用Arduino编程 这里演示一下开发环境的搭建以及最简demo。
搭建开发环境 安装Arduino-1.8版本以上Arduino1.8.7(百度网盘) (安装过程一直next就是,我就不录视频了),配置ESP8266扩展开发板网址并安装SDK。(我已经配置并安装了,你们自行安装一下,安装过程可能会比较慢。)扩展开发板网址:http://arduino.esp8266.com/stable/package_esp8266com_index.json
。但由于不可描述的原因,一般是安装失败的,可请看另一文章进行解决:Arduino开发板管理安装失败解决办法 。
验证一下是否已经安装扩展SDK,如果烧录程序时提示ESP8266WiFi.h:No such file or directory
,基本就代表没有安装或选择扩展。
安装完扩展开发板信息后,记得选择开发板为NodeMCU 1.0
。如果连接上开发板并可以看到开发板信息,说明连接正常,可以编程了。拿到开发板的第一件事,就是跑个例程,证明硬件是没问题的。 我们接下来要做的事就是,通过代码把开发板上的LED闪烁起来,证明板子没问题。然后就是实践串口通信收发消息与验证连接WIFI的功能。
例程 控制LED NodeMCU板LED灯闪烁。 特别注意:NodeMCU分V2与V3版本,两者略有不同,其中V3的LED引脚略有不同,写代码需要另外定义引脚:#define LED_BUILTIN 2
,即把第二行代码取消注释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void setup () { pinMode(LED_BUILTIN, OUTPUT); } void loop () { digitalWrite(LED_BUILTIN, LOW); delay(1000 ); digitalWrite(LED_BUILTIN, HIGH); delay(2000 ); }
串口通信 展示一个定时串口打印信息的简单demo。Arduino串口信息窗口:IDE菜单栏->工具->串口监视器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void setup () { Serial.begin(115200 ); delay(10 ); Serial.println(); Serial.println(); Serial.print("Connecting to " ); } void loop () { Serial.println("WiFi connected" ); delay(1000 ); }
TCP通信-串口打印 演示中使用到的网络调试助手-百度网盘 ,自行安装。 注意根据实际情况 修改WIFI的标识号与密码(第3、4行),与TCP服务器的IP地址、端口号(第6、7行) ,注意部分学校校园网是需要登陆学生帐号密码的,所以是用不了的,可以用手机发热点来代替。 演示中使用了网络调试助手开启了TCP服务器,0.0.0.0
代表的是本机所有的IP地址,如果127.0.0.1
的话,则只允许本机的程序连接。2424
端口对应着程序的代码端口。新手注意,中英文的区别:127.0.0.1
不要写成了中文的符号成了:127。0。0。1
,这样子是不行的,中文符号是新手经常导致异常的误操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <ESP8266WiFi.h> const char * ssid = "you-wifi" ;const char * password = "you-wifi-password" ;const char * host = "192.168.1.121" ;const int port = 2424 ;WiFiClient client; void setup () { Serial.begin(115200 ); delay(10 ); Serial.println(); Serial.print("Connecting to " ); Serial.println(ssid); WiFi.begin(ssid, password); client.setTimeout(100 ); while (WiFi.status() != WL_CONNECTED) { delay(500 ); Serial.print("." ); } Serial.println("" ); Serial.println("WiFi connected" ); } void loop () { if (client.connect(host, port)) { Serial.println("client connected to the host" ); client.println("hello~" ); } else { Serial.println("client connection failure" ); } while (client.connected()) { delay(1000 ); client.println("tick" ); if (client.available()) { String line = client.readStringUntil('\n' ); Serial.print("receive:" ); Serial.println(line); } } }
DHT11(可选学) 在我做的教程里,本来是通过程序生成随机数来模拟“从温度传感器上拿到的数据”,从而省少了温度传感器的费用。当然,有部分读者会觉得不踏实,不完整,所以有读者把连接DHT11,并把代码分享出来了。温湿度传感器DHT11总共有三个引脚(电源、数据、地),电源与地分别接NodeMCU的VCC(或3.3V)与地线,数据线所接引脚要与代码相符合。感谢该读者提供了相关的代码供大家参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <dht11.h> dht11 DHT11; #define DHT11_PIN 13 void setup () { Serial.println("init" ); } void loop () { int chk = DHT11.read(DHT11_PIN); Serial.print("Temperature=" ); Serial.println(DHT11.temperature); Serial.print("Humidity=" ); Serial.println(DHT11.humidity); delay(1000 ); }
要使用<dht11.h>
,就要装第三方库或自行手动添加以下库文件,Arduino IDE 库文件如何添加? ,将库文件放到至Arduino IDE 所在文件夹的libraries文件夹中,如(/arduino/libraries):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #ifndef dht11_h #define dht11_h #if defined(ARDUINO) && (ARDUINO >= 100) #include <Arduino.h> #else #include <WProgram.h> #endif #define DHT11LIB_VERSION "0.4.1" #define DHTLIB_OK 0 #define DHTLIB_ERROR_CHECKSUM -1 #define DHTLIB_ERROR_TIMEOUT -2 class dht11 { public : int read (int pin) ; int humidity; int temperature; }; #endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 #include "dht11.h" int dht11::read (int pin) { uint8_t bits[5 ]; uint8_t cnt = 7 ; uint8_t idx = 0 ; for (int i=0 ; i< 5 ; i++) bits[i] = 0 ; pinMode(pin, OUTPUT); digitalWrite(pin, LOW); delay(18 ); digitalWrite(pin, HIGH); delayMicroseconds(40 ); pinMode(pin, INPUT); unsigned int loopCnt = 10000 ; while (digitalRead(pin) == LOW) if (loopCnt-- == 0 ) return DHTLIB_ERROR_TIMEOUT; loopCnt = 10000 ; while (digitalRead(pin) == HIGH) if (loopCnt-- == 0 ) return DHTLIB_ERROR_TIMEOUT; for (int i=0 ; i<40 ; i++) { loopCnt = 10000 ; while (digitalRead(pin) == LOW) if (loopCnt-- == 0 ) return DHTLIB_ERROR_TIMEOUT; unsigned long t = micros(); loopCnt = 10000 ; while (digitalRead(pin) == HIGH) if (loopCnt-- == 0 ) return DHTLIB_ERROR_TIMEOUT; if ((micros() - t) > 40 ) bits[idx] |= (1 << cnt); if (cnt == 0 ) { cnt = 7 ; idx++; } else cnt--; } humidity = bits[0 ]; temperature = bits[2 ]; uint8_t sum = bits[0 ] + bits[2 ]; if (bits[4 ] != sum) return DHTLIB_ERROR_CHECKSUM; return DHTLIB_OK; }
如何区分不同类型的数据(扩展补充) 那么问题来了,在demo中,我是使用程序生成模拟数来模拟温度的,所以我可以直接发数值,后端程序默认都当成是温度来处理:
但现在接上硬件后发现其实数据是两种,除了温度还有湿度,就要区分开来,如何区分在于看我们怎么定义,我们可以这么定义:
1 2 3 4 5 6 Temperature=24 Humidity=30 Temperature=25 Humidity=31 Temperature=26 Humidity=32
同时后端接收到这样的数据时,也要做对应的处理,JS可以使用
split()
函数来拆解字符串,代码例子:
1 2 3 4 5 6 7 8 9 let humidityValue = 0 let temperatureValue = 0 const valueString = 'Humidity=30' const arr = valueString.split('=' ) if (arr[0 ] === 'Humidity' ){ humidityValue = arr[1 ] }else if (arr[0 ] === 'Temperature' ){ temperatureValue = arr[1 ] }
当然,这样定义还是有问题,主要在于要上传的字节太多,在商业的角度来看就是浪费流量,成本高。所以为了省流量,一般都是用字节,比如说我可以传
1 2 3 0x2430 // 0x2430 是十六进制的写法,转换成二进制就是 0010 0100 0011 0000 0x2531 0x2632
一个字节有八位,有两个数值,我可以把其中四位当作温度值十位,其中四位当作温度值的个位,这样温度值只花了一个字节,湿度值同理也只使用了一个字节,组合起来共使用了两个字节而已。更进一步地,这个在商用上还存在着一个扩展性差的问题,在工业界流行使用TVL格式(type,value,length),自行搜索学习,点到即止,不再深入扩展。
硬件知识其实只用到了,点灯,串口通信,网络通信这几块,所以这里就很简单地带过,这些知识就已经足够完成本教程的内容了。有些读者想学习更多关于硬件的知识,其它读者分享的太极创客 《零基础入门学用Arduino教程》 ,大家可以去学习。
FAQ
错误提示:ESP8266WiFi.h:No such file or directory?答:说明没有安装ESP8266扩展开发板信息或者没选择NodeMCU开发板,导致找不到相关文件。
在开发板管理器安装esp8266 by ES8266 Community 十分缓慢,有其它办法吗?答:有解决办法,请看Arduino开发板管理安装失败解决办法
哪里可以看到API文档? 答:
附录