string - 努力让 Arduino Uno 上的 ESP8266 与 AT 通信可靠地工作
问题描述
我正在努力将 ESP8266 连接到作为网络服务器可靠工作的 Arduino Uno。我的 ESP8266 的固件是 1.1.1 - 我目前没有更新它的选项(或知识)。下面是我的代码。如果我提供一个小字符串,它几乎不会起作用。但是,如果我尝试从浏览器加载页面三到四次,它通常会关闭连接或永远加载(崩溃?)。最终,我需要提供一个嵌入了 json 的网页,该网页将加载由 esp8266 提供的第二个页面,一个 json 文件。我有一个工作演示,但在几次检索后它崩溃了。我知道我的 html 页面对于字符串来说太长了,所以一直试图转移到 PROGMEM,最初只用一个短字符串进行测试。我正在正确存储和检索它(我认为,至少我可以Serial.print
它)但是一旦我尝试将其写入 ESP8266,我的浏览器中就会出现永无止境的负载。
我在哪里错了?是导致问题的字符串/PROGMEM 还是我在 AT 命令中缺少的其他内容(例如某种 ping 以保持连接打开)?
//load softserial library
#include <SoftwareSerial.h>
#include <avr/pgmspace.h>
//set a boolean constant variable to true
//#define DEBUG true
const boolean DEBUG = true;
//RX (pin 2) goes to TX on esp8266, TX (pin 3) goes to RX on esp8266
SoftwareSerial esp8266(2, 3);
//input from the photoresistor
//int photoresistorpin = 0;
//create a PROGMEM variable
//String WEBPAGE = "hello";
static const char PROGMEM WEBPAGE[] = {"hello"};
/*
static const char WEBPAGE[] PROGMEM = R"rawliteral(
<html>
<head>
<meta name="viewport" content="width=device-width, minimumscale=1, maximum-scale=1, initial-scale=1">
</head>
<h1>Light:</h1><div id="light"></div>
<script>
function loadDoc()
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
{
var obj = JSON.parse(this.responseText);
document.getElementById('light').innerHTML = obj.data[0].datavalue;
}
};
xhttp.open('GET', 'data.json', true); xhttp.send();
}
var timedEvent = setInterval(function() { loadDoc(); }, 5000);
</script>
</body>
</html>
)rawliteral";
*/
//const int WEBPAGE_len = sizeof(WEBPAGE)/sizeof(WEBPAGE[0]);
void setup()
{
//open the serial port
Serial.begin(115200);
//print setup started in the serial monitor
Serial.println("Setup started");
//start esp8266 module (note: your esp's baud rate might be different)
esp8266.begin(115200);
//reset esp8266 module
senddata("AT+RST\r\n", 2000, DEBUG);
//set esp8266 as access point mode
//1 = Station mode (client)
//2 = Access point mode (host)
//3 = Access point mode + Station mode
senddata("AT+CWMODE=2\r\n", 1000, DEBUG);
//get ip address for esp8266
senddata("AT+CIFSR\r\n", 2000, DEBUG);
//configure esp8266 for multiple connections
senddata("AT+CIPMUX=1\r\n", 1000, DEBUG);
//turn on esp8266 server on port 80
senddata("AT+CIPSERVER=1,80\r\n", 1000, DEBUG);
//setup completed
Serial.println("Setup done");
}
void loop()
{
//take a reading from the photoresistor
//int lightval = analogRead(photoresistorpin);
int lightval = random(1000);
//to test
//Serial.println(lightval);
//is the esp8266 sending a message
if (esp8266.available())
{
//if received data from esp8266
if (esp8266.find("+IPD,"))
{
//subtract 48 because the read() function returns the ASCII decimal
//value and 0 (the first decimal number) starts at 48
int connectionid = esp8266.read() - 48;
//Serial.println("");
//Serial.println("*****");
//Serial.print("string = ");
//read the url sent by the client, look for the variable (/)
String msg;
esp8266.find("/");
delay(100);
msg = esp8266.readStringUntil(' ');
String pathrequested = msg.substring(0);
Serial.println("*****");
Serial.println(pathrequested);
Serial.println("*****");
//create a senddata string to send the webpage to the esp8266
String cipsend = "AT+CIPSEND=" + String(connectionid) + ",";
//cipsend += WEBPAGE.length();
cipsend += strlen_P(WEBPAGE);
cipsend += "\r\n";
Serial.println(cipsend);
char buffer[1000];
strcpy_P(buffer, WEBPAGE);
Serial.println(buffer);
//senddata(cipsend, 500, DEBUG);
//senddata(WEBPAGE, 500, DEBUG);
senddata(buffer, 500, DEBUG);
//create a string closecommand with the connection id and send it
String closecommand = "AT+CIPCLOSE=" + String(connectionid) + "\r\n";
senddata(closecommand, 500, DEBUG);
//increment the count
//count++;
}
}
}
void senddata(String command, const int timeout, boolean debug)
{
//send the received command to the esp8266
esp8266.print(command);
//set int variable to the number of millisends since Arduino began
long int time = millis();
//while the time and the timeout is less than the number of millisends since Arduino began
while((time + timeout) > millis())
{
//while the esp8266 is sending messages
while(esp8266.available())
{
//display output in the serial window
Serial.write(esp8266.read());
}
}
}
解决方案
假设“在我的浏览器中获得永无止境的负载”意味着浏览器中没有显示 - 检查以下内容:
1. 去掉代码中的字符串和字符串构造函数 (+=) 并将其替换为建筑物的固定字符数组的消息。阅读更多:https
://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/
2. 我对 AT 接口的体验是 - 超过 9600 波特不可靠,这不是足以做你想做的事。
3. 如果您的 Esp 模块的最小 512kb(很可能高达 4Mb)在此处托管您的代码,并仅将 UNO 用作来自附加硬件/传感器的信号接收器/发送器。为自己省去很多麻烦和问题 - AT com 的大多数示例都没有真正起作用,而且更令人痛苦。我在 2 天内放弃了 AT 接口,在过去的 4 年中从未错过任何东西。
通过将代码闪烁到 Esp 模块,您还可以完全控制和查看由于调试可能性而发生的事情,您甚至可以在那里的文件系统上托管 html/css/js (LittleFS / SPIFFS)
推荐阅读
- informix - 在 Informix 中设置 sbspace 以保存发送和接收队列
- javascript - 子菜单部分显示
- python - 如何在 python 脚本中将 .obj 文件从搅拌机导入搅拌机游戏引擎
- java - 如何为已经存在的命令创建别名?
- android - WebView 和高级视图未加载特定 URL
- java - 在eclipse中提供自签名证书
- javascript - Flatpickr 初始化失败
- machine-learning - 使用监督学习算法时计算句子极性的方法有哪些?
- roku - Roku DVR Strem Url 视频全长
- node.js - 如何按字符串参数过滤,web3 2.0.0-alpha.1 Solidity 事件?