废话不多说,直接上代码,这里调用的包是需要提前引入(见后文)的,否则会报错。
网盘链接:WIFImaneger
提取码:wifi
/**********************************************************************
项目:WIFI开关(终端)
功能:自动配网,接受命令/发送数据
@author mansuosuo
***********************************************************************/
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <Servo.h>
// 建立WiFi客户端对象,对象名称client
WiFiClient client;
//连接服务器参数
const String HOST = "192.168.2.136";
const int PORT = 8000;
//舵机参数
Servo myservo; //创建一个舵机控制对象
const int SERVO_PIN = 4; //对应D2
int pos = 0; // 该变量用与存储舵机角度位置
//串口接受数据
String inputString;
void setup() {
// 初始化串口设置
Serial.begin(9600);
// 建立WiFiManager对象
WiFiManager wifiManager;
// 自身WiFi。以下语句的参数是连接ESP8266时的WiFi名称,供首次设置连接
// wifiManager.autoConnect("^_^WIFI UPDATE01", "12345678");
wifiManager.autoConnect("^_^WIFI UPDATE01");
}
void loop() {
// 调用函数
wifiClientRequest();
delay(60000);
}
// 请求并连接到服务器
void wifiClientRequest(){
// 建立字符串,用于HTTP请求
String httpRequest = "ADD::CL001";
// 连接网络服务器
if (client.connect(HOST, PORT)){
client.print(httpRequest); // 向服务器发送HTTP请求
// 通过串口输出网络服务器响应信息
while (client.connected() || client.available()){
readDataFromServer();
}
client.stop(); // 断开与服务器的连接
Serial.print("Disconnected from "); // 并且通过串口输出断开连接信息
Serial.print(HOST);
} else{ // 如果连接不成功则通过串口输出“连接失败”信息
Serial.println(" connection failed!");
client.stop();
}
}
//接受服务器数据并响应
void readDataFromServer(){
while(client.available()){
if (client.read()=='G'){
char a = client.read();
Serial.print(a);
int inNum = (a-48)*20;
// String s = client.readString();
// Serial.print(s);
// int inNum = s.toInt();
// int inNum = client.parseInt();
Serial.print("inNum = ");Serial.println(inNum);
servoGo(inNum);
client.print("OK");
}
delayMicroseconds(5000); //延时等待下一个数据接收到(单位1ms)
}
}
//get缓冲区事件
void readDataFromSerial(){
inputString=""; //清空接收的数据
while(Serial.available()>0){
char inChar = (char)Serial.read(); //每次读取一个字节
if(inChar=='G'){
int inNum = Serial.parseInt(); //每次读取一个字节
servoGo(inNum);
}
delayMicroseconds(5000); //延时等待下一个数据接收到(单位1ms)
inputString +=inChar; //将接收的字节拼接到字符串
}
}
//舵机运行到指定位置
void servoGo(int n){
myservo.attach(SERVO_PIN);
int lastNum = myservo.read();
if(lastNum<n){
for(pos=lastNum; pos<=n; pos+=1){
myservo.write(pos); // 指定舵机转向的角度
delay(5); // 等待15ms让舵机到达指定位置
}
}else{
for(pos=lastNum; pos>=n; pos-=1){
myservo.write(pos); // 指定舵机转向的角度
delay(5); // 等待15ms让舵机到达指定位置
}
}
myservo.detach();
}
配网部分的代码不多说了,这里说说接收服务器的数据问题,我尝试使用readString()方法接入数据,这样读取一个字符串String,也方便我们转换类型,但是问题来了,这个读取速度及其低效,根本实现不了实时控制,几乎收到一条数据需要1.5秒以上。原因就是这里读取的时候是按位读取的ASC码,那么怎末读取比较快呢,当然是直接用read()方法读取,读到的是ASCII码,我这里控制的是9g小舵机,其灵敏度比较低,我在控制的时候间隔为20度就行了,所以直接使用ASCII码做乘法,如果是复杂数据,其实这里可以自己写一个方法:循环按位读取,再将char数组转字符串,也比原来的读取快的多,至于如何类型转换,看下这个不要太简单,主要是两个方法:
1.String类的toCharArray()方法,将字符串转为字符(char)数组
String ss=“abc”;
char[] cc;
cc=ss.toCharArray();
这时cc={‘a’,‘b’,‘c’};
2.String类的valueOf()方法,将字符(char)数组转换为字符串
char[] cc={‘a’,‘b’,‘c’};
ss=String.valueOf(cc);
这时ss=“abc”;
3.字符串转为int使用toInt()方法:
String my_str = "123";
int my_int = my_str.toInt();
如果你看不懂部分代码,那么你需要先了解一下WIFIClient下面的库函数,他们有不同的作用;
我这里放一张图(不是我做的,推荐:https://www.cnblogs.com/liming19680104/p/11227742.html)
最后,把ASC码表也发一下: