Esphome compile error in the scripted main.cpp

Adafruit is still trying to sell flexible 16 x 16 LED matraces for $95 each. You can buy them directly from China for less than $9. I now have 36 16 x 16 LED matraces. I am trying to combine two programming projects into one ESPHome/Home Assistant project. First, I found this tricky little callback program for custom components at https://loopylab.de/. I got it working with Home Assistant very easily. I find it interesting that it is not necessary to register the component with the “app” object. Perhaps because the component only receives information and does not provide it.

Second, just for kicks, I have been playing around with Arduino, PlatformIO, FastLED, LEDMatrix, Adafruit NeoMatrix, Adafruit GFX, Arduino GFX, etc., for almost a year without ESPHome or Home Assistant. I would like to combine all of these together and have a wireless LED panel matrix automatically turn on and off, display the date, sunrise and sunset times with graphics. Right now I use an Athom wall plug with Home Assistant to turn the 3 x 3 tiled matrix on and off. No time and date, little bitmaps, sunrise and sunset information.

I am trying to make my PlatformIO/Arduino project into an ESPHome Custom Component that works with Home Assistant. First, I struggled with adding two more callbacks for Home Assistant text sensors holding sunrise and sunset data. Second, I worked out the proper order for loading the libraries in the EspHome YAML file. The only problem left is the compilation error when PlatformIO starts to compile the ESPHome scripted main.cpp file.

Here is my code and the error message:

cst-cmpnt.yaml:

> esphome:
>   name: cst-cmpnt
>   friendly_name: cst-cmpnt
>   includes:
>     - "LEDMatrixCmpnt.h"
>   libraries:
>     - "Wire"
>     - "SPI"
>     - "fastled/FastLED"
>     - "Adafruit BusIO"
>     - "Adafruit GFX Library"
>     - "Framebuffer GFX"
>     - "FastLED NeoMatrix"
> 
> esp32:
>   board: esp32-s3-devkitc-1
>   framework:
>     type: arduino
> 
> logger:
> 
> api:
> 
>   encryption:
>     key: "RBk7GAee8EMXAxo="
> 
> ota:
>   password: ""
> 
> wifi:
>   ssid: !secret wifi_ssid
>   password: !secret wifi_password
> 
>   # Enable fallback hotspot (captive portal) in case wifi connection fails
>   ap:
>     ssid: "Cst-Cmpnt Fallback Hotspot"
>     password: "U3BPl"
> 
> captive_portal:
> 
> number:
>   - platform: template
>     name: "Frequency"
>     id: blink_frequency
>     optimistic: true
>     min_value: 0.1
>     max_value: 100
>     step: 0.1
>     restore_value: true
> 
> switch:
>   - platform: template
>     name: "Enable"
>     id: panel_enable
>     optimistic: true
>     restore_mode: RESTORE_DEFAULT_OFF
> 
> text_sensor:
>   - platform: homeassistant
>     name: "Sun Rise"
>     entity_id: sensor.sun_next_rising
>     id: sun_rise
>   - platform: homeassistant
>     name: "Sun Set"
>     entity_id: sensor.sun_next_setting
>     id: sun_set
> 
> custom_component:
> - lambda: |-
>     auto myMatrix = new LEDMatrixCmpnt(id(panel_enable), id(blink_frequency), id(sun_rise), 
>             id(sun_set));
>     return {myMatrix};

LEDMatrixCmpnt.h:

> #include "esphome.h"
> #include <FastLED.h>
> #include <Adafruit_GFX.h>
> #include <FastLED_NeoMatrix.h>
> 
> #define LED_PIN    38
> #define LED_PIN2   15
> #define PIN        13
> 
> #define BRIGHTNESS 45
> 
> #define mw         48
> #define mh         48
> 
> #define NUMMATRIX (mw * mh)
> 
> #define LED_BLACK   0
> #define LED_RED_VERYLOW   (3 <<  11)
> #define LED_RED_LOW       (7 <<  11)
> #define LED_RED_MEDIUM    (15 << 11)
> #define LED_RED_HIGH      (31 << 11)
> #define LED_GREEN_VERYLOW (1 <<  5)  
> #define LED_GREEN_LOW     (15 << 5)  
> #define LED_GREEN_MEDIUM  (31 << 5)  
> #define LED_GREEN_HIGH    (63 << 5)  
> #define LED_BLUE_VERYLOW   3
> #define LED_BLUE_LOW       7
> #define LED_BLUE_MEDIUM   15
> #define LED_BLUE_HIGH     31
> 
> #define LED_GOLD            (0xFF80)
> #define LED_ORANGE_VERYLOW  (LED_RED_VERYLOW + LED_GREEN_VERYLOW)
> #define LED_ORANGE_LOW    (LED_RED_LOW     + LED_GREEN_LOW)
> #define LED_ORANGE_MEDIUM (LED_RED_MEDIUM  + LED_GREEN_MEDIUM)
> #define LED_ORANGE_HIGH   (LED_RED_HIGH    + LED_GREEN_HIGH)
> #define LED_PURPLE_VERYLOW  (LED_RED_VERYLOW + LED_BLUE_VERYLOW)
> #define LED_PURPLE_LOW      (LED_RED_LOW     + LED_BLUE_LOW)
> #define LED_PURPLE_MEDIUM   (LED_RED_MEDIUM  + LED_BLUE_MEDIUM)
> #define LED_PURPLE_HIGH     (LED_RED_HIGH    + LED_BLUE_HIGH)
> #define LED_CYAN_VERYLOW  (LED_GREEN_VERYLOW + LED_BLUE_VERYLOW)
> #define LED_CYAN_LOW      (LED_GREEN_LOW     + LED_BLUE_LOW)
> #define LED_CYAN_MEDIUM   (LED_GREEN_MEDIUM  + LED_BLUE_MEDIUM)
> #define LED_CYAN_HIGH     (LED_GREEN_HIGH    + LED_BLUE_HIGH)
> #define LED_WHITE_VERYLOW (LED_RED_VERYLOW + LED_GREEN_VERYLOW + LED_BLUE_VERYLOW)
> #define LED_WHITE_LOW     (LED_RED_LOW     + LED_GREEN_LOW     + LED_BLUE_LOW)
> #define LED_WHITE_MEDIUM  (LED_RED_MEDIUM  + LED_GREEN_MEDIUM  + LED_BLUE_MEDIUM)
> #define LED_WHITE_HIGH    (LED_RED_HIGH    + LED_GREEN_HIGH    + LED_BLUE_HIGH)
> 
> CRGB leds[NUMMATRIX];
> 
> FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, 16, 16, 3, 3,
>     NEO_MATRIX_BOTTOM     + NEO_MATRIX_RIGHT +
>     NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG +
>     NEO_TILE_BOTTOM + NEO_TILE_RIGHT + NEO_TILE_COLUMNS +  NEO_TILE_ZIGZAG
>   );
> 
> class LEDMatrixCmpnt : public Component
> {
> public:
>   unsigned long last_led_change;
>   bool enable = false;
>   float frequency = 1;
>   std::string sun_rise, sun_set, last_sunrise, last_sunset;
> 
>   LEDMatrixCmpnt(esphome::template_::TemplateSwitch *&_enable,
>                 esphome::template_::TemplateNumber *&_frequency,
>                 esphome::homeassistant::HomeassistantTextSensor *&_sunrise,
>                 esphome::homeassistant::HomeassistantTextSensor *&_sunset)
>   {
>     _enable->add_on_state_callback([this](bool newState) { enable = newState; });
>     _frequency->add_on_state_callback([this](float newFrequency) { frequency = newFrequency; });
>     _sunrise->add_on_state_callback([this](std::string newSunrise)
>     {
>       last_sunrise = sun_rise;
>       sun_rise = newSunrise;
>     });
>     _sunset->add_on_state_callback([this](std::string newSunset)
>     {
>       last_sunset = sun_set;
>       sun_set = newSunset;
>     });
>   }
> 
>   void setup() override
>   {
>     pinMode(LED_PIN, OUTPUT);
>     pinMode(LED_PIN2, OUTPUT);
>     digitalWrite(LED_PIN2, HIGH);
>     last_led_change = millis();
>     FastLED.addLeds<NEOPIXEL,PIN>(leds, NUMMATRIX).setCorrection(TypicalSMD5050);
>     matrix->begin();
>     matrix->setTextWrap(false);
>     matrix->setBrightness(BRIGHTNESS);
>   }
>   void loop() override
>   {
>     if (enable == false)
>     {
>       return;
>     }
>     unsigned long now = millis();
>     if (last_led_change + 1000 / frequency  < now)
>     {
>       digitalWrite(LED_PIN, !digitalRead(LED_PIN));
>       digitalWrite(LED_PIN2, !digitalRead(LED_PIN2));
>       last_led_change = now;
>     }
>   }
> 
>   void scrollText()
>   {
>     uint8_t size = max(int(mw/8), 1);
>     matrix->clear();
>     matrix->setTextWrap(false); 
>     matrix->setTextSize(2);
>     matrix->setRotation(0);
>     for (int8_t x=24; x>=-48; x--) {
>       yield();
>       matrix->clear();
>       matrix->setCursor(x,4);
>       matrix->setTextColor(LED_BLUE_LOW);
>       matrix->print("Moon");
>       if (mh>11) {
>         matrix->setCursor(20-x,mh-20);
>         matrix->setTextColor(LED_RED_MEDIUM);
>         matrix->print("Sun");
>       }
>       matrix->show();
>       delay(10);
>     }
>     matrix->setTextSize(3);
>     matrix->setTextColor(LED_GOLD);
>     matrix->setBrightness(4);
>     for (int16_t x=8*size; x>=-4*8*size; x--) {
>       yield();
>       String text = "LV Pro Teams";
>       matrix->clear();
>       matrix->setCursor(x,mw/2-size*4+1);
>       matrix->print(text);
>       matrix->show();
>     }
>     matrix->setCursor(0,0);
>     matrix->setBrightness(BRIGHTNESS);
>     matrix->show();
>   }
> };

The error message:

> src/main.cpp:27:34: error: invalid use of '::'
>  #define delay(x) esphome::delay(x)
>                                   ^
> /data/cst-cmpnt/.piolibdeps/cst-cmpnt/FastLED/src/FastLED.h:596:7: note: in expansion of macro 'delay'
>   void delay(unsigned long ms);
>        ^~~~~
> Compiling /data/cst-cmpnt/.pioenvs/cst-cmpnt/libb7e/Framebuffer GFX/Framebuffer_GFX.cpp.o
> Compiling /data/cst-cmpnt/.pioenvs/cst-cmpnt/libe4d/FastLED NeoMatrix/FastLED_NeoMatrix.cpp.o
> *** [/data/cst-cmpnt/.pioenvs/cst-cmpnt/src/main.cpp.o] Error 1

Erroneous code:

> // Auto generated code by esphome
> // ========== AUTO GENERATED INCLUDE BLOCK BEGIN ===========
> 
> #include "esphome.h"
> using namespace esphome;
> using std::isnan;
> using std::min;
> using std::max;
> using namespace switch_;
> using namespace text_sensor;
> logger::Logger *logger_logger;
> web_server_base::WebServerBase *web_server_base_webserverbase;
> captive_portal::CaptivePortal *captive_portal_captiveportal;
> wifi::WiFiComponent *wifi_wificomponent;
> mdns::MDNSComponent *mdns_mdnscomponent;
> ota::OTAComponent *ota_otacomponent;
> api::APIServer *api_apiserver;
> using namespace api;
> using namespace number;
> preferences::IntervalSyncer *preferences_intervalsyncer;
> template_::TemplateNumber *blink_frequency;
> template_::TemplateSwitch *panel_enable;
> homeassistant::HomeassistantTextSensor *sun_rise;
> homeassistant::HomeassistantTextSensor *sun_set;
> #define yield() esphome::yield()
> #define millis() esphome::millis()
> #define micros() esphome::micros()
> #define delay(x) esphome::delay(x)                                <-- Line 27
> #define delayMicroseconds(x) esphome::delayMicroseconds(x)
> #include "LEDMatrixCmpnt.h"
> 
> // ========== AUTO GENERATED INCLUDE BLOCK END ==========="

Any help would be greatly appreciated. Thank you.

yarbles

Well, stick a fork in me, I’m done. I took it in the yarbles on this one oh me brothers. Just like getting blue balled by the old lady. Where is my plastic Jesus when I need him?

Here is ESPHome’s reply to my error reported on Github:

That linked post uses a whole bunch of external untested libraries.
Closing as its not part of ESPHome codebase.
Closed [#4809] as not planned.
Closed [#4809] as completed.

My response was the following:

I don't mean to sound rude, but your response is as vague and cryptic as
a compiler error.  I thought the whole idea behind "includes" and "libraries"
was to expand, enlarge, and dare I say it, engorge the codebase.
 
What you are saying is, if I don't "test" the "untested libraries", this will
never be fixed.  The error below suggests to me that "delay" and
"delayMicroseconds" need attention.  Is this something I can do as
ESPHome is open source?  Where do I start?
 
Ken Klausner
 
 
#define yield() esphome::yield()
#define millis() esphome::millis()
#define micros() esphome::micros()
#define delay(x) esphome::delay(x)              <-- obviously the "x" is a problem
#define delayMicroseconds(x) esphome::delayMicroseconds(x)  <--

Here are the latest developments: I know I’m not the smartest peanut in the turd, but I can count the corn. I’m trying to hire a pro but to no avail. A professional programmer said I need someone familiar with ESPHome’s Framework (Codebase) because “refactoring” is required.

Here is the offending code in both core.cpp and FastLED.h where the only thing I can identify is a possible “type” mismatch between an “unsigned long” and an “unint32_t”.

ESPHome esp32/core.cpp:

FastLED.h:

Success! I paid some guy a few “Ben Franklins” (that’s a Happy Ending+ here in Las Vegas, Nevada, USA) for this simple “fix the compiler error” solution. I still don’t know if the 3 x 3 tiles and 16 x 16 matrices that make up the nine tiles will work with Home Assistant sunrise and sunset information. So here are the changes to the top of the LEDMatrixCmpnt.h file:

#ifndef LED_MATRIX_CMPNT_H
#define LED_MATRIX_CMPNT_H
#endif

#include "esphome.h"
#undef delay(x)
#define ESPHOME_DELAY(x) esphome::delay(x)
#include <FastLED.h>

#include <Adafruit_GFX.h>
#include <FastLED_NeoMatrix.h>

I’ll keep posting my progress.

24 Aug 23: if I do any processing in the “loop” function (move a bitmap or text around) besides simply splashing a bitmap and time information as static objects, the esp32 crashes in about 30 seconds. Obviously, ESPHome has a lot going on in the background, and my custom component’s processing is trying to hog all the CPU cycles.

This will work better with an “update” function in this case. I am working on a Polling Component, and I’m looking into a custom Home Assistant Integration, which would skip ESPHome. I wanted to avoid Python, however. Maybe MQTT.