Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding LedBar Animation for Visual effects of OpenEVSE activity and status #899

Merged
merged 7 commits into from
Sep 1, 2024
43 changes: 43 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ build_partitions_debug = min_spiffs_debug.csv
build_partitions_16mb = openevse_16mb.csv

neopixel_lib = adafruit/Adafruit [email protected]
ws2812fx_lib = kitesurfer1404/[email protected]

gfx_display_libs =
# lvgl/[email protected]
Expand Down Expand Up @@ -378,6 +379,7 @@ build_flags =
-D RX1=25
-D TX1=27


[env:wt32-eth01]
# For Wireless Tag
board = wt32-eth01
Expand All @@ -401,6 +403,47 @@ build_flags =
-D ETH_CLK_MODE=ETH_CLOCK_GPIO0_IN
-D ETH_PHY_POWER=16

[env:wt32-eth01-ws2812]
# For Wireless Tag
board = wt32-eth01
lib_deps =
${common.lib_deps}
${common.neopixel_lib}
${common.ws2812fx_lib}
adafruit/Adafruit MCP9808 Library @ 1.1.2
build_flags =
${common.build_flags}
${common.src_build_flags}
#-D WIFI_LED=12
#-D WIFI_LED_ON_STATE=HIGH
-D NEO_PIXEL_PIN=12
-D NEO_PIXEL_LENGTH=15
-D ENABLE_WS2812FX
-D WIFI_PIXEL_NUMBER=1
-D WIFI_BUTTON=4
-D WIFI_BUTTON_PRESSED_STATE=LOW
# -D DEBUG_PORT=Serial
-D RAPI_PORT=Serial2
# If using PN532 RFID reader through I2C
# Need to comment pin definition for SDA and SCL at .platformio/packages/framework-arduinoespressif32/variants/wt32-eth01/pins_arduino.h
#-D I2C_SDA=2
#-D I2C_SCL=4
#-D ENABLE_PN532
# If Using MCP9808
#-D SDA=2
#-D SCL=4
#-D ENABLE_MCP9808
-D ENABLE_WIRED_ETHERNET
-D RESET_ETH_PHY_ON_BOOT=1
-D RX2=5
-D TX2=17
-D ETH_PHY_TYPE=ETH_PHY_LAN8720
-D ETH_PHY_ADDR=1
-D ETH_PHY_MDC=23
-D ETH_PHY_MDIO=18
-D ETH_CLK_MODE=ETH_CLOCK_GPIO0_IN
-D ETH_PHY_POWER=16

[env:esp32-c3-devkitc-02]
board = esp32-c3-devkitc-02
lib_deps =
Expand Down
205 changes: 201 additions & 4 deletions src/LedManagerTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@
#include "emonesp.h"
#include "LedManagerTask.h"

#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH)
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && !defined(ENABLE_WS2812FX)
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NEO_PIXEL_LENGTH, NEO_PIXEL_PIN, NEO_GRB + NEO_KHZ800);
#elif defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
#include <WS2812FX.h>
WS2812FX ws2812fx = WS2812FX(NEO_PIXEL_LENGTH, NEO_PIXEL_PIN, NEO_GRB + NEO_KHZ800);
#endif

#define FADE_STEP 16
Expand All @@ -41,6 +44,13 @@ Adafruit_NeoPixel strip = Adafruit_NeoPixel(NEO_PIXEL_LENGTH, NEO_PIXEL_PIN, NEO
#define CONNECTING_FLASH_TIME 450
#define CONNECTED_FLASH_TIME 250

#if defined(ENABLE_WS2812FX)
// Speed for FX Bar Effects
#define DEFAULT_FX_SPEED 1000
#define CONNECTING_FX_SPEED 2000
#define CONNECTED_FX_SPEED 1000
#endif

#define TEST_LED_TIME 500

#if defined(RED_LED) && defined(GREEN_LED) && defined(BLUE_LED)
Expand Down Expand Up @@ -91,6 +101,41 @@ uint8_t buttonShareState = 0;

#define rgb(r,g,b) (r<<16|g<<8|b)

#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)

static uint32_t status_colour_map(u_int8_t lcdcol)
{
u_int32_t color;
switch (lcdcol)
{
case OPENEVSE_LCD_OFF:
color = 0x000000; // BLACK
break;
case OPENEVSE_LCD_RED:
color = 0xFF0000; // RED
break;
case OPENEVSE_LCD_GREEN:
color = 0x00FF00; // GREEN
break;
case OPENEVSE_LCD_YELLOW:
color = 0xFFFF00; // YELLOW
break;
case OPENEVSE_LCD_BLUE:
color = 0x0000FF; // BLUE
break;
case OPENEVSE_LCD_VIOLET:
color = 0xFF00FF; // VIOLET
break;
case OPENEVSE_LCD_TEAL:
color = 0x00FFFF; // TEAL
break;
case OPENEVSE_LCD_WHITE:
color = 0xFFFFFF; // WHITE
break;
}
return color; // WHITE
}
#else
static uint32_t status_colour_map[] =
{
rgb(0, 0, 0), // OPENEVSE_LCD_OFF
Expand All @@ -103,6 +148,7 @@ static uint32_t status_colour_map[] =
rgb(255, 255, 255), // OPENEVSE_LCD_WHITE
};
#endif
#endif

LedManagerTask::LedManagerTask() :
MicroTasks::Task(),
Expand All @@ -125,11 +171,22 @@ void LedManagerTask::begin(EvseManager &evse)

void LedManagerTask::setup()
{
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH)
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && !defined(ENABLE_WS2812FX)
DBUGF("Initialising NeoPixels");
strip.begin();
//strip.setBrightness(brightness);
setAllRGB(0, 0, 0);
#elif defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
DEBUG.printf("Initialising NeoPixels WS2812FX MODE...\n");
ws2812fx.init();
ws2812fx.setBrightness(brightness);
ws2812fx.setSpeed(DEFAULT_FX_SPEED);
ws2812fx.setColor(BLACK);
ws2812fx.setMode(FX_MODE_STATIC);
//ws2812fx.setBrightness(this->brightness);
DEBUG.printf("Brightness: %d ", this->brightness);
DEBUG.printf("Brightness: %d ", brightness);
jdgarcia99 marked this conversation as resolved.
Show resolved Hide resolved
ws2812fx.start();
#endif

#if defined(RED_LED) && defined(GREEN_LED) && defined(BLUE_LED)
Expand Down Expand Up @@ -179,6 +236,100 @@ unsigned long LedManagerTask::loop(MicroTasks::WakeReason reason)
}

#if RGB_LED
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
switch(state)
{
case LedState_Off:
//setAllRGB(0, 0, 0);
ws2812fx.setColor(BLACK);
return MicroTask.Infinate;

case LedState_Test_Red:
//setAllRGB(255, 0, 0);
ws2812fx.setColor(RED);
state = LedState_Test_Green;
return TEST_LED_TIME;

case LedState_Test_Green:
//setAllRGB(0, 255, 0);
ws2812fx.setColor(GREEN);
state = LedState_Test_Blue;
return TEST_LED_TIME;

case LedState_Test_Blue:
//setAllRGB(0, 0, 255);
ws2812fx.setColor(BLUE);
state = LedState_Off;
setNewState(false);
return TEST_LED_TIME;


case LedState_Evse_State:
case LedState_WiFi_Access_Point_Waiting:
case LedState_WiFi_Access_Point_Connected:
case LedState_WiFi_Client_Connecting:
case LedState_WiFi_Client_Connected:
{
uint8_t lcdCol = _evse->getStateColour();
DBUGVAR(lcdCol);
uint32_t col = status_colour_map(lcdCol);
DBUGVAR(col, HEX);
//DEBUG.printf("Color: %x\n", col);
bool isCharging;
u_int16_t speed;
speed = 2000 - ((_evse->getChargeCurrent()/_evse->getMaxHardwareCurrent())*1000);
DEBUG.printf("Speed: %d ",speed);
DEBUG.printf("Amps: %d ", _evse->getAmps());
DEBUG.printf("ChargeCurrent: %d ", _evse->getChargeCurrent());
DEBUG.printf("MaxHWCurrent: %d ", _evse->getMaxHardwareCurrent());
if (this->brightness == 0){
ws2812fx.setBrightness(255);
}
else {
ws2812fx.setBrightness(this->brightness-1);
}
switch(state)
{
case LedState_Evse_State:
isCharging = _evse->isCharging();
if(isCharging){
setAllRGB(col, FX_MODE_COLOR_WIPE, speed);
}
else {
setAllRGB(col, FX_MODE_STATIC, DEFAULT_FX_SPEED);
}
//DEBUG.printf("MODO: LedState_Evse_State\n");
return MicroTask.Infinate;

case LedState_WiFi_Access_Point_Waiting:
setEvseAndWifiRGB(col, FX_MODE_BLINK, CONNECTING_FX_SPEED);
//DEBUG.printf("MODO: LedState_WiFi_Access_Point_Waiting\n");
return CONNECTING_FLASH_TIME;

case LedState_WiFi_Access_Point_Connected:
setEvseAndWifiRGB(col, FX_MODE_FADE, CONNECTED_FX_SPEED);
flashState = !flashState;
//DEBUG.printf("MODO: LedState_WiFi_Access_Point_Connected\n");
return CONNECTED_FLASH_TIME;

case LedState_WiFi_Client_Connecting:
setEvseAndWifiRGB(col, FX_MODE_FADE, CONNECTING_FX_SPEED);
flashState = !flashState;
//DEBUG.printf("MODO: LedState_WiFi_Client_Connecting\n");
return CONNECTING_FLASH_TIME;

case LedState_WiFi_Client_Connected:
setEvseAndWifiRGB(col, FX_MODE_FADE, CONNECTED_FX_SPEED);
//DEBUG.printf("MODO: LedState_WiFi_Client_Connected\n");
return MicroTask.Infinate;

default:
break;
}
}

}
#else
switch(state)
{
case LedState_Off:
Expand Down Expand Up @@ -279,6 +430,7 @@ unsigned long LedManagerTask::loop(MicroTasks::WakeReason reason)
#endif
}
#endif
#endif

