Skip to content

Commit

Permalink
Added POV image effect
Browse files Browse the repository at this point in the history
Setup is really easy, after first boot and WiFi/LEDs setup:
go to wled.local/edit and upload a couple image to WLed's filesystem.
Only PNG is supported right now, further support for GIF is planned.
The image should be as wide as the 1D segment you want to apply to.

When done, go to the Effect page on the UI, select "POV Image" effect.

You could also update the image with a post to the JSON-API like this:
curl -X POST http://[wled]/json/state -d '{"seg":{"id":0,"fx":114,"f":"/axel.png"}}'

The segment should move at around 120RPM (that's 2revolutions per seconds) for an image to showup.
More informations and pictures here : https://lumina.toys
  • Loading branch information
Arthur Suzuki committed Aug 9, 2024
1 parent d2401a2 commit ed5eb28
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 0 deletions.
4 changes: 4 additions & 0 deletions platformio_override.sample.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ lib_deps = ${esp8266.lib_deps}
; ;gmag11/QuickESPNow @ ~0.7.0 # will also load QuickDebug
; https://github.com/blazoncek/QuickESPNow.git#optional-debug ;; exludes debug library
; ${esp32.AR_lib_deps} ;; used for USERMOD_AUDIOREACTIVE
; bitbank2/PNGdec@^1.0.1 ;; used for POV display uncomment following

build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags}
;
Expand Down Expand Up @@ -152,6 +154,8 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
; -D TACHO_PIN=33
; -D PWM_PIN=32
;
; Use POV Display usermod
; -D USERMOD_POV_DISPLAY
; Use built-in or custom LED as a status indicator (assumes LED is connected to GPIO16)
; -D STATUSLED=16
;
Expand Down
85 changes: 85 additions & 0 deletions usermods/pov_display/usermod_pov_display.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#pragma once
#include "wled.h"
#include <PNGdec.h>

void * openFile(const char *filename, int32_t *size) {
f = WLED_FS.open(filename);
*size = f.size();
return &f;
}

void closeFile(void *handle) {
if (f) f.close();
}

int32_t readFile(PNGFILE *pFile, uint8_t *pBuf, int32_t iLen)
{
int32_t iBytesRead;
iBytesRead = iLen;
File *f = static_cast<File *>(pFile->fHandle);
// Note: If you read a file all the way to the last byte, seek() stops working
if ((pFile->iSize - pFile->iPos) < iLen)
iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around
if (iBytesRead <= 0)
return 0;
iBytesRead = (int32_t)f->read(pBuf, iBytesRead);
pFile->iPos = f->position();
return iBytesRead;
}

int32_t seekFile(PNGFILE *pFile, int32_t iPosition)
{
int i = micros();
File *f = static_cast<File *>(pFile->fHandle);
f->seek(iPosition);
pFile->iPos = (int32_t)f->position();
i = micros() - i;
return pFile->iPos;
}

void draw(PNGDRAW *pDraw) {
uint16_t usPixels[SEGLEN];
png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_LITTLE_ENDIAN, 0xffffffff);
for(int x=0; x < SEGLEN; x++) {
uint16_t color = usPixels[x];
byte r = ((color >> 11) & 0x1F);
byte g = ((color >> 5) & 0x3F);
byte b = (color & 0x1F);
SEGMENT.setPixelColor(x, RGBW32(r,g,b,0));
}
strip.show();
}

uint16_t mode_pov_image(void) {
const char * filepath = SEGMENT.name;
int rc = png.open(filepath, openFile, closeFile, readFile, seekFile, draw);
if (rc == PNG_SUCCESS) {
rc = png.decode(NULL, 0);
png.close();
return FRAMETIME;
}
return FRAMETIME;
}

class PovDisplayUsermod : public Usermod
{
public:
static const char _data_FX_MODE_POV_IMAGE[] PROGMEM = "POV Image@!;;;1";

PNG png;
File f;

void setup() {
strip.addEffect(255, &mode_pov_image, _data_FX_MODE_POV_IMAGE);
}

void loop() {
}

uint16_t getId()
{
return USERMOD_ID_POV_DISPLAY;
}

void connected() {}
};
1 change: 1 addition & 0 deletions wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
#define USERMOD_ID_INA226 50 //Usermod "usermod_ina226.h"
#define USERMOD_ID_AHT10 51 //Usermod "usermod_aht10.h"
#define USERMOD_ID_LD2410 52 //Usermod "usermod_ld2410.h"
#define USERMOD_ID_POV_DISPLAY 53 //Usermod "usermod_pov_display.h"

//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
Expand Down
8 changes: 8 additions & 0 deletions wled00/usermods_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@
#include "../usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h"
#endif

#ifdef USERMOD_POV_DISPLAY
#include "../usermods/pov_display/usermod_pov_display.h"
#endif

#ifdef USERMOD_STAIRCASE_WIPE
#include "../usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h"
#endif
Expand Down Expand Up @@ -454,4 +458,8 @@ void registerUsermods()
#ifdef USERMOD_LD2410
usermods.add(new LD2410Usermod());
#endif

#ifdef USERMOD_POV_DISPLAY
usermods.add(new PovDisplayUsermod());
#endif
}

0 comments on commit ed5eb28

Please sign in to comment.