I'm having no luck attempting to reconcile my class definitions, with the amount of RAM that disappears when the classes are instantiated. Several of them are consuming VASTLY more RAM than they should. This class compiles for both AVR and ESP targets. Only the AVR (Nano, at present) target is of concern here.
In all cases, ALL "strings" are stored in PROGMEM. There are NO external classes or data instantiated within the class, though one (GaugeConfig) is referenced through a pointer to an instance created within setup(), and passed into the Setup() function of this class. This class does USE a small subset of the FastLED library functionality (addLeds(), fill_solid(), show()) but, AFAICT, FastLED does not appear to use any RAM, other than the LED array, which is contained within the below LEDLighting class instance data.
Based on the class data, this class should consume well under 100 bytes, but according to the compilers memory report, it consumes over 450 bytes as soon as it is instantiated! Where in the world is all that RAM going?? Is there some huge run-time RAM usage (i.e. - stack or heap?) within FastLED???
This is but one example (LEDLighting.h/.cpp):
LEDLighting.h
#pragma once
#include "../types.h"
#include "types.h"
#ifdef ARDUINO_ARCH_ESP8266
// ESP Only
#include "../Config/MasterConfig.h"
#else
// AVR Only
#include "../MemoryFree/MemoryFree.h"
#endif
#include "../Config/GaugeConfig.h"
#include <FastLED.h>
class LEDLighting
{
private:
#define MAX_LEDS 10
GaugeConfig *Cfg = NULL;
CRGB Neo[MAX_LEDS];
gaugeModes curMode = gaugeModes::MODE_OFF;
uint8_t curColor = 0;
uint8_t curBrightness = 0;
gaugeModes nextMode = gaugeModes::MODE_OFF;
uint8_t nextColor = 0;
uint8_t nextBrightness = 0;
uint32_t animationStart = 0;
uint8_t animationStep = 0;
uint8_t gaugeValue = 0;
uint32_t lightingUpdateTime = 0;
public:
LEDLighting() {};
~LEDLighting() {};
void SetColor(uint8_t color, uint8_t bright);
void SetMode(gaugeModes mode, uint8_t color, uint8_t bright);
void SetAutoColor(boolean en);
void SetValue(uint8_t val) { gaugeValue = val; };
void Update(float val);
void Tick(int tick);
void Setup(GaugeConfig *cfg);
};
LEDLighting.cpp
#include "LEDLighting.h"
void LEDLighting::SetColor(uint8_t color, uint8_t bright)
{
//Serial.printf(F("SetColor: color=%d bright=%d\n"), color, bright);
if ((color >= 0) && (color <= 253) && (bright > 0))
{
fill_solid(Neo, Cfg->numLEDs(), CHSV(color,255,bright));
}
else if ((color == 253) || (bright == 0))
{
// Black
fill_solid(Neo, Cfg->numLEDs(), CRGB(0, 0, 0));
}
else
{
// White
fill_solid(Neo, Cfg->numLEDs(), CRGB(bright, bright, bright));
}
curColor = color;
curBrightness = bright;
FastLED.show();
}
void LEDLighting::SetMode(gaugeModes mode, uint8_t color, uint8_t bright)
{
//Serial.printf(F("SetMode0: mode=%d color=%d bright=%d\n"), (int)mode, (int)color, (int)bright);
nextMode = mode;
nextColor = color;
nextBrightness = bright;
//Serial.printf(F("SetMode1: nextMode=%d nextColor=%d nextBrightness=%d\n"), (int)nextMode, (int)nextColor, (int)nextBrightness);
}
void LEDLighting::Update(float val)
{
//Serial.printf(F("Update0: curMode=%d curColor=%d Brightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
boolean busy = false;
// if (Cfg->getAutoColor())
// {
// // FIXME - Check for AutoColor Here!
// curMode = gaugeModes::MODE_AUTOCOLOR;
// }
if ((nextMode != curMode) && (nextMode == gaugeModes::MODE_OFF))
{
// OFF mode takes effect immediately
curMode = nextMode;
curColor = nextColor;
curBrightness = nextBrightness;
}
switch(curMode)
{
case gaugeModes::MODE_OFF:
case gaugeModes::MODE_NORMAL:
// Off mode, so just set lighting
//Serial.printf(F("Update1: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
SetColor(curColor, curBrightness);
break;
// case gaugeModes::MODE_INIT_ANIMATE:
// // Do startup animation here
// busy = true;
// break;
case gaugeModes::MODE_AUTOCOLOR:
// Handle AutoColor Mode
break;
case gaugeModes::MODE_ALERTING:
// Alert animation is handled in Tick()
busy = true;
break;
}
if (!busy)
{
switch(nextMode)
{
case gaugeModes::MODE_OFF:
case gaugeModes::MODE_NORMAL:
//Serial.printf(F("Update2: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
// Normal or Off mode, so just set lighting
curMode = nextMode;
curColor = nextColor;
curBrightness = nextBrightness;
SetColor(curColor, curBrightness);
//Serial.printf(F("Update3: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
break;
// case gaugeModes::MODE_INIT_ANIMATE:
// // Begin startup animation here
// SetColor(Colors::Black, 0);
// animationStart = millis();
// break;
case gaugeModes::MODE_AUTOCOLOR:
// Handle AutoColor Mode
break;
case gaugeModes::MODE_ALERTING:
// Begin alert animation here
//Serial.printf(F("Update4: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
curMode = nextMode;
curColor = nextColor;
curBrightness = nextBrightness;
//SetColor(curColor, curBrightness);
animationStep = 0;
//Serial.printf(F("Update5: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
break;
}
}
}
void LEDLighting::Tick(int tick)
{
// Handle clock ticks here
switch(curMode)
{
case gaugeModes::MODE_OFF:
case gaugeModes::MODE_NORMAL:
case gaugeModes::MODE_INIT_ANIMATE:
// Normal, Off or Animating mode, so nothing to do
break;
case gaugeModes::MODE_ALERTING:
// Update alert animation here
switch (animationStep)
{
case 0:
if (tick)
{
if (nextMode == gaugeModes::MODE_ALERTING)
{
SetColor(0, 255);
animationStep = 1;
}
else
{
curMode = nextMode;
curColor = nextColor;
curBrightness = nextBrightness;
SetColor(curColor, curBrightness);
}
}
break;
case 1:
if (!tick)
{
SetColor(0, 0);
animationStep = 0;
}
break;
default:
break;
}
break;
}
}
void LEDLighting::Setup(GaugeConfig *cfg)
{
Cfg = cfg;
switch(Cfg->ledPin())
{
case 2: // Pin 2, used by all AVR "smart" gauges
//Serial.printf(F("Using pin %d %d LEDs\n"), Cfg->ledPin(), Cfg->numLEDs());
FastLED.addLeds<NEOPIXEL, 2>(Neo, Cfg->numLEDs());
break;
case 3:
//Serial.printf(F("Using pin %d %d LEDs\n"), Cfg->ledPin(), Cfg->numLEDs());
FastLED.addLeds<NEOPIXEL, 3>(Neo, Cfg->numLEDs());
break;
}
fill_solid(Neo, Cfg->numLEDs(), CRGB(100,100,100));
FastLED.show();
//Serial.printf(F("Setup0: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
//Update(0.0);
//Serial.printf(F("Setup1: curMode=%d curColor=%d curBrightness=%d\n"), (int)curMode, (int)curColor, (int)curBrightness);
}
Regards,
Ray L.