这个标题很容易解释,就像我在Exception 28 thrown on ESP8266-01 when connected to Adafruit MQTT and Telegram上发布的另一个问题一样
有人可能会说这是同样的问题,但实际上这是它的后续,我认为这是一个独立的问题,因为它也可能帮助其他人,而且在其他互联网上也没有真正涉及到。我还将发布我的全部代码(就像我在前一个问题上所做的那样),尽管StackOverflow建议只发布最小值来复制错误,因为我觉得完全复制错误是需要的。(私有数据改为私有数据)
#include "UniversalTelegramBot.h"
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>
#define BOTtoken "PRIVATE"
#define fanPin 2
#define myChatId "PRIVATE"
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "PRIVATE"
#define AIO_KEY "PRIVATE"
char ssid[] = "PRIVATE";
char password[] = "PRIVATE";
bool fanState;
unsigned long lastTimeBotRan = 0;
unsigned long checkTime = 1000;
int numNewMessages;
unsigned long timerStartPoint = 0;
bool timerStart;
String chat_id;
String text;
int messagesNumber;
String timerString;
String Request;
const unsigned long rst = 300000;
boolean MQTT_connect();
WiFiClientSecure telegramClient;
WiFiClient MQTTClient;
UniversalTelegramBot bot(BOTtoken, telegramClient);
Adafruit_MQTT_Client mqtt(&MQTTClient, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Subscribe PRIVATE = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/PRIVATE");
void checkUpdates(int numNewMessages) {
for (int i = 0; i < numNewMessages; i++) {
chat_id = String(bot.messages[i].chat_id);
text = bot.messages[i].text;
String from_name = bot.messages[i].from_name;
if (chat_id != myChatId) {
bot.sendMessage(chat_id, "Unauthorized user, please refrain from texting this bot again.", "");
continue;
}
if (text == "/start") {
bot.sendMessage(chat_id, "Welcome " + from_name + "!\n"
"Control your fan remotely!\n\n"
"/fanon: switch the fan ON\n"
"/fanoff: switch the fan OFF\n"
"/state: get the current state of the fan"
"/timer15: run fan for 15 minutes"
"/timer30: run fan for 30 minutes"
"/timer60: run fan for 1 hour"
"/timer: run fan for the amount of time you specify", "Markdown");
}
if (text == "/fanon") {
digitalWrite(fanPin, HIGH);
Serial.println("Fan on");
fanState = true;
bot.sendMessage(chat_id, "Your fan is ON", "");
}
if (text == "/fanoff") {
fanState = false;
timerStart = false;
digitalWrite(fanPin, LOW);
Serial.println("Fan off");
bot.sendMessage(chat_id, "Your fan is OFF", "");
}
if (text == "/state") {
if (digitalRead(2) == HIGH) {
bot.sendMessage(chat_id, "Your fan is ON", "");
} else {
bot.sendMessage(chat_id, "Your fan is OFF", "");
}
}
if (text == "/timer15") {
timerStartPoint = millis();
digitalWrite(fanPin, HIGH);
timerStart = true;
Serial.print("(/timer15) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(chat_id, "Your fan will run for 15 minutes", "");
launchTimer(15);
}
if (text == "/timer30") {
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(/timer30) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(chat_id, "Your fan will run for 30 minutes", "");
launchTimer(30);
}
if (text == "/timer60") {
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(/timer60) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(chat_id, "Your fan will run for 1 hour", "");
launchTimer(60);
}
if (text == "/timer") {
messagesNumber = bot.last_message_received + 1;
bot.sendMessage(chat_id, "How long do you want the fan to run for? (in minutes)", "");
Serial.println(messagesNumber);
while (messagesNumber == (bot.last_message_received + 1)) {
checkUpdates(bot.getUpdates(bot.last_message_received + 1));
timerString = bot.messages[i].text;
yield();
}
if (messagesNumber < (bot.last_message_received + 1)) {
unsigned long timer = timerString.toInt();
Serial.println(timer);
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(/timer) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(chat_id, "Your fan will run for " + timerString + " minutes", "");
launchTimer(timer);
}
}
text = "";
}
}
void launchTimer(unsigned long timeInMinutes) {
unsigned long timeInMillis = timeInMinutes * 60 * 1000;
while (timerStart) {
checkUpdates(bot.getUpdates(bot.last_message_received + 1));
if (MQTT_connect()) {
Adafruit_MQTT_Subscribe *subscription_name;
while ((subscription_name = mqtt.readSubscription(4000))) {
if (subscription_name == &PRIVATE) {
Request = ((char *)PRIVATE.lastread);
if (Request == "fanon") {
digitalWrite(fanPin, HIGH);
Serial.println("(Control panel) Fan on");
fanState = true;
bot.sendMessage(myChatId, "Fan turned on through Control Panel", "");
}
if (Request == "fanoff") {
fanState = false;
timerStart = false;
Serial.println("(Control panel) Fan off");
digitalWrite(fanPin, LOW);
bot.sendMessage(myChatId, "Fan turned off through Control Panel", "");
}
if (Request == "timer15") {
timerStartPoint = millis();
digitalWrite(fanPin, HIGH);
timerStart = true;
Serial.print("(CP /timer15) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(myChatId, "Fan turned on for 15 minutes through Control Panel", "");
launchTimer(15);
}
if (Request == "timer30") {
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(CP /timer30) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(myChatId, "Fan turned on for 30 minutes through Control Panel", "");
launchTimer(30);
}
if (Request == "timer60") {
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(CP /timer60) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(myChatId, "Fan turned on for 1 hour through Control Panel", "");
launchTimer(60);
}
}
}
}
if (millis() - timerStartPoint > timeInMillis) {
digitalWrite(fanPin, LOW);
timerStart = false;
Serial.print("Timer run out at ");
Serial.println(millis());
bot.sendMessage(myChatId, "Fan turned off because timer ran out", "");
}
yield();
}
}
boolean MQTT_connect() {
int8_t ret;
if (mqtt.connected()) {
return true;
} uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) {
mqtt.disconnect();
delay(2000);
retries--;
if (retries == 0) {
return false;
}
} return true;
}
void setup() {
Serial.begin(115200);
telegramClient.setInsecure();
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.print("Connecting Wifi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
pinMode(fanPin, OUTPUT);
delay(10);
digitalWrite(fanPin, LOW);
Request = "";
mqtt.subscribe(&PRIVATE);
if (MQTT_connect()) {
Serial.println("mqtt connected");
}
else {
Serial.println("mqtt connection failed");
}
}
void loop() {
if (millis() - lastTimeBotRan > checkTime) {
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages) {
checkUpdates(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
lastTimeBotRan = millis();
}
delay(1000);
if (MQTT_connect()) {
Adafruit_MQTT_Subscribe *subscription_name;
while ((subscription_name = mqtt.readSubscription(4000))) {
if (subscription_name == &PRIVATE) {
Request = ((char *)PRIVATE.lastread);
if (Request == "fanon") {
digitalWrite(fanPin, HIGH);
Serial.println("(Control panel) Fan on");
fanState = true;
bot.sendMessage(myChatId, "Fan turned on through Control Panel", "");
}
if (Request == "fanoff") {
fanState = false;
timerStart = false;
Serial.println("(Control panel) Fan off");
digitalWrite(fanPin, LOW);
bot.sendMessage(myChatId, "Fan turned off through Control Panel", "");
}
if (Request == "timer15") {
timerStartPoint = millis();
digitalWrite(fanPin, HIGH);
timerStart = true;
Serial.print("(CP /timer15) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(myChatId, "Fan turned on for 15 minutes through Control Panel", "");
launchTimer(15);
}
if (Request == "timer30") {
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(CP /timer30) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(myChatId, "Fan turned on for 30 minutes through Control Panel", "");
launchTimer(30);
}
if (Request == "timer60") {
digitalWrite(fanPin, HIGH);
timerStart = true;
timerStartPoint = millis();
Serial.print("(CP /timer60) Fan on at ");
Serial.println(timerStartPoint);
bot.sendMessage(myChatId, "Fan turned on for 1 hour through Control Panel", "");
launchTimer(60);
}
}
}
}
if (!mqtt.ping()) {
mqtt.disconnect();
}
}现在,问题是:我想实例化WiFiClient (连接到Adafruit )和WiFiClientSecure (连接到我的Telegram bot),而不以崩溃告终,然后是一个异常28堆栈跟踪(我已经在链接的另一个问题中发布了一个“正常”和解码版本)。我知道,经过几个小时的研究,我无法实例化WiFiClientSecure的两个实例,因为它将超过ESP01上可用的堆,而且我还知道,仅WiFiClient或仅WiFiClientSecure就不会碰巧抛出所述异常。
我没有发现WiFiClient和WiFiClientSecure不能一起使用,但是我可能遗漏了什么。因此,我的问题是:是否可以在相同的代码中同时使用WiFiClient和WiFiClientSecure,用于两个不同的目的(分别是MQTT和WiFiClientSecure)?
我期待着阅读任何一条建议,因为我目前对想法无所适从。提前感谢每一个愿意帮忙的人。
编辑:对于任何感兴趣的人,以下是我的最新发现:
更新:发现问题并更改标题。问题完全在于这两个库的堆使用。这两个库都使用大量的堆空间,过一段时间就会耗尽,导致异常28,因为,据我所知,ESP试图从其内存的错误部分读取,导致它崩溃。我将在3分钟内附加堆的串行输出:
41552
19448
20008
20120
20312
20200
20120
20120
20120
20312
20120
20120
20120
20312
20312
20312
20312
20312
20312
20504
20312
20312
19640如您所见,第一个实例的堆显示超过40k,这是正常的,因为51kish是最大值。然后它跳到20000,然后就用完了,尽管ESP在几分钟后恢复了它自己的内存。
发布于 2021-01-07 10:54:00
在我的WiFiClient多传感器检查和发布项目中,我也使用了WiFiClientSecure和ESP8266。虽然我的WifiClient一直在运行(对于MQTT和ThingSpeak),但我决定将安全连接(为了更少地发布到GoogleSheets --每30分钟一次)进行连接。整个项目代码太大(有5570行),下面是其中的一部分,其中有一些注释介绍了堆的使用情况:
// heap size before call of the function: 37112
int SendGSCRPT() {
showHeap(); // 35312
WiFiClientSecure GoogleClient;
showHeap(); // 27512
GoogleClient.setInsecure();
if (!GoogleClient.connect("script.google.com", 443)) {
GoogleClient.stop();
return 0;
}
showHeap(); // 9840 !!!
char sGog[200];
snprintf(sGog, sizeof(sGog), "GET %s HTTP/1.1\r\nHost: script.google.com\r\nUser-Agent: PRIVATE\r\nConnection: close\r\n\r\n", "PRIVATE");
GoogleClient.print(sGog);
Serial.println("request sent!");
int res = 1;
GoogleClient.stop();
showHeap(); // 30104
return res;
}
// heap size after function releases all the memory taken: 37112 again !!!https://stackoverflow.com/questions/63396210
复制相似问题