第一次发帖... 我通常使用 ATMEGA 328P 编程,但最近开始使用 D1 Mini ESP8266。我写了一个我认为相当简单的程序。我在 IDE 的 VSCode 中使用 PlatformIO。 我关心的是程序使用的静态 RAM 的数量。 内存统计: 内存区域使用大小 区域大小 %age Used dport0_0_seg:0 GB 16 B 0.00% dram0_0_seg:33872 B 80 KB 41.35% irom0_0_seg:492260 B 1044464 B 47.13% ** iram1_0_seg:27804 B 32 KB 84.85%** 检索最大程序大小 .pio uild\d1_mini irmware.elf 检查大小 .pio uild\d1_mini irmware.elf 高级内存使用可通过“PlatformIO Home > Project Inspect”获得 RAM:[====] 41.3%(使用了 81920 字节中的 33812 字节) 闪存:[=====] 50.4%(使用了 1044464 字节中的 526682 字节) 构建 .pio uild\d1_mini irmware.bin
我在328P上好像没遇到过这个问题。我正在寻找有关此问题的一些反馈或减少 IRAM 使用的提示或技巧。 PROGMEM 没有帮助。
提前致谢。
史蒂夫
#ifndef Arduino_h
#include <Arduino.h>
#endif
#ifndef WiFi_h
#include <ESP8266WiFi.h>
#endif
#ifndef ESP_MAIL_CLIENT_H
#include <ESP_Mail_Client.h>
#endif
#ifndef creditials_h
#include <creditials.h>
#endif
#ifndef localWifi_h
#include <localWifi.h>
#endif
#ifndef getTime_h
#include <getTime.h>
#endif
#ifndef _Time_h
#include <TimeLib.h>
#endif
#ifndef WIFIUDP_H
#include <WiFiUdp.h>
#endif
#ifndef global_h
#include <global.h>
#endif
#ifndef TimFlsh_h
#include "TimerFlasher.h"
#endif
// instantate methods
GetTime M_getTime;
LocalWiFi M_WiFi;
L_Global M_Global;
TimFlsh M_TimFlsh;
// global variable
long unsigned millisSeconds = 1000;
int cnt = 0;
int machHasRun [2] = {_Off, _Off }; //indicates that a mach as started
bool machAllReadyOn [2] = {false, false};
int whichMachCase [2] = { 0, 0 };
/*
D3 INPUT: Washer running, pulled low when on.
D4 INPUT: Dryer running, pulled low when on.
D5 OUTPUT: pull low to turn on Washer ON LED.
D6 OUTPUT: pull low to turn on Dryer ON LED.
D7 OUTPUT: pull low to turn on Send E-mail LED.
*/
int machOnIO [2] = { D3, D4 }; // mach on / off IO
int machLEDIO [2] = { D5, D6 }; // LED on/off IO
int emailLED = D7;
bool wait [2] = {false, false};
long unsigned OffDelayPrevMillis [2] = {0,0};
long unsigned OffDelayInterval [2] = {60 * millisSeconds, 60 * millisSeconds};
long unsigned EmailDelayPrevMillis [2] = {0,0};
long unsigned EmailDelayInterval [2] = {30 * millisSeconds, 30 * millisSeconds};
bool oneSecond [2] = {true, true};
long unsigned oneSecondPrevMillis [2] = {0,0};
long unsigned oneSecondInterval [2] = {1 * millisSeconds, 1 * millisSeconds};
bool EmailOK;
//forward declare
bool SendEmail (int cnt);
void setup()
{
pinMode(machOnIO[WASHER], INPUT_PULLUP); //washer on/off
pinMode(machOnIO[DRYER], INPUT_PULLUP); //dryer on/off
pinMode(machLEDIO[WASHER], OUTPUT); //washer power LED
pinMode(machLEDIO[DRYER], OUTPUT); // dryer LED
pinMode(emailLED, OUTPUT); // sending e-mail indiacator
#if TEST
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(9600);
Serial.println("Setup complete:");
digitalWrite(LED_BUILTIN,I_Off); // turn off on board led
#endif
} //end setup
//==========================================================================================================================
// main loop A. loop through machines to see if running
// b. loop on case for each machine
// case 1. start cycle, set machine to running, when detect off, prepare to delay
// case 2. delay off of machine cycle to assure this is not a user interrupt (door opened),
// return to case 1 if starts running again before delay expires
// case 3. machine confirmed off, send an e-mail. if email fails stay in case 3, send again after delay, try 3 times
// return to A
//==========================================================================================================================
void loop()
{ // check if a machine is running
for (int loop = WASHER; loop <= DRYER; loop++ ) // Washer = 0, Dryer = 1
{
oneSecond[loop] = (M_TimFlsh.oneSecondDelay(loop, oneSecond, oneSecondPrevMillis, oneSecondInterval));
if (digitalRead(machOnIO[loop]) == I_On and machAllReadyOn[loop] == false ) // machine On and not detected before
{
digitalWrite(machLEDIO[loop], I_On); // turn on proper cycle LED
whichMachCase[loop] = START_CYCLE; // set switch/case
#if TEST
if(loop == WASHER){digitalWrite(BUILTIN_LED,I_On);}
#endif
} //end if
} // end for
//============================================================================================
for (int loop = WASHER; loop <= DRYER; loop++ ) // check all machines
{
//What to do
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
switch(whichMachCase[loop])
{
//---------------------------------------------------------------------------------------
case START_CYCLE: // check for end of cycle or user invocked stop
{
#if TEST
Serial.println("Case START_CYCLE " + M_Global.name[loop]);
#endif
machAllReadyOn[loop] = true; // set proper machine to on
if(digitalRead(machOnIO[loop]) == HIGH) // ck mach off IO
{
OffDelayPrevMillis[loop] = millis(); // set start time for current machine for the off delay
whichMachCase[loop] = DELAYOFF; // move to next case
}
break;
} // END CASE Start_cycle
//-------------------------------------------------------------------------------------------
case DELAYOFF: // make sure cyce is over and not just a user interruption "off delay timer"
{
#if TEST
Serial.println("Case DELAYOFF " + M_Global.name[loop]);
#endif
if(M_TimFlsh.ckOffDelayTime(loop, OffDelayPrevMillis[loop], OffDelayInterval[loop])) // true when timed out
{
digitalWrite(machLEDIO[loop], I_Off); // turn off cycle LED
#if TEST
digitalWrite(BUILTIN_LED,I_Off);
#endif
wait[loop] = false;
whichMachCase[loop] = SENDMAIL; // move to next case
}
else if (oneSecond[loop])
{ // waiting for timeout
machAllReadyOn[loop] = false;
M_TimFlsh.flashLED(machLEDIO[loop]);
}
break;
} // END CASE DelayOFf
//-----------------------------------------------------------------------------------
case SENDMAIL: // time to send the e-mail
{
#if TEST
Serial.println("Case SENDEMAIL " + M_Global.name[loop]);
#endif
if(wait[loop]) // prior e-mail failed, wait to send a replacment
{
{wait[loop] = M_TimFlsh.ckEmailDelay(loop, EmailDelayPrevMillis[loop], OffDelayInterval[loop]);}
}
else
{
digitalWrite(emailLED, I_On);
EmailOK = SendEmail(loop);
EmailDelayPrevMillis[loop] = millis(); // set start time for e-mail delay
if (EmailOK)
{
machAllReadyOn[loop] = false;
wait[loop] = false;
whichMachCase[loop] = 0;
digitalWrite(emailLED, I_Off);
}
else if (!EmailOK)
{
M_TimFlsh.fastBlinkLED(emailLED);
wait[loop] = true;
}
}
} // END CASE SendEmail
//-----------------------------------------------------------------------------------------------
default:
{
break;
} // END DEFAULT
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
} //END SWITCH
//====================================================================================================
} // END FOR LOOP
} // end loop()
//==================================================================
// Send e-mail and get the status
//==================================================================
bool SendEmail(int cnt)
{
bool EmailFail = false;
int WiFiOK = M_WiFi.connect_WiFi();
if (WiFiOK == WL_CONNECTED)
{
String Dtmsg = M_getTime.NST_Time();
String Emsg = M_Global.msg[cnt];
bool EmailOK = M_WiFi.send_Email(Dtmsg, Emsg, "ESP8266 machine monitoring", cnt);
if(EmailOK)
{
#if TEST
Serial.println("Email OK");
#endif
M_WiFi.discon_Wifi();
return EmailOK;
} //end if emailOK
else
{
M_WiFi.discon_Wifi();
#if TEST
Serial.println("Email Failed");
#endif
return EmailFail;
} // end else emailok
}
#if TEST
Serial.println("Email Failed");
#endif
return EmailFail;
}
我试过使用 PROGMEM 将数据移动到程序内存中。大多数数据是 String 类型,编译器不允许将它们移动到程序内存。