#ifdef WIFI_LED
switch(state)
Expand Down Expand Up @@ -339,13 +491,39 @@ int LedManagerTask::fadeLed(int fadeValue, int FadeDir)
*/

#if RGB_LED
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
void LedManagerTask::setAllRGB(uint32_t color, u_int8_t mode, uint16_t speed)
{
setEvseAndWifiRGB(color, mode, speed);
}


void LedManagerTask::setEvseAndWifiRGB(uint32_t evseColor, u_int8_t mode, u_int16_t speed)
{
DBUG("EVSE LED COLOR:");
DBUG(evseColor);
if(evseColor != ws2812fx.getColor()){
ws2812fx.setColor(evseColor);
}

if(speed != ws2812fx.getSpeed()){
ws2812fx.setSpeed(speed);
}

if (ws2812fx.getMode() != mode){
ws2812fx.setMode(mode);
}

}
#else
void LedManagerTask::setAllRGB(uint8_t red, uint8_t green, uint8_t blue)
{
setEvseAndWifiRGB(red, green, blue, red, green, blue);
}
#endif
#endif

#if WIFI_PIXEL_NUMBER
#if WIFI_PIXEL_NUMBER && !defined(ENABLE_WS2812FX)
void LedManagerTask::setEvseAndWifiRGB(uint8_t evseRed, uint8_t evseGreen, uint8_t evseBlue, uint8_t wifiRed, uint8_t wifiGreen, uint8_t wifiBlue)
{
DBUG("EVSE LED R:");
Expand Down Expand Up @@ -385,7 +563,7 @@ void LedManagerTask::setEvseAndWifiRGB(uint8_t evseRed, uint8_t evseGreen, uint8
DBUG(" B:");
DBUGLN(wifiBlue);

#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH)
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && !defined(ENABLE_WS2812FX)
uint32_t col = strip.gamma32(strip.Color(evseRed, evseGreen, evseBlue));
DBUGVAR(col, HEX);
strip.fill(col);
Expand Down Expand Up @@ -549,10 +727,29 @@ void LedManagerTask::setBrightness(uint8_t brightness)
// brightness (off), 255 = just below max brightness.
this->brightness = brightness + 1;

#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
// This controls changes on the limits of the web interface slidebar.
// Otherwise it gets out of sync
if (this->brightness == 0){
ws2812fx.setBrightness(255);
}
else {
ws2812fx.setBrightness(this->brightness-1);
}

#endif

DBUGVAR(this->brightness);

// Wake the task to refresh the state
MicroTask.wakeTask(this);
}

LedManagerTask ledManager;

#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
extern void ledManager_loop()
{
ws2812fx.service();
}
#endif
13 changes: 13 additions & 0 deletions src/LedManagerTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@ class LedManagerTask : public MicroTasks::Task
MicroTasks::EventListener onStateChange;

#if RGB_LED
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
void setAllRGB(uint32_t color, u_int8_t mode, u_int16_t speed);
void setEvseAndWifiRGB(uint32_t evseColor, u_int8_t mode, u_int16_t speed);
#else
void setAllRGB(uint8_t red, uint8_t green, uint8_t blue);
void setEvseAndWifiRGB(uint8_t evseRed, uint8_t evseGreen, uint8_t evseBlue, uint8_t wifiRed, uint8_t wifiGreen, uint8_t wifiBlue);
#endif
#endif

#ifdef WIFI_LED
void setWiFiLed(uint8_t state);
Expand Down Expand Up @@ -77,4 +82,12 @@ class LedManagerTask : public MicroTasks::Task

extern LedManagerTask ledManager;

// -------------------------------------------------------------------
// Perform the background status bar operations. Must be called in the main
// loop function
// -------------------------------------------------------------------
#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
extern void ledManager_loop();
#endif

#endif // LED_MANAGER_TASK_H
4 changes: 4 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ loop() {
MicroTask.update();
Profile_End(MicroTask, 10);

#if defined(NEO_PIXEL_PIN) && defined(NEO_PIXEL_LENGTH) && defined(ENABLE_WS2812FX)
ledManager_loop();
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be needed, the MicroTask and the LedManagerTask instance provide the equivelant without the need to add lots of loop calls to the main loop function.

If you can't use the LedManagerTask you could setup another task just for running the animations.

Copy link
Contributor Author

@jdgarcia99 jdgarcia99 Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Jeremy.
Understood. However the main reason to call this is to invoke the ws2812fx.service() method which refreshes the led status bar.

I'm not sure about the Microtasks architecture as I could not find much information about.
The problem I have is that the service() method need to be invoked regularly to update the bar and If I do not force the call the bar is not updated. I could find any way within ledManagertask to execute this regularly. Only when the EVSE changes status that invokes the service just once and then the animation is stopped

Should I call from main loop just a service method directly instead?
I mean:
create a method within the ledManagerTask called service and then launch from the main loop? (that is in essence what this ledManager_loop call is doing)

Thanks in advance


if(OpenEVSE.isConnected())
{
if(OPENEVSE_STATE_STARTING != evse.getEvseState())
Expand Down
Loading