该板子上有两个按键,其中 RST 是用来复位开发板的,而 FLASH 则是在开发板刷固件时需要用到的。
浅蓝色的引脚为通讯引脚,包括 I2C、SPI、UART 等。
黑底白字的引脚是用来操作它内部的存储单元的。 也就是说几个引脚一般不做普通引脚使用。
4.4、通过网页文本框控制 ESP8266 开发板的 PWM 引脚
源文件(下载)链接: http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/spiffs/spiffs-web-server/text-pwm-pin-control/
需要注意,在PWM控制方面,Arduino 开发板的可输入的数值与 ESP8266 的不同, Arduino 只能输入 0 - 255,而 ESP8266 则可以输入 0 - 1023。但是,此处需要重点说明的是,“在 3.0 之前的版本中,默认范围为 0 - 1023”,
参考链接: https://blog.csdn.net/qq_39209508/article/details/120844466
我这里的使用的库是3.0.2版本,所以默认范围就是 0 — 255。 而要想变成 0 - 1023,也很简单,只需要在 setup 函数中添加一句代码 analogWriteRange(1023); 即可。
void setup(void){
...
...
analogWriteRange(1023);
...
}
4.4.1 通过一个网页文本框输入 PWM 数值来控制 PWM 波形
完整代码如下,
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <FS.h>
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
void setup(void){
Serial.begin(9600);
Serial.println("");
pinMode(LED_BUILTIN, OUTPUT);
analogWriteRange(1023);
wifiMulti.addAP("FAST_153C80", "123456798");
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
Serial.println("Connecting ...");
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
if(SPIFFS.begin()){
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
esp8266_server.on("/LED-Control", handleLEDControl);
esp8266_server.onNotFound(handleUserRequest);
esp8266_server.begin();
Serial.println("HTTP server started");
}
void loop(void){
esp8266_server.handleClient();
}
void handleLEDControl(){
String ledPwm = esp8266_server.arg("ledPwm");
int ledPwmVal = ledPwm.toInt();
analogWrite(LED_BUILTIN, ledPwmVal);
String httpBody = "Led PWM: " + ledPwm + "<p><a href=\"/LED.html\"><-LED Page</a></p>";
esp8266_server.send(200, "text/html", httpBody);
}
void handleUserRequest() {
String reqResource = esp8266_server.uri();
Serial.print("reqResource: ");
Serial.println(reqResource);
bool fileReadOK = handleFileRead(reqResource);
if (!fileReadOK){
esp8266_server.send(404, "text/plain", "404 Not Found");
}
}
bool handleFileRead(String resource) {
if (resource.endsWith("/")) {
resource = "/index.html";
}
String contentType = getContentType(resource);
if (SPIFFS.exists(resource)) {
File file = SPIFFS.open(resource, "r");
esp8266_server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
String getContentType(String filename){
if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
运行效果如下,
点击 “前往PWM控制页面” , 输入 0 —— 1023 之间的数,因为 LED的正极接 3.3 V,所以当输入的值越大时, LED 灯两端的压差就越小,也就越暗。
这个设置过程与网络环境有关,网速越快,设置也就越快。 下面,再来重点来分析下这个代码。
void handleLEDControl(){
String ledPwm = esp8266_server.arg("ledPwm");
int ledPwmVal = ledPwm.toInt();
analogWrite(LED_BUILTIN, ledPwmVal);
String httpBody = "Led PWM: " + ledPwm + "<p><a href=\"/LED.html\"><-LED Page</a></p>";
esp8266_server.send(200, "text/html", httpBody);
}
arg 参数是可以通过浏览器这个地址信息中, 通过这个地址信息呢,看有没有和 arg 函数中的参数相匹配的信息,如果有就会把该参数后面的数字获取到。获取到之后将以返回值的形式赋值给 ledPWM 这个字符串变量。
之后,httpBody 是响应体中的信息,也就是, 其中,
<p><a href=\"/LED.html\"><-LED Page</a></p>
代表的含义是一个链接,可以链接到 LED.html 这个页面。
最后,再通过
esp8266_server.send(200, "text/html", httpBody);
把这个响应体通过服务器响应给浏览器,从而浏览器就可以显示出页面的信息了。
下面再把整个流程给理一理。
起初, 网络服务器启动之后,通过串口监视器输出连接成功信息 。
然后,初始化网络服务器,告知系统如何处理/LED-Control请求 和 处理其它网络请求。
esp8266_server.on("/LED-Control", handleLEDControl);
esp8266_server.onNotFound(handleUserRequest);
然后,用户在登录服务器地址之后,在回车之后,向服务器请求资源,然后通过浏览器出现下面页面,
这个页面也就是 index.html 这个网页文件中的内容。
我们使用记事本文件打开这个网页文件看下,这个网页文件的内容。
该网页文件指出,当用户点击“前往PWM控制页面”这个链接之后,就会跳转到 /LED.html 这个网页。从而也就出现下面这个网页内容。
我们再来看下,这个网页文件中是怎么写的。
该网页指出,当点击 /img/taichi-maker.jpg 这个图片时,会跳转到太极创客的官网 http://www.taichi-maker.com,
还有核心的部分: 当用户在这个页面输入设定的数值,然后点击 OK 后,就会执行对应程序中的 handleLEDControl() 的处理内容。
void handleLEDControl(){
String ledPwm = esp8266_server.arg("ledPwm");
int ledPwmVal = ledPwm.toInt();
analogWrite(LED_BUILTIN, ledPwmVal);
String httpBody = "Led PWM: " + ledPwm + "<p><a href=\"/LED.html\"><-LED Page</a></p>";
esp8266_server.send(200, "text/html", httpBody);
}
从而跳转进入 之后,点击链接 < - LED Page 就会回到 /LED.html 这个目录下,需要说明下,“text/html” 是文件类型。
4.4.2 通过多个网页文本框输入 PWM 数值来控制 PWM 波形
void handleLEDControl(){
String value1 = esp8266_server.arg("value1");
String value2 = esp8266_server.arg("value2");
Serial.print("value1 = ");Serial.println(value1);
Serial.print("value2 = ");Serial.println(value2);
String httpBody = "value1: " + value1 + "<br> value2: " + value2 + "<p><a href=\"/LED.html\"><-LED Page</a></p>";
esp8266_server.send(200, "text/html", httpBody);
}
其他地方,没什么变化。流程也一致。不重点说了,用到时再来看。
4.5 (Ajax)控制LED引脚并将A0引脚读数实时显示于网页中
(现在还不懂 Ajax 技术,但已了解其功能。)
在 index.html 中从< script >…< / script >之间的内容就是使用 Ajax 技术实现的内容了。
这段 Ajax 代码的作用就是部分更新网页中的内容,之前的试例程序是网页全部内容重新刷新。
4.6 (JavaScript)通过网页图形界面控制ESP8266的PWM引脚
(现在还不懂 JavaScript 技术,但了解其功能。)
4.7 (JavaScript)使用指针表显示模拟输入引脚数值
(现在还不懂 JavaScript 技术,但了解其功能。)
4.8 通过网页将文件上传到ESP8266开发板闪存文件系统
程序和网页下载链接: http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/spiffs/spiffs-web-server/file-upload-server/
代码如下,
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <FS.h>
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
File fsUploadFile;
void setup() {
Serial.begin(9600);
Serial.println("");
wifiMulti.addAP("FAST_153C80", "123456798");
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
Serial.println("Connecting ...");
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print('.');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
if(SPIFFS.begin()){
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
esp8266_server.on("/upload.html",
HTTP_POST,
respondOK,
handleFileUpload);
esp8266_server.onNotFound(handleUserRequest);
esp8266_server.begin();
Serial.println("HTTP server started");
}
void loop() {
esp8266_server.handleClient();
}
void handleFileUpload(){
HTTPUpload& upload = esp8266_server.upload();
if(upload.status == UPLOAD_FILE_START){
String filename = upload.filename;
if(!filename.startsWith("/")) filename = "/" + filename;
Serial.println("File Name: " + filename);
fsUploadFile = SPIFFS.open(filename, "w");
} else if(upload.status == UPLOAD_FILE_WRITE){
if(fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize);
} else if(upload.status == UPLOAD_FILE_END){
if(fsUploadFile) {
fsUploadFile.close();
Serial.println(" Size: "+ upload.totalSize);
esp8266_server.sendHeader("Location","/success.html");
esp8266_server.send(303);
} else {
Serial.println("File upload failed");
esp8266_server.send(500, "text/plain", "500: couldn't create file");
}
}
}
void respondOK(){
esp8266_server.send(200);
}
void handleUserRequest(){
String webAddress = esp8266_server.uri();
bool fileReadOK = handleFileRead(webAddress);
if (!fileReadOK){
esp8266_server.send(404, "text/plain", "404 Not Found");
}
}
bool handleFileRead(String path) {
if (path.endsWith("/")) {
path = "/index.html";
}
String contentType = getContentType(path);
if (SPIFFS.exists(path)) {
File file = SPIFFS.open(path, "r");
esp8266_server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
String getContentType(String filename){
if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
运行并测试程序: 之后,通过读取文本中的内容来查看是否真的上传成功(代码在前面有介绍),这里不试了。
这里没有代码分析,可直接调用,在后面用到时再来分析代码。
|