diff --git a/platformio.ini b/platformio.ini index cd09d66..efe2bdf 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,5 +28,5 @@ lib_deps = https://github.com/Gianbacchio/ESP8266_Spiram.git Adafruit Unified Sensor Adafruit BME280 Library - ClickEncoder + https://github.com/samguyer/FastLED.git lib_ignore = ESPAsyncTCP diff --git a/src/hardware.h b/src/hardware.h index 7b54e47..d8ed6a9 100644 --- a/src/hardware.h +++ b/src/hardware.h @@ -9,6 +9,10 @@ static constexpr uint8_t sensorPin = 0; static constexpr uint8_t rotaryPinA = 39; static constexpr uint8_t rotaryPinB = 38; static constexpr uint8_t rotaryPinButton = 17; +static constexpr uint8_t PROGMEM LED_PIN = 21; +static constexpr uint8_t PROGMEM NUM_LEDS = 21; +#define LED_TYPE WS2812B +#define COLOR_ORDER GRB static constexpr uint8_t ext_wakeup_pin_1 = 0; static constexpr uint8_t ext_wakeup_pin_2 = 0; diff --git a/src/led.cpp b/src/led.cpp new file mode 100644 index 0000000..80f3d63 --- /dev/null +++ b/src/led.cpp @@ -0,0 +1,127 @@ +//#define FASTLED_ALLOW_INTERRUPTS 0 +//#define FASTLED_INTERRUPT_RETRY_COUNT 1 +#include + +#include "led.h" +#include "hardware.h" + +using namespace std; + +Led::Led(void) { + index = 0; + duration = 0; +} + +void Led::loop_rainbow(void) { + fill_rainbow(leds, NUM_LEDS, index, 14); +} + +void Led::loop_confetti(void) +{ + // random colored speckles that blink in and fade smoothly + fadeToBlackBy( leds, NUM_LEDS, 10); + int pos = random16(NUM_LEDS); + leds[pos] += CHSV( index + random8(64), 200, 255); + + leds[0] = CRGB::White; + leds[1] = CRGB::White; + leds[NUM_LEDS-1] = CRGB::White; + leds[NUM_LEDS-2] = CRGB::White; + leds[NUM_LEDS-3] = CRGB::White; +} + +void Led::loop_dispense(void) { + // top: led 9 and 10 + + // a colored dot sweeping back and forth, with fading trails + fadeToBlackBy( leds, NUM_LEDS, 20); + int pos = beatsin16( 13, 0, NUM_LEDS-1 ); + leds[pos] += CHSV( index, 255, 192); + + leds[0] = CRGB::White; + leds[NUM_LEDS-1] = CRGB::White; + leds[NUM_LEDS-2] = CRGB::White; +} + +void Led::loop_denied(void) { + fill_solid(leds, NUM_LEDS, CRGB::Red); +} + +void Led::loop_steady(void) { + fill_solid(leds, NUM_LEDS, color); +} + +void Led::changeAnimation(uint8_t num, uint16_t duration) { + change = true; + if (duration == 0) this->duration = UINT16_MAX; + else this->duration = duration; + if (num == 0) refresh = &Led::loop_steady; + else if (num == 1) refresh = &Led::loop_dispense; + else if (num == 2) refresh = &Led::loop_confetti; + else if (num == 3) refresh = &Led::loop_rainbow; + else if (num == 4) refresh = &Led::loop_denied; +} + +void Led::changeColor(uint8_t r, uint8_t g, uint8_t b) { + color = CRGB(r, g, b); + change = true; +} +void Led::changeBrightness(uint8_t brightness) { + if (brightness > 254) { // don't set first byte to 255 on tm1829 + FastLED.setBrightness(254); + } else { + FastLED.setBrightness(brightness); + } + change = true; +} + +void Led::setup(void) { + pinMode(LED_PIN, OUTPUT); + FastLED.addLeds(leds, NUM_LEDS); + FastLED.setBrightness(96); + FastLED.setCorrection(0xFF5050); + fill_solid(leds, NUM_LEDS, CRGB::White); + color = CRGB::Orange; + change = true; + + refresh = &Led::loop_steady; + delay(100); + xTaskCreate( + &cTaskWrapper, /* Task function. */ + "ledAnimationTask", /* String with name of task. */ + 1024, /* Stack size in words. */ + this, /* Parameter passed as input of the task */ + tskIDLE_PRIORITY+3, /* Priority of the task. */ + &ledTaskHandle); /* Task handle. */ +} + +void Led::animationTask(void* parameters) { + while(true) { + if (refresh != nullptr) { + (*this.*refresh)(); + if (refresh != (&Led::loop_steady) || change == true) FastLED.show(); + change = false; +// EVERY_N_MILLISECONDS ( 20) { index++; } + index++; + if (duration == 0) { + refresh = &Led::loop_steady; + change = true; + } else if (duration == UINT16_MAX) { + } else { + duration--; + } + EVERY_N_SECONDS(300) { +// FastLED.clear(); +// delay(200); + changeAnimation(3, 400); + } + } + vTaskDelay(50 / portTICK_PERIOD_MS); + } + Serial.println("LED animation end!"); + vTaskDelete(NULL); +} + +void Led::cTaskWrapper(void* parameters) { + static_cast(parameters)->animationTask(NULL); +} diff --git a/src/led.h b/src/led.h new file mode 100644 index 0000000..b029c09 --- /dev/null +++ b/src/led.h @@ -0,0 +1,35 @@ +#ifndef _LED_H +#define _LED_H + +//#define FASTLED_ALLOW_INTERRUPTS 0 +//#define FASTLED_INTERRUPT_RETRY_COUNT 1 +#include + +#include "hardware.h" + + +class Led { + public: + Led(void); + void setup(void); + void changeAnimation(uint8_t num, uint16_t duration); + void changeColor(uint8_t, uint8_t, uint8_t); + void changeBrightness(uint8_t); + private: + CRGB leds[NUM_LEDS]; + void animationTask(void*); + static void cTaskWrapper(void*); + TaskHandle_t ledTaskHandle; + void (Led::*refresh)(void) = NULL; + void loop_steady(void); + void loop_rainbow(void); + void loop_confetti(void); + void loop_dispense(void); + void loop_denied(void); + uint16_t duration; + uint8_t index; + bool change; + CRGB color; +}; + +#endif /* _LED_H */ diff --git a/src/main.cpp b/src/main.cpp index d0654d2..5916ecc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,6 +22,7 @@ #include "BME280.h" #include "rotary.h" #include "screen.h" +#include "led.h" U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 15, /* data=*/ 4); @@ -37,6 +38,7 @@ BME280 bme280; MP3 mp3; Rotary rotary; Screen* screen; +Led led; menuType menuChange = eNone; uint32_t lastButtonPress = 0; @@ -136,6 +138,7 @@ Serial.println(strftime_buf); } mp3.begin(); + led.setup(); rotary.registerCallback(rotation); rotary.begin(rotaryPinA, rotaryPinB, rotaryPinButton);