ESP8266 反复抛出 Exception(0)
ESP8266 repeatedly throws Exception(0)
我正在制作一个带有连接到 Arduino 的称重传感器的物联网称重秤。然后,Arduino 将数据发送到通过串行连接的 ESP8266,该 ESP8266 随后会在 Google 的 Firebase 上更新我的数据库。但是,我的ESP8266启动时抛出异常。一半的时间它工作得很好。当我连接串行电缆时,另一半抛出以下错误。这个错误反复出现,所以我认为它可能是 void loop() 内部的错误,但我似乎无法弄清楚到底是什么问题。另外,我的电缆质量不是最好的,但我不确定这是否会影响什么
Exception (0):
epc1=0x4025803e epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000a depc=0x00000000
>>>stack>>>
ctx: sys
sp: 3fffe0c0 end: 3fffffb0 offset: 01a0
3fffe260: 00000000 00000000 00000000 00000000
3fffe270: 00000000 00000000 00000000 40104b72
3fffe280: 40104b54 3fffc100 0000001a 00000000
3fffe290: 00000000 4025803e 00000000 00000000
3fffe2a0: 400005e1 00000000 00000000 00000000
3fffe2b0: 4025803e 00000033 00000010 00000000
3fffe2c0: 4025803e 40266fd0 00000000 00000001
3fffe2d0: fbf8ffff 04000002 3feffe00 00000100
3fffe2e0: 0000001a 00000018 04000102 40104b54
3fffe2f0: 3fffc100 0000001a 00000000 00000000
3fffe300: 00000000 00000000 00000000 00000000
3fffe310: 00000000 00000000 00000000 00000000
3fffe320: 00000000 00000000 00000000 00000000
3fffe330: 00000000 00000000 00000000 00000000
3fffe340: 00000000 00000000 00000000 00000000
3fffe350: 00000000 00000000 00000000 00000000
3fffe360: 00000000 00000000 00000000 00000000
3fffe370: 00000000 00000000 00000000 00000000
3fffe380: 00000000 00000000 00000000 00000000
3fffe390: 00000000 00000000 00000000 00000000
3fffe3a0: 00000000 00000000 00000000 00000000
3fffe3b0: 00000000 00000000 00000000 00000000
3fffe3c0: 00000000 00000000 00000000 40104b72
3fffe3d0: 40104b54 3fffc100 0000001a 00000000
3fffe3e0: 00000000 4025803e 00000000 00000000
3fffe3f0: 400005e1 00000000 00000000 00000000
3fffe400: 4025803e 00000033 00000010 00000000
3fffe410: 4025803e 40266fd0 00000000 00000001
3fffe420: fbf8ffff 04000002 3feffe00 00000100
3fffe430: 0000001a 00000018 04000102 40104b54
3fffe440: 3fffc100 0000001a 00000000 00000000
3fffe450: 00000000 00000000 00000000 00000000
3fffe460: 00000000 00000000 00000000 00000000
3fffe470: 00000000 00000000 00000000 00000000
3fffe480: 00000000 00000000 00000000 00000000
3fffe490: 00000000 00000000 00000000 00000000
3fffe4a0: 00000000 00000000 00000000 00000000
3fffe4b0: 00000000 00000000 00000000 00000000
3fffe4c0: 00000000 00000000 00000000 00000000
3fffe4d0: 00000000 00000000 00000000 00000000
3fffe4e0: 00000000 00000000 00000000 00000000
3fffe4f0: 00000000 00000000 00000000 00000000
3fffe500: 00000000 00000000 00000000 00000000
3fffe510: 00000000 00000000 00000000 40104b72
3fffe520: 40104b54 3fffc100 0000001a 00000000
3fffe530: 00000000 4025803e 00000000 00000000
3fffe540: 400005e1 00000000 00000000 00000000
3fffe550: 4025803e 00000033 00000010 00000000
3fffe560: 4025803e 40266fd0 00000000 00000001
3fffe570: fbf8ffff 04000002 3feffe00 00000100
3fffe580: 0000001a 00000018 04000102 40104b54
3fffe590: 3fffc100 0000001a 00000000 00000000
3fffe5a0: 00000000 00000000 00000000 00000000
3fffe5b0: 00000000 00000000 00000000 00000000
3fffe5c0: 00000000 00000000 00000000 00000000
3fffe5d0: 00000000 00000000 00000000 00000000
3fffe5e0: 00000000 00000000 00000000 00000000
3fffe5f0: 00000000 00000000 00000000 00000000
3fffe600: 00000000 00000000 00000000 00000000
3fffe610: 00000000 00000000 00000000 00000000
3fffe620: 00000000 00000000 00000000 00000000
3fffe630: 00000000 00000000 00000000 00000000
3fffe640: 00000000 00000000 00000000 00000000
3fffe650: 00000000 00000000 00000000 00000000
3fffe660: 00000000 00000000 00000000 40104b72
3fffe670: 40104b54 3fffc100 0000001a 00000000
3fffe680: 00000000 4025803e 00000000 00000000
3fffe690: 400005e1 00000000 00000000 00000000
3fffe6a0: 4025803e 00000033 00000010 00000000
3fffe6b0: 4025803e 40266fd0 00000000 00000001
3fffe6c0: fbf8ffff 04000002 3feffe00 00000100
3fffe6d0: 0000001a 00000018 04000102 40104b54
3fffe6e0: 3fffc100 0000001a 00000000 00000000
3fffe6f0: 00000000 00000000 00000000 00000000
3fffe700: 00000000 00000000 00000000 00000000
3fffe710: 00000000 00000000 00000000 00000000
3fffe720: 0af8a400 00000001 647a4f3a 00000000
3fffe730: 0af8a400 00000001 647a4f3a 00000000
3fffe740: 00000000 00000000 00000000 00000000
3fffe750: 00000000 00000000 00000000 00000000
3fffe760: 00000000 00000000 00000000 00000000
3fffe770: 00000000 15f14800 000015f1 00004800
3fffe780: 0000c8f4 000215f1 00000000 00000000
3fffe790: c8f49e74 00009e74 00000000 00000000
3fffe7a0: 00000000 00000000 00000000 00000000
3fffe7b0: 00000000 00000000 00000000 40104b72
3fffe7c0: 40104b54 3fffc100 0000001a 00000000
3fffe7d0: 00000000 4025803e 647a4f3a 00000000
3fffe7e0: 400005e1 00000002 000000ad 00000000
3fffe7f0: 4025803e 00000033 00000010 004e11a5
3fffe800: 4025803e 40266fd0 00000000 00000001
3fffe810: fbf8ffff 04000002 3feffe00 00000100
3fffe820: 0000001a 00000018 04000102 40104b54
3fffe830: 3fffc100 0000001a 00000000 00000000
3fffe840: ffffffff 00000000 00000001 00000000
3fffe850: 00005201 00000000 4026492a ffffffff
3fffe860: 00000000 fffffffd 00000000 00000000
3fffe870: 00000000 00000000 00000001 40006545
3fffe880: 00000000 00000000 00000000 40006545
3fffe890: 00000001 00000001 00000000 40006589
3fffe8a0: 00000000 3fffe922 00000000 40264b1e
3fffe8b0: 40264b32 00000001 00000000 00000000
3fffe8c0: 3fffe8d3 00000000 00000000 40006545
3fffe8d0: 000005e0 3fffe918 3ffef288 40226a30
3fffe8e0: 00000608 00000000 00000000 00000000
3fffe8f0: 00000000 00000020 402532c3 00000001
3fffe900: ffffffff 00000000 3ffe8e91 40104b72
3fffe910: 40104b54 3fffc100 0000001a 00000000
3fffe920: 00000000 4025803e 00000020 401001a4
3fffe930: 400005e1 00000000 00000000 401015bc
3fffe940: 4025803e 00000033 00000010 3ffed11c
3fffe950: 4025803e 40266fd0 00000000 00000001
3fffe960: fbf8ffff 04000002 3feffe00 00000100
3fffe970: 0000001a 00000018 04000102 40104b54
3fffe980: 3fffc100 0000001a 00000000 00000000
3fffe990: 00000000 00000002 3ffee8a0 402660a3
3fffe9a0: c0266089 7fffffff 00000002 40211114
3fffe9b0: 3ffe8765 00000002 3ffee898 4026608a
3fffe9c0: 00000000 7fffffff 3fff17ec 3ffed29c
3fffe9d0: 00000000 3ffeea48 3ffe8765 40222cde
3fffe9e0: 3fffea00 3ffeea1c 3ffe8765 3ffeea78
3fffe9f0: 3ffe8765 3ffeea9c 3ffe8765 40222cde
3fffea00: 3fffea20 3ffeebb4 3ffeeb24 3ffed29c
3fffea10: 3ffe8765 00000000 3ffee678 402063e8
3fffea20: 40247cf1 00000000 3ffeeaa8 402037d8
3fffea30: ffffffff 00000000 3ffeeaa8 402109af
3fffea40: 00000000 00000000 00000001 401001a4
3fffea50: 3ffedffc 3ffee028 3ffe8abc 40104b72
3fffea60: 40104b54 3fffc100 0000001a 00000000
3fffea70: 00000000 4025803e 00000001 402587be
3fffea80: 400005e1 00001000 40104e0d 000003fd
3fffea90: 4025803e 00000033 00000010 00000000
3fffeaa0: 4025803e 40266fd0 00000000 00000001
3fffeab0: fbf8ffff 04000002 3feffe00 00000100
3fffeac0: c_⸮⸮rS⸮
这是我在 ESP8266 上的代码。对于任何不良的编程习惯,我深表歉意。
#include <ESP8266WiFi.h>
#include <FirebaseESP8266.h>
//Hidden for security
#define WIFINAME
#define WIFIPASSWORD
#define BAUTRATE 9600
#define FIREBASE_HOST
#define FIREBASE_COMMAND_ADDRESS
#define FIREBASE_AUTH
WiFiClientSecure client;
FirebaseData firebaseData;
unsigned long previousTime;
String firebaseWriteAddress;
String firebaseReadAddress;
String weight; // Stored in a string to accomodate the "loading" text
bool maxWRead;
bool minWRead;
bool displayPrefRead;
bool instructedToConnectWifi;
void readWeights(){
// function to read the min and max weights, then send to Arduino
if (!maxWRead){
String maxWAddress = firebaseReadAddress + "/Product/MaxW";
if (Firebase.get(firebaseData,maxWAddress)){
if (firebaseData.dataType() == "string"){
String maxWMessage = "max:"+ firebaseData.stringData();
Serial.println(maxWMessage);
maxWRead = true;
}
}
}
if (!minWRead){
String minWAddress = firebaseReadAddress + "/Product/MinW";
if (Firebase.get(firebaseData,minWAddress)){
if (firebaseData.dataType() == "string"){
String minWMessage = "min:"+ firebaseData.stringData();
Serial.println(minWMessage);
minWRead = true;
}
}
}
}
void readDisplayPref(){
String displayAddress = firebaseReadAddress + "/Display";
if (Firebase.get(firebaseData,displayAddress)){
if (firebaseData.dataType() == "string"){
String displayMessage = "dsp:"+ firebaseData.stringData();
Serial.println(displayMessage);
displayPrefRead = true;
}
}
}
void sendFireBase(){
// function to send data to Firebase Real-time Database
Firebase.setString(firebaseData, firebaseWriteAddress,weight);
}
void readFireBase(){
Firebase.begin(FIREBASE_HOST,FIREBASE_AUTH);
if(Firebase.get(firebaseData, FIREBASE_COMMAND_ADDRESS)){
if (firebaseData.dataType() == "string"){
String data = firebaseData.stringData();
String command = data.substring(0,4);
if (command == "read"){
firebaseReadAddress = "/UserData/" + data.substring(4);
readWeights();
firebaseWriteAddress = "/UserData/" + data.substring(4)
+ "/Weight";
}
}
}
}
void connectWifi(){
WiFi.begin(WIFINAME, WIFIPASSWORD);
byte wifiCounter = 0;
// Allow some buffer time to connect to WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(100);
wifiCounter ++;
if (wifiCounter > 50){
// tries for 5 sec.
break;
}
}
if (WiFi.status() == WL_CONNECTED){
Serial.print("WiFi Connected!\n");
instructedToConnectWifi = true;
}
else {
Serial.print("Can't Connect. Trying Again\n");
connectWifi();
}
}
void readArd(){
// function to read Serial inputs from arduino
String message = Serial.readStringUntil('\n');
if (message == "ConnectWifi"){
connectWifi();
}
else{
weight = message;
// stores weight without the percentage sign. Only stores if its within 0-100
sendFireBase();
}
}
void setup() {
Serial.begin(BAUTRATE);
previousTime = millis();
maxWRead = false;
minWRead = false;
displayPrefRead = false;
instructedToConnectWifi = false;
}
void loop() {
if (Serial.available()){
readArd();
}
if (instructedToConnectWifi){
// if wifi disconnects halfway, auto connect back
if (WiFi.status() != WL_CONNECTED){
connectWifi();
}
}
unsigned long currentTime = millis();
if (currentTime - previousTime >2000){
// cycles every 2 sec to prevent spam
// TODO: fix overflow problem (49 days) if it becomes product
if (instructedToConnectWifi){
if (!minWRead || !maxWRead){
// stop once max and min has been read
readFireBase();
previousTime = currentTime;
}
else {
readDisplayPref();
previousTime = currentTime;
}
}
}
}
分析这些异常后得到以下结果:
Exception 0: Illegal instruction
深入研究错误会发现:
std::basic_string , std::allocator >::basic_string(char const*, std::allocator const&)
此错误模式是字符串 class 的典型错误模式。
用固定的字符数组替换所有字符串(不是动态创建的(!))
原因:字符串 class 会破坏堆,导致 ESP 崩溃(8266 和 ESP32)。
为什么会这样?因为我们在WiFi场景(IoT)中使用它们(与"normal" Arduinos相反,达到99%。所以内存中发生了很多事情。
怎么办?去掉String class (和 delay() 如果使用)
String firebaseWriteAddress;
String firebaseReadAddress;
String weight; // Stored in a string to accomodate the "loading" text
以上这些与(动态定义的字符串变量)等函数结合
String data = firebaseData.stringData();
String command = data.substring(0,4);
if (command == "read"){
firebaseReadAddress = "/UserData/" + data.substring(4);
readWeights();
firebaseWriteAddress = "/UserData/" + data.substring(4)
+ "/Weight";
将确保 ESP 非常快速地崩溃。由于没有垃圾收集器(并且无论如何都没有足够的内存),您在某个时候写入占用的内存 - 请参阅我的错误分析的第一行 - 崩溃。
为什么要使用固定字符? - 它们被编译到闪存中,您大部分时间都使用指针进行操作。所以所有 "fixed" 条短信都进入 flash(示例)
char firebaseReadAddress[64] = {'[=14=]'}; //Takes 63 chars
像
一样使用
strcpy(firebaseReadAddress, "/UserData/");
strcat(firebaseReadAddress, dataContent);
要检查字符数组是否以 "read" 开头,您可以使用此方法:
if (strncmp( command, "read", 4) == 0) { /** Compare the first 4 characters - returns 0 if they are equal */
处理与 String class 一样简单,但它让您的应用程序 运行 永远(至少只要有电源)
检查还使用了库大量使用字符串(尤其是当它们不是专用于 ESP 时)。如果他们这样做 - 抛弃它们或重写它们;-)
firebase lib 是一个积极的例子,没有使用动态字符串和大量使用 char 数组。
抱歉坏消息
如果你想要一个稳定的应用程序,请重写你的程序,如果有特殊问题,我可以帮助你 - 请在这里发表评论。
我正在制作一个带有连接到 Arduino 的称重传感器的物联网称重秤。然后,Arduino 将数据发送到通过串行连接的 ESP8266,该 ESP8266 随后会在 Google 的 Firebase 上更新我的数据库。但是,我的ESP8266启动时抛出异常。一半的时间它工作得很好。当我连接串行电缆时,另一半抛出以下错误。这个错误反复出现,所以我认为它可能是 void loop() 内部的错误,但我似乎无法弄清楚到底是什么问题。另外,我的电缆质量不是最好的,但我不确定这是否会影响什么
Exception (0):
epc1=0x4025803e epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000a depc=0x00000000
>>>stack>>>
ctx: sys
sp: 3fffe0c0 end: 3fffffb0 offset: 01a0
3fffe260: 00000000 00000000 00000000 00000000
3fffe270: 00000000 00000000 00000000 40104b72
3fffe280: 40104b54 3fffc100 0000001a 00000000
3fffe290: 00000000 4025803e 00000000 00000000
3fffe2a0: 400005e1 00000000 00000000 00000000
3fffe2b0: 4025803e 00000033 00000010 00000000
3fffe2c0: 4025803e 40266fd0 00000000 00000001
3fffe2d0: fbf8ffff 04000002 3feffe00 00000100
3fffe2e0: 0000001a 00000018 04000102 40104b54
3fffe2f0: 3fffc100 0000001a 00000000 00000000
3fffe300: 00000000 00000000 00000000 00000000
3fffe310: 00000000 00000000 00000000 00000000
3fffe320: 00000000 00000000 00000000 00000000
3fffe330: 00000000 00000000 00000000 00000000
3fffe340: 00000000 00000000 00000000 00000000
3fffe350: 00000000 00000000 00000000 00000000
3fffe360: 00000000 00000000 00000000 00000000
3fffe370: 00000000 00000000 00000000 00000000
3fffe380: 00000000 00000000 00000000 00000000
3fffe390: 00000000 00000000 00000000 00000000
3fffe3a0: 00000000 00000000 00000000 00000000
3fffe3b0: 00000000 00000000 00000000 00000000
3fffe3c0: 00000000 00000000 00000000 40104b72
3fffe3d0: 40104b54 3fffc100 0000001a 00000000
3fffe3e0: 00000000 4025803e 00000000 00000000
3fffe3f0: 400005e1 00000000 00000000 00000000
3fffe400: 4025803e 00000033 00000010 00000000
3fffe410: 4025803e 40266fd0 00000000 00000001
3fffe420: fbf8ffff 04000002 3feffe00 00000100
3fffe430: 0000001a 00000018 04000102 40104b54
3fffe440: 3fffc100 0000001a 00000000 00000000
3fffe450: 00000000 00000000 00000000 00000000
3fffe460: 00000000 00000000 00000000 00000000
3fffe470: 00000000 00000000 00000000 00000000
3fffe480: 00000000 00000000 00000000 00000000
3fffe490: 00000000 00000000 00000000 00000000
3fffe4a0: 00000000 00000000 00000000 00000000
3fffe4b0: 00000000 00000000 00000000 00000000
3fffe4c0: 00000000 00000000 00000000 00000000
3fffe4d0: 00000000 00000000 00000000 00000000
3fffe4e0: 00000000 00000000 00000000 00000000
3fffe4f0: 00000000 00000000 00000000 00000000
3fffe500: 00000000 00000000 00000000 00000000
3fffe510: 00000000 00000000 00000000 40104b72
3fffe520: 40104b54 3fffc100 0000001a 00000000
3fffe530: 00000000 4025803e 00000000 00000000
3fffe540: 400005e1 00000000 00000000 00000000
3fffe550: 4025803e 00000033 00000010 00000000
3fffe560: 4025803e 40266fd0 00000000 00000001
3fffe570: fbf8ffff 04000002 3feffe00 00000100
3fffe580: 0000001a 00000018 04000102 40104b54
3fffe590: 3fffc100 0000001a 00000000 00000000
3fffe5a0: 00000000 00000000 00000000 00000000
3fffe5b0: 00000000 00000000 00000000 00000000
3fffe5c0: 00000000 00000000 00000000 00000000
3fffe5d0: 00000000 00000000 00000000 00000000
3fffe5e0: 00000000 00000000 00000000 00000000
3fffe5f0: 00000000 00000000 00000000 00000000
3fffe600: 00000000 00000000 00000000 00000000
3fffe610: 00000000 00000000 00000000 00000000
3fffe620: 00000000 00000000 00000000 00000000
3fffe630: 00000000 00000000 00000000 00000000
3fffe640: 00000000 00000000 00000000 00000000
3fffe650: 00000000 00000000 00000000 00000000
3fffe660: 00000000 00000000 00000000 40104b72
3fffe670: 40104b54 3fffc100 0000001a 00000000
3fffe680: 00000000 4025803e 00000000 00000000
3fffe690: 400005e1 00000000 00000000 00000000
3fffe6a0: 4025803e 00000033 00000010 00000000
3fffe6b0: 4025803e 40266fd0 00000000 00000001
3fffe6c0: fbf8ffff 04000002 3feffe00 00000100
3fffe6d0: 0000001a 00000018 04000102 40104b54
3fffe6e0: 3fffc100 0000001a 00000000 00000000
3fffe6f0: 00000000 00000000 00000000 00000000
3fffe700: 00000000 00000000 00000000 00000000
3fffe710: 00000000 00000000 00000000 00000000
3fffe720: 0af8a400 00000001 647a4f3a 00000000
3fffe730: 0af8a400 00000001 647a4f3a 00000000
3fffe740: 00000000 00000000 00000000 00000000
3fffe750: 00000000 00000000 00000000 00000000
3fffe760: 00000000 00000000 00000000 00000000
3fffe770: 00000000 15f14800 000015f1 00004800
3fffe780: 0000c8f4 000215f1 00000000 00000000
3fffe790: c8f49e74 00009e74 00000000 00000000
3fffe7a0: 00000000 00000000 00000000 00000000
3fffe7b0: 00000000 00000000 00000000 40104b72
3fffe7c0: 40104b54 3fffc100 0000001a 00000000
3fffe7d0: 00000000 4025803e 647a4f3a 00000000
3fffe7e0: 400005e1 00000002 000000ad 00000000
3fffe7f0: 4025803e 00000033 00000010 004e11a5
3fffe800: 4025803e 40266fd0 00000000 00000001
3fffe810: fbf8ffff 04000002 3feffe00 00000100
3fffe820: 0000001a 00000018 04000102 40104b54
3fffe830: 3fffc100 0000001a 00000000 00000000
3fffe840: ffffffff 00000000 00000001 00000000
3fffe850: 00005201 00000000 4026492a ffffffff
3fffe860: 00000000 fffffffd 00000000 00000000
3fffe870: 00000000 00000000 00000001 40006545
3fffe880: 00000000 00000000 00000000 40006545
3fffe890: 00000001 00000001 00000000 40006589
3fffe8a0: 00000000 3fffe922 00000000 40264b1e
3fffe8b0: 40264b32 00000001 00000000 00000000
3fffe8c0: 3fffe8d3 00000000 00000000 40006545
3fffe8d0: 000005e0 3fffe918 3ffef288 40226a30
3fffe8e0: 00000608 00000000 00000000 00000000
3fffe8f0: 00000000 00000020 402532c3 00000001
3fffe900: ffffffff 00000000 3ffe8e91 40104b72
3fffe910: 40104b54 3fffc100 0000001a 00000000
3fffe920: 00000000 4025803e 00000020 401001a4
3fffe930: 400005e1 00000000 00000000 401015bc
3fffe940: 4025803e 00000033 00000010 3ffed11c
3fffe950: 4025803e 40266fd0 00000000 00000001
3fffe960: fbf8ffff 04000002 3feffe00 00000100
3fffe970: 0000001a 00000018 04000102 40104b54
3fffe980: 3fffc100 0000001a 00000000 00000000
3fffe990: 00000000 00000002 3ffee8a0 402660a3
3fffe9a0: c0266089 7fffffff 00000002 40211114
3fffe9b0: 3ffe8765 00000002 3ffee898 4026608a
3fffe9c0: 00000000 7fffffff 3fff17ec 3ffed29c
3fffe9d0: 00000000 3ffeea48 3ffe8765 40222cde
3fffe9e0: 3fffea00 3ffeea1c 3ffe8765 3ffeea78
3fffe9f0: 3ffe8765 3ffeea9c 3ffe8765 40222cde
3fffea00: 3fffea20 3ffeebb4 3ffeeb24 3ffed29c
3fffea10: 3ffe8765 00000000 3ffee678 402063e8
3fffea20: 40247cf1 00000000 3ffeeaa8 402037d8
3fffea30: ffffffff 00000000 3ffeeaa8 402109af
3fffea40: 00000000 00000000 00000001 401001a4
3fffea50: 3ffedffc 3ffee028 3ffe8abc 40104b72
3fffea60: 40104b54 3fffc100 0000001a 00000000
3fffea70: 00000000 4025803e 00000001 402587be
3fffea80: 400005e1 00001000 40104e0d 000003fd
3fffea90: 4025803e 00000033 00000010 00000000
3fffeaa0: 4025803e 40266fd0 00000000 00000001
3fffeab0: fbf8ffff 04000002 3feffe00 00000100
3fffeac0: c_⸮⸮rS⸮
这是我在 ESP8266 上的代码。对于任何不良的编程习惯,我深表歉意。
#include <ESP8266WiFi.h>
#include <FirebaseESP8266.h>
//Hidden for security
#define WIFINAME
#define WIFIPASSWORD
#define BAUTRATE 9600
#define FIREBASE_HOST
#define FIREBASE_COMMAND_ADDRESS
#define FIREBASE_AUTH
WiFiClientSecure client;
FirebaseData firebaseData;
unsigned long previousTime;
String firebaseWriteAddress;
String firebaseReadAddress;
String weight; // Stored in a string to accomodate the "loading" text
bool maxWRead;
bool minWRead;
bool displayPrefRead;
bool instructedToConnectWifi;
void readWeights(){
// function to read the min and max weights, then send to Arduino
if (!maxWRead){
String maxWAddress = firebaseReadAddress + "/Product/MaxW";
if (Firebase.get(firebaseData,maxWAddress)){
if (firebaseData.dataType() == "string"){
String maxWMessage = "max:"+ firebaseData.stringData();
Serial.println(maxWMessage);
maxWRead = true;
}
}
}
if (!minWRead){
String minWAddress = firebaseReadAddress + "/Product/MinW";
if (Firebase.get(firebaseData,minWAddress)){
if (firebaseData.dataType() == "string"){
String minWMessage = "min:"+ firebaseData.stringData();
Serial.println(minWMessage);
minWRead = true;
}
}
}
}
void readDisplayPref(){
String displayAddress = firebaseReadAddress + "/Display";
if (Firebase.get(firebaseData,displayAddress)){
if (firebaseData.dataType() == "string"){
String displayMessage = "dsp:"+ firebaseData.stringData();
Serial.println(displayMessage);
displayPrefRead = true;
}
}
}
void sendFireBase(){
// function to send data to Firebase Real-time Database
Firebase.setString(firebaseData, firebaseWriteAddress,weight);
}
void readFireBase(){
Firebase.begin(FIREBASE_HOST,FIREBASE_AUTH);
if(Firebase.get(firebaseData, FIREBASE_COMMAND_ADDRESS)){
if (firebaseData.dataType() == "string"){
String data = firebaseData.stringData();
String command = data.substring(0,4);
if (command == "read"){
firebaseReadAddress = "/UserData/" + data.substring(4);
readWeights();
firebaseWriteAddress = "/UserData/" + data.substring(4)
+ "/Weight";
}
}
}
}
void connectWifi(){
WiFi.begin(WIFINAME, WIFIPASSWORD);
byte wifiCounter = 0;
// Allow some buffer time to connect to WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(100);
wifiCounter ++;
if (wifiCounter > 50){
// tries for 5 sec.
break;
}
}
if (WiFi.status() == WL_CONNECTED){
Serial.print("WiFi Connected!\n");
instructedToConnectWifi = true;
}
else {
Serial.print("Can't Connect. Trying Again\n");
connectWifi();
}
}
void readArd(){
// function to read Serial inputs from arduino
String message = Serial.readStringUntil('\n');
if (message == "ConnectWifi"){
connectWifi();
}
else{
weight = message;
// stores weight without the percentage sign. Only stores if its within 0-100
sendFireBase();
}
}
void setup() {
Serial.begin(BAUTRATE);
previousTime = millis();
maxWRead = false;
minWRead = false;
displayPrefRead = false;
instructedToConnectWifi = false;
}
void loop() {
if (Serial.available()){
readArd();
}
if (instructedToConnectWifi){
// if wifi disconnects halfway, auto connect back
if (WiFi.status() != WL_CONNECTED){
connectWifi();
}
}
unsigned long currentTime = millis();
if (currentTime - previousTime >2000){
// cycles every 2 sec to prevent spam
// TODO: fix overflow problem (49 days) if it becomes product
if (instructedToConnectWifi){
if (!minWRead || !maxWRead){
// stop once max and min has been read
readFireBase();
previousTime = currentTime;
}
else {
readDisplayPref();
previousTime = currentTime;
}
}
}
}
分析这些异常后得到以下结果:
Exception 0: Illegal instruction
深入研究错误会发现:
std::basic_string , std::allocator >::basic_string(char const*, std::allocator const&)
此错误模式是字符串 class 的典型错误模式。
用固定的字符数组替换所有字符串(不是动态创建的(!))
原因:字符串 class 会破坏堆,导致 ESP 崩溃(8266 和 ESP32)。
为什么会这样?因为我们在WiFi场景(IoT)中使用它们(与"normal" Arduinos相反,达到99%。所以内存中发生了很多事情。
怎么办?去掉String class (和 delay() 如果使用)
String firebaseWriteAddress;
String firebaseReadAddress;
String weight; // Stored in a string to accomodate the "loading" text
以上这些与(动态定义的字符串变量)等函数结合
String data = firebaseData.stringData();
String command = data.substring(0,4);
if (command == "read"){
firebaseReadAddress = "/UserData/" + data.substring(4);
readWeights();
firebaseWriteAddress = "/UserData/" + data.substring(4)
+ "/Weight";
将确保 ESP 非常快速地崩溃。由于没有垃圾收集器(并且无论如何都没有足够的内存),您在某个时候写入占用的内存 - 请参阅我的错误分析的第一行 - 崩溃。
为什么要使用固定字符? - 它们被编译到闪存中,您大部分时间都使用指针进行操作。所以所有 "fixed" 条短信都进入 flash(示例)
char firebaseReadAddress[64] = {'[=14=]'}; //Takes 63 chars
像
一样使用 strcpy(firebaseReadAddress, "/UserData/");
strcat(firebaseReadAddress, dataContent);
要检查字符数组是否以 "read" 开头,您可以使用此方法:
if (strncmp( command, "read", 4) == 0) { /** Compare the first 4 characters - returns 0 if they are equal */
处理与 String class 一样简单,但它让您的应用程序 运行 永远(至少只要有电源)
检查还使用了库大量使用字符串(尤其是当它们不是专用于 ESP 时)。如果他们这样做 - 抛弃它们或重写它们;-)
firebase lib 是一个积极的例子,没有使用动态字符串和大量使用 char 数组。
抱歉坏消息
如果你想要一个稳定的应用程序,请重写你的程序,如果有特殊问题,我可以帮助你 - 请在这里发表评论。