This commit is contained in:
Aircoookie 2020-02-01 00:36:07 +01:00
commit b78d1baaaf
19 changed files with 701 additions and 79 deletions

View File

@ -7,15 +7,15 @@ data_dir = ./wled00/data
;lib_extra_dirs = ./wled00/src ;lib_extra_dirs = ./wled00/src
lib_dir = ./wled00/src lib_dir = ./wled00/src
; Please uncomment one of the 5 lines below to select your board ; Please uncomment one of the 5 lines below to select your board
env_default = nodemcuv2 default_envs = nodemcuv2
; env_default = esp01 ; default_envs = esp01
; env_default = esp01_1m ; default_envs = esp01_1m
; env_default = esp07 ; default_envs = esp07
; env_default = d1_mini ; default_envs = d1_mini
; env_default = esp32dev ; default_envs = esp32dev
; env_default = esp8285_4CH_MagicHome ; default_envs = esp8285_4CH_MagicHome
; env_default = esp8285_4CH_H801 ; default_envs = esp8285_4CH_H801
; env_default = esp8285_5CH_H801 ; default_envs = esp8285_5CH_H801
[common] [common]
framework = arduino framework = arduino
@ -30,15 +30,11 @@ build_flags =
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here) #build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
-D _IR_ENABLE_DEFAULT_=false -D _IR_ENABLE_DEFAULT_=false
-D DECODE_HASH=true -D DECODE_HASH=true
-D DECODE_NEC=true -D DECODE_NEC=true
-D DECODE_SONY=true -D DECODE_SONY=true
-D DECODE_PANASONIC=true
-D DECODE_JVC=true
-D DECODE_SAMSUNG=true -D DECODE_SAMSUNG=true
-D DECODE_LG=true -D DECODE_LG=true
-D DECODE_SANYO=true
-D DECODE_SHARP=true
-D DECODE_DENON=true
# TODO replace libs in /lib with managed libs in here if possible. # TODO replace libs in /lib with managed libs in here if possible.
# If they are not changed it's just a matter of setting the correct version and change the import statement # If they are not changed it's just a matter of setting the correct version and change the import statement
lib_deps_external = lib_deps_external =
@ -52,8 +48,7 @@ lib_deps_external =
Esp Async WebServer@1.2.0 Esp Async WebServer@1.2.0
#ArduinoJson@5.13.5 #ArduinoJson@5.13.5
#IRremoteESP8266@2.7.2 #IRremoteESP8266@2.7.2
#For saving 20k program space the brnach "compile_flags" will be used: https://github.com/crankyoldgit/IRremoteESP8266.git
https://github.com/crankyoldgit/IRremoteESP8266.git#compile_flags
#Time@1.5 #Time@1.5
#Timezone@1.2.1 #Timezone@1.2.1
#For use SSD1306 0.91" OLED display uncomment following #For use SSD1306 0.91" OLED display uncomment following

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

View File

@ -0,0 +1,7 @@
# Enclosure and PCB
## IP67 rated enclosure
![Enclosure](controller.jpg)
## PCB
![PCB](pcb.png)

View File

@ -0,0 +1,38 @@
# Almost universal controller board for outdoor applications
This usermod is using ideas from @mrVanboy and @400killer
## Project repository
- [Original repository](https://github.com/srg74/Controller-for-WLED-firmware) - Main controller repository
## Features
* SSD1306 128x32 and 128x64 I2C OLED display
* On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
* Auto display shutoff for saving display lifetime
* Dallas temperature sensor
* Reporting temperature to MQTT broker
## Hardware
![Hardware connection](assets/controller.jpg)
## Functionality checked with
* ESP-07S
* PlatformIO
* SSD1306 128x32 I2C OLED display
* DS18B20 (temperature sensor)
* KY-022 (infrared receiver)
* Push button (N.O. momentary switch)
### Platformio requirements
Uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
```ini
# platformio.ini
...
[common]
...
lib_deps_external =
...
#For use SSD1306 OLED display uncomment following
U8g2@~2.27.3
#For Dallas sensor uncomment following 2 lines
DallasTemperature@~3.8.0
OneWire@~2.3.5
...
```

View File

@ -0,0 +1,206 @@
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
#include <DallasTemperature.h> //Dallastemperature sensor
//The SCL and SDA pins are defined here.
//Lolin32 boards use SCL=5 SDA=4
#define U8X8_PIN_SCL 5
#define U8X8_PIN_SDA 4
// Dallas sensor
OneWire oneWire(12);
DallasTemperature sensor(&oneWire);
long temptimer = millis();
long lastMeasure = 0;
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
// If display does not work or looks corrupted check the
// constructor reference:
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// or check the gallery:
// https://github.com/olikraus/u8g2/wiki/gallery
// --> First choise of cheap I2C OLED 128X32
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// --> Second choise of cheap I2C OLED 128X64
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// gets called once at boot. Do all initialization that doesn't depend on
// network here
void userSetup() {
sensor.begin(); //Start Dallas temperature sensor
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.drawString(0, 0, "Loading...");
}
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void userConnected() {}
// needRedraw marks if redraw is required to prevent often redrawing.
bool needRedraw = true;
// Next variables hold the previous known values to determine if redraw is
// required.
String knownSsid = "";
IPAddress knownIp;
uint8_t knownBrightness = 0;
uint8_t knownMode = 0;
uint8_t knownPalette = 0;
long lastUpdate = 0;
long lastRedraw = 0;
bool displayTurnedOff = false;
// How often we are redrawing screen
#define USER_LOOP_REFRESH_RATE_MS 5000
void userLoop() {
//----> Dallas temperature sensor MQTT publishing
temptimer = millis();
// Timer to publishe new temperature every 60 seconds
if (temptimer - lastMeasure > 60000)
{
lastMeasure = temptimer;
//Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr)
{
sensor.requestTemperatures();
//Gets prefered temperature scale based on selection in definitions section
#ifdef Celsius
float board_temperature = sensor.getTempCByIndex(0);
#else
float board_temperature = sensor.getTempFByIndex(0);
#endif
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
char subuf[38];
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/temperature");
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
}
}
// Check if we time interval for redrawing passes.
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
return;
}
lastUpdate = millis();
// Turn off display after 3 minutes with no change.
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
u8x8.setPowerSave(1);
displayTurnedOff = true;
}
// Check if values which are shown on display changed from the last time.
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
needRedraw = true;
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
needRedraw = true;
}
if (!needRedraw) {
return;
}
needRedraw = false;
if (displayTurnedOff)
{
u8x8.setPowerSave(0);
displayTurnedOff = false;
}
lastRedraw = millis();
// Update last known values.
#if defined(ESP8266)
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
#else
knownSsid = WiFi.SSID();
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);
// First row with Wifi name
u8x8.setCursor(1, 0);
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
// Print `~` char to indicate that SSID is longer, than owr dicplay
if (knownSsid.length() > u8x8.getCols())
u8x8.print("~");
// Second row with IP or Psssword
u8x8.setCursor(1, 1);
// Print password in AP mode and if led is OFF.
if (apActive && bri == 0)
u8x8.print(apPass);
else
u8x8.print(knownIp);
// Third row with mode name
u8x8.setCursor(2, 2);
uint8_t qComma = 0;
bool insideQuotes = false;
uint8_t printedChars = 0;
char singleJsonSymbol;
// Find the mode name in JSON
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownMode))
break;
u8x8.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
break;
}
// Fourth row with palette name
u8x8.setCursor(2, 3);
qComma = 0;
insideQuotes = false;
printedChars = 0;
// Looking for palette name in JSON.
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownPalette))
break;
u8x8.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
break;
}
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
u8x8.drawGlyph(0, 0, 80); // wifi icon
u8x8.drawGlyph(0, 1, 68); // home icon
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
}

View File

@ -0,0 +1,28 @@
# Blynk controllable relay
This usermod allows controlling a relay state from the user variables. It also allows the user variables to be set over Blynk.
Optionally, the servo can have a reset timer to go back to it's default state after an interval. This interval is set through userVar1.
## Instalation
Replace the WLED06_usermod.ino file in Aircoookies WLED folder with the one here.
## Customizations
Update the following parameters in WLED06_usermod.ino to configure the mod's behavior:
```cpp
//Which pin is the relay connected to
#define RELAY_PIN 5
//Which pin state should the relay default to
#define RELAY_PIN_DEFAULT LOW
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
#define RELAY_PIN_TIMER_DEFAULT 3000
//Blynk virtual pin for controlling relay
#define BLYNK_USER_VAR0_PIN V9
//Blynk virtual pin for controlling relay timer
#define BLYNK_USER_VAR1_PIN V10
//Number of milliseconds between updating blynk
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
```

View File

@ -0,0 +1,96 @@
/*
* This file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
* bytes 2400+ are currently ununsed, but might be used for future wled features
*/
//Use userVar0 (API calls &U0=, uint16_t) to set relay state
#define relayPinState userVar0
//Use userVar1 (API calls &U1=, uint16_t) to set relay timer duration
//Ignored if 0, otherwise number of milliseconds to allow relay to stay in
//non default state.
#define relayTimerInterval userVar1
//Which pin is the relay connected to
#define RELAY_PIN 5
//Which pin state should the relay default to
#define RELAY_PIN_DEFAULT LOW
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
#define RELAY_PIN_TIMER_DEFAULT 3000
//Blynk virtual pin for controlling relay
#define BLYNK_USER_VAR0_PIN V9
//Blynk virtual pin for controlling relay timer
#define BLYNK_USER_VAR1_PIN V10
//Number of milliseconds between updating blynk
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
//Is the timer for resetting the relay active
bool relayTimerStarted = false;
//millis() time after which relay will be reset
unsigned long relayTimeToDefault = 0;
//millis() time after which relay vars in Blynk will be sent
unsigned long relayBlynkUpdateTime = 0;
//gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup()
{
relayPinState = RELAY_PIN_DEFAULT;
relayTimerInterval = RELAY_PIN_TIMER_DEFAULT;
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, relayPinState);
}
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
void userConnected()
{
}
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
void userLoop()
{
//Normalize relayPinState to an accepted value
if (relayPinState != HIGH && relayPinState != LOW) {
relayPinState = RELAY_PIN_DEFAULT;
}
//If relay changes and relayTimerInterval is set, start a timer to change back
if (relayTimerInterval != 0 &&
relayPinState != RELAY_PIN_DEFAULT &&
!relayTimerStarted ) {
relayTimerStarted = true;
relayTimeToDefault = millis() + relayTimerInterval;
}
//If manually changed back to default, cancel timer
if (relayTimerStarted && relayPinState == RELAY_PIN_DEFAULT ) {
relayTimerStarted = false;
}
//If timer completes, set relay back to default
if (relayTimerStarted && millis() > relayTimeToDefault) {
relayPinState = RELAY_PIN_DEFAULT;
relayTimerStarted = false;
}
digitalWrite(RELAY_PIN, relayPinState);
updateRelayBlynk();
}
//Update Blynk with state of userVars at BLYNK_RELAY_UPDATE_INTERVAL
void updateRelayBlynk()
{
if (!WLED_CONNECTED) return;
if (relayBlynkUpdateTime > millis()) return;
Blynk.virtualWrite(BLYNK_USER_VAR0_PIN, userVar0);
Blynk.virtualWrite(BLYNK_USER_VAR1_PIN, userVar1);
relayBlynkUpdateTime = millis() + BLYNK_RELAY_UPDATE_INTERVAL;
}
//Add Blynk callback for setting userVar0
BLYNK_WRITE(BLYNK_USER_VAR0_PIN)
{
userVar0 = param.asInt();
}
//Add Blynk callback for setting userVar1
BLYNK_WRITE(BLYNK_USER_VAR1_PIN)
{
userVar1 = param.asInt();
}

View File

@ -11,6 +11,9 @@ byte wipeState = 0; //0: inactive 1: wiping 2: solid
unsigned long timeStaticStart = 0; unsigned long timeStaticStart = 0;
uint16_t previousUserVar0 = 0; uint16_t previousUserVar0 = 0;
//comment this out if you want the turn off effect to be just fading out instead of reverse wipe
#define STAIRCASE_WIPE_OFF
//gets called once at boot. Do all initialization that doesn't depend on network here //gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup() void userSetup()
{ {
@ -52,14 +55,28 @@ void userLoop()
{ {
if (millis() - timeStaticStart > userVar1*1000) wipeState = 3; if (millis() - timeStaticStart > userVar1*1000) wipeState = 3;
} }
} else { //wipeState == 3, turn off slowly } else if (wipeState == 3) { //switch to wipe off
#ifdef STAIRCASE_WIPE_OFF
effectCurrent = FX_MODE_COLOR_WIPE;
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
colorUpdated(3);
wipeState = 4;
#else
turnOff(); turnOff();
userVar0 = 0; #endif
wipeState = 0; } else { //wiping off
if (millis() + strip.timebase > (725 + (255 - effectSpeed)*150)) turnOff(); //wipe complete
} }
} else { } else {
if (previousUserVar0) turnOff();
wipeState = 0; //reset for next time wipeState = 0; //reset for next time
if (previousUserVar0) {
#ifdef STAIRCASE_WIPE_OFF
userVar0 = previousUserVar0;
wipeState = 3;
#else
turnOff();
#endif
}
previousUserVar0 = 0; previousUserVar0 = 0;
} }
} }
@ -81,7 +98,14 @@ void startWipe()
void turnOff() void turnOff()
{ {
transitionDelayTemp = 4000; #ifdef STAIRCASE_WIPE_OFF
transitionDelayTemp = 0; //turn off immediately after wipe completed
#else
transitionDelayTemp = 4000; //fade out slowly
#endif
bri = 0; bri = 0;
colorUpdated(3); colorUpdated(3);
wipeState = 0;
userVar0 = 0;
previousUserVar0 = 0;
} }

View File

@ -1025,15 +1025,26 @@ uint16_t WS2812FX::larson_scanner(bool dual) {
/* /*
* Firing comets from one end. * Firing comets from one end. "Lighthouse"
*/ */
uint16_t WS2812FX::mode_comet(void) { uint16_t WS2812FX::mode_comet(void) {
uint16_t counter = now * (SEGMENT.speed >>3) +1; uint16_t counter = now * ((SEGMENT.speed >>2) +1);
uint16_t index = counter * SEGLEN >> 16; uint16_t index = counter * SEGLEN >> 16;
if (SEGENV.call == 0) SEGENV.aux0 = index;
fade_out(SEGMENT.intensity); fade_out(SEGMENT.intensity);
setPixelColor( index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); setPixelColor( index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0));
if (index > SEGENV.aux0) {
for (uint16_t i = SEGENV.aux0; i < index ; i++) {
setPixelColor( i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
} else if (index < SEGENV.aux0 && index < 10) {
for (uint16_t i = 0; i < index ; i++) {
setPixelColor( i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
}
SEGENV.aux0 = index++;
return FRAMETIME; return FRAMETIME;
} }
@ -1172,19 +1183,26 @@ uint16_t WS2812FX::mode_loading(void) {
//American Police Light with all LEDs Red and Blue //American Police Light with all LEDs Red and Blue
uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2) uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2)
{ {
uint16_t counter = now * ((SEGMENT.speed >> 3) +1); uint16_t counter = now * ((SEGMENT.speed >> 2) +1);
uint16_t idexR = (counter * SEGLEN) >> 16; uint16_t idexR = (counter * SEGLEN) >> 16;
if (idexR >= SEGLEN) idexR = 0; if (idexR >= SEGLEN) idexR = 0;
uint16_t topindex = SEGLEN >> 1; uint16_t topindex = SEGLEN >> 1;
uint16_t idexB = idexR + topindex; uint16_t idexB = idexR + topindex;
if (SEGENV.call == 0) SEGENV.aux0 = idexR;
if (idexR > topindex) idexB -= SEGLEN; if (idexR > topindex) idexB -= SEGLEN;
if (idexB >= SEGLEN) idexB = 0; //otherwise overflow on odd number of LEDs if (idexB >= SEGLEN) idexB = 0; //otherwise overflow on odd number of LEDs
setPixelColor(idexR, color1); uint8_t gap = (SEGENV.aux0 < idexR)? idexR - SEGENV.aux0:SEGLEN - SEGENV.aux0 + idexR;
setPixelColor(idexB, color2); for (uint8_t i = 0; i < gap ; i++) {
if ((idexR - i) < 0) idexR = SEGLEN-1 + i;
if ((idexB - i) < 0) idexB = SEGLEN-1 + i;
setPixelColor(idexR-i, color1);
setPixelColor(idexB-i, color2);
}
SEGENV.aux0 = idexR;
return FRAMETIME; return FRAMETIME;
} }
@ -1720,7 +1738,8 @@ uint16_t WS2812FX::mode_colorwaves()
uint8_t msmultiplier = beatsin88(147, 23, 60); uint8_t msmultiplier = beatsin88(147, 23, 60);
uint16_t hue16 = sHue16;//gHue * 256; uint16_t hue16 = sHue16;//gHue * 256;
uint16_t hueinc16 = beatsin88(113, 300, 1500); // uint16_t hueinc16 = beatsin88(113, 300, 1500);
uint16_t hueinc16 = beatsin88(113, 60, 300)*SEGMENT.intensity*10/255; // Use the Intensity Slider for the hues
sPseudotime += duration * msmultiplier; sPseudotime += duration * msmultiplier;
sHue16 += duration * beatsin88(400, 5, 9); sHue16 += duration * beatsin88(400, 5, 9);
@ -2485,22 +2504,33 @@ uint16_t WS2812FX::mode_bouncing_balls(void) {
*/ */
uint16_t WS2812FX::sinelon_base(bool dual, bool rainbow=false) { uint16_t WS2812FX::sinelon_base(bool dual, bool rainbow=false) {
fade_out(SEGMENT.intensity); fade_out(SEGMENT.intensity);
int pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); uint16_t pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1);
if (SEGENV.call == 0) SEGENV.aux0 = pos;
uint32_t color1 = color_from_palette(pos, true, false, 0); uint32_t color1 = color_from_palette(pos, true, false, 0);
uint32_t color2 = SEGCOLOR(2);
if (rainbow) { if (rainbow) {
color1 = color_wheel((pos & 0x07) * 32); color1 = color_wheel((pos & 0x07) * 32);
} }
setPixelColor(pos, color1); setPixelColor(pos, color1);
if (dual) { if (dual) {
uint32_t color2 = SEGCOLOR(2);
if (!color2) color2 = color_from_palette(pos, true, false, 0); if (!color2) color2 = color_from_palette(pos, true, false, 0);
if (rainbow) color2 = color1; //rainbow if (rainbow) color2 = color1; //rainbow
setPixelColor(SEGLEN-1-pos, color2); setPixelColor(SEGLEN-1-pos, color2);
} }
if (SEGENV.aux0 != pos) {
if (SEGENV.aux0 < pos) {
for (uint16_t i = SEGENV.aux0; i < pos ; i++) {
setPixelColor(i, color1);
if (dual) setPixelColor(SEGLEN-1-i, color2);
}
} else {
for (uint16_t i = SEGENV.aux0; i > pos ; i--) {
setPixelColor(i, color1);
if (dual) setPixelColor(SEGLEN-1-i, color2);
}
}
SEGENV.aux0 = pos;
}
return FRAMETIME; return FRAMETIME;
} }
@ -2890,7 +2920,7 @@ uint16_t WS2812FX::mode_exploding_fireworks(void)
uint16_t WS2812FX::mode_drip(void) uint16_t WS2812FX::mode_drip(void)
{ {
//allocate segment data //allocate segment data
uint16_t numDrops = 2; uint16_t numDrops = 4;
uint16_t dataSize = sizeof(spark) * numDrops; uint16_t dataSize = sizeof(spark) * numDrops;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
@ -2898,6 +2928,8 @@ uint16_t WS2812FX::mode_drip(void)
Spark* drops = reinterpret_cast<Spark*>(SEGENV.data); Spark* drops = reinterpret_cast<Spark*>(SEGENV.data);
numDrops = 1 + (SEGMENT.intensity >> 6);
float gravity = -0.001 - (SEGMENT.speed/50000.0); float gravity = -0.001 - (SEGMENT.speed/50000.0);
gravity *= SEGLEN; gravity *= SEGLEN;
int sourcedrop = 12; int sourcedrop = 12;
@ -2915,7 +2947,7 @@ uint16_t WS2812FX::mode_drip(void)
if (drops[j].col>255) drops[j].col=255; if (drops[j].col>255) drops[j].col=255;
setPixelColor(int(drops[j].pos),color_blend(BLACK,SEGCOLOR(0),drops[j].col)); setPixelColor(int(drops[j].pos),color_blend(BLACK,SEGCOLOR(0),drops[j].col));
drops[j].col += map(SEGMENT.intensity, 0, 255, 1, 6); // swelling drops[j].col += map(SEGMENT.speed, 0, 255, 1, 6); // swelling
if (random8() < drops[j].col/10) { // random drop if (random8() < drops[j].col/10) { // random drop
drops[j].colIndex=2; //fall drops[j].colIndex=2; //fall
@ -2954,3 +2986,54 @@ uint16_t WS2812FX::mode_drip(void)
} }
return FRAMETIME; return FRAMETIME;
} }
/*
/ Plasma Effect
/ adapted from https://github.com/atuline/FastLED-Demos/blob/master/plasma/plasma.ino
*/
uint16_t WS2812FX::mode_plasma(void) {
uint8_t thisPhase = beatsin8(6,-64,64); // Setting phase change for a couple of waves.
uint8_t thatPhase = beatsin8(7,-64,64);
for (int i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set color & brightness based on a wave as follows:
uint8_t colorIndex = cubicwave8((i*(1+ 3*(SEGMENT.speed >> 5)))+(thisPhase) & 0xFF)/2 // factor=23 // Create a wave and add a phase change and add another wave with its own phase change.
+ cos8((i*(1+ 2*(SEGMENT.speed >> 5)))+(thatPhase) & 0xFF)/2; // factor=15 // Hey, you can even change the frequencies if you wish.
uint8_t thisBright = qsub8(colorIndex, beatsin8(6,0, (255 - SEGMENT.intensity)|0x01 ));
CRGB color = ColorFromPalette(currentPalette, colorIndex, thisBright, LINEARBLEND);
setPixelColor(i, color.red, color.green, color.blue);
}
return FRAMETIME;
}
/*
* Percentage display
* Intesity values from 0-100 turn on the leds.
*/
uint16_t WS2812FX::mode_percent(void) {
uint8_t percent = max(0, min(100, SEGMENT.intensity));
uint16_t active_leds = SEGLEN * percent / 100.0;
if (SEGENV.call == 0) SEGENV.step = 0;
uint8_t size = (1 + ((SEGMENT.speed * SEGLEN) >> 11)) & 0xFF ;
for (uint16_t i = 0; i < SEGLEN; i++) {
if (i < SEGENV.step) {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
else {
setPixelColor(i, SEGCOLOR(1));
}
}
if(active_leds > SEGENV.step) {
SEGENV.step += size;
if (SEGENV.step > active_leds) SEGENV.step = active_leds;
} else if (active_leds < SEGENV.step) {
if (SEGENV.step > size) SEGENV.step -= size; else SEGENV.step = 0;
if (SEGENV.step < active_leds) SEGENV.step = active_leds;
}
return FRAMETIME;
}

View File

@ -91,7 +91,7 @@
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
#define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED )
#define MODE_COUNT 97 #define MODE_COUNT 99
#define FX_MODE_STATIC 0 #define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1 #define FX_MODE_BLINK 1
@ -190,7 +190,8 @@
#define FX_MODE_SINELON_RAINBOW 94 #define FX_MODE_SINELON_RAINBOW 94
#define FX_MODE_POPCORN 95 #define FX_MODE_POPCORN 95
#define FX_MODE_DRIP 96 #define FX_MODE_DRIP 96
#define FX_MODE_PLASMA 97
#define FX_MODE_PERCENT 98
class WS2812FX { class WS2812FX {
typedef uint16_t (WS2812FX::*mode_ptr)(void); typedef uint16_t (WS2812FX::*mode_ptr)(void);
@ -376,6 +377,8 @@ class WS2812FX {
_mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow; _mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow;
_mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn;
_mode[FX_MODE_DRIP] = &WS2812FX::mode_drip; _mode[FX_MODE_DRIP] = &WS2812FX::mode_drip;
_mode[FX_MODE_PLASMA] = &WS2812FX::mode_plasma;
_mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent;
_brightness = DEFAULT_BRIGHTNESS; _brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black); currentPalette = CRGBPalette16(CRGB::Black);
@ -557,7 +560,9 @@ class WS2812FX {
mode_sinelon_dual(void), mode_sinelon_dual(void),
mode_sinelon_rainbow(void), mode_sinelon_rainbow(void),
mode_popcorn(void), mode_popcorn(void),
mode_drip(void); mode_drip(void),
mode_plasma(void),
mode_percent(void);
private: private:
@ -637,7 +642,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise",
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip" "Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent"
])====="; ])=====";

View File

@ -469,7 +469,19 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off
if (i2 <= i1) //disable segment if (i2 <= i1) //disable segment
{ {
seg.stop = 0; return; seg.stop = 0;
if (n == mainSegment) //if main segment is deleted, set first active as main segment
{
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive()) {
mainSegment = i;
return;
}
}
mainSegment = 0; //should not happen (always at least one active segment)
}
return;
} }
if (i1 < _length) seg.start = i1; if (i1 < _length) seg.start = i1;
seg.stop = i2; seg.stop = i2;
@ -482,6 +494,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
} }
void WS2812FX::resetSegments() { void WS2812FX::resetSegments() {
mainSegment = 0;
memset(_segments, 0, sizeof(_segments)); memset(_segments, 0, sizeof(_segments));
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); //memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
_segment_index = 0; _segment_index = 0;

View File

@ -9,7 +9,7 @@
//#define USE_LPD8806 // Uncomment for using LPD8806 //#define USE_LPD8806 // Uncomment for using LPD8806
//#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13) //#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13)
//#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well //#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well
//#define WLED_USE_5CH //5 Channel H801 for cold and warm white //#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) #define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0 #define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
@ -34,7 +34,7 @@
#define RPIN 15 //R pin for analog LED strip #define RPIN 15 //R pin for analog LED strip
#define GPIN 13 //G pin for analog LED strip #define GPIN 13 //G pin for analog LED strip
#define BPIN 12 //B pin for analog LED strip #define BPIN 12 //B pin for analog LED strip
#define WPIN 14 //W pin for analog LED strip (W1: 14, W2: 04) #define WPIN 14 //W pin for analog LED strip
#define W2PIN 04 //W2 pin for analog LED strip #define W2PIN 04 //W2 pin for analog LED strip
#undef BTNPIN #undef BTNPIN
#undef IR_PIN #undef IR_PIN
@ -44,7 +44,7 @@
#define RPIN 5 //R pin for analog LED strip #define RPIN 5 //R pin for analog LED strip
#define GPIN 12 //G pin for analog LED strip #define GPIN 12 //G pin for analog LED strip
#define BPIN 15 //B pin for analog LED strip #define BPIN 15 //B pin for analog LED strip
#define WPIN 13 //W pin for analog LED strip (W1: 14, W2: 04) #define WPIN 13 //W pin for analog LED strip
#endif #endif
#undef RLYPIN #undef RLYPIN
#define RLYPIN -1 //disable as pin 12 is used by analog LEDs #define RLYPIN -1 //disable as pin 12 is used by analog LEDs
@ -248,7 +248,7 @@ public:
if (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) { if (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) {
SetRgbwPwm(0, 0, 0, 0, color.W * b / 255); SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
} else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) { } else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 512, colorW.W * b / 255); SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255);
} else if (color.R == 0 & color.G == 0 && color.B == 0 && color.W == 255) { } else if (color.R == 0 & color.G == 0 && color.B == 0 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 255, 0); SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
} else if (color.R == 130 & color.G == 90 && color.B == 0 && color.W == 255) { } else if (color.R == 130 & color.G == 90 && color.B == 0 && color.W == 255) {
@ -256,7 +256,7 @@ public:
} else if (color.R == 255 & color.G == 153 && color.B == 0 && color.W == 255) { } else if (color.R == 255 & color.G == 153 && color.B == 0 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 255, 0); SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
} else { // not only white colors } else { // not only white colors
SetRgbwPwm(color.R * b / 255, colorW.G * b / 255, colorW.B * b / 255, color.W * b / 255); SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
} }
#else #else
SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255); SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);

View File

@ -189,7 +189,7 @@ const char PAGE_settings_sync[] PROGMEM = R"=====(<!DOCTYPE html>
<h2>Sync setup</h2> <h2>Sync setup</h2>
<h3>Button setup</h3> <h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BT"><br> On/Off button enabled: <input type="checkbox" name="BT"><br>
Infrared receiver type (0 = disabled): <input name="IR" type="number" min="0" max="4" required><br> Infrared receiver type (0 = disabled): <input name="IR" type="number" min="0" max="6" required><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a> <a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
<h3>WLED Broadcast</h3> <h3>WLED Broadcast</h3>
UDP Port: <input name="UP" type="number" min="1" max="65535" required><br> UDP Port: <input name="UP" type="number" min="1" max="65535" required><br>
@ -234,13 +234,13 @@ Group Topic: <input name="MG" maxlength="32"><br>
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a> <i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
<h3>Philips Hue</h3> <h3>Philips Hue</h3>
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br> <i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br> Poll Hue light <input name="HL" type="number" min="1" max="99" > every <input name="HI" type="number" min="100" max="65000"> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br> Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Hue Bridge IP:<br> Hue Bridge IP:<br>
<input name="H0" type="number" min="0" max="255" required> . <input name="H0" type="number" min="0" max="255" > .
<input name="H1" type="number" min="0" max="255" required> . <input name="H1" type="number" min="0" max="255" > .
<input name="H2" type="number" min="0" max="255" required> . <input name="H2" type="number" min="0" max="255" > .
<input name="H3" type="number" min="0" max="255" required><br> <input name="H3" type="number" min="0" max="255" ><br>
<b>Press the pushlink button on the bridge, after that save this page!</b><br> <b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br> (when first connecting)<br>
Hue status: <span class="hms"> Internal ESP Error! </span><hr> Hue status: <span class="hms"> Internal ESP Error! </span><hr>

View File

@ -4,6 +4,16 @@
#define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example) #define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example)
#define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for #define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for
// Default IR codes for 6-key learning remote https://www.aliexpress.com/item/4000307837886.html
// This cheap remote has the advantage of being more powerful (longer range) than cheap credit-card remotes
#define IR6_POWER 0xFF0FF0
#define IR6_CHANNEL_UP 0xFF8F70
#define IR6_CHANNEL_DOWN 0xFF4FB0
#define IR6_VOLUME_UP 0xFFCF30
#define IR6_VOLUME_DOWN 0xFF2FD0
#define IR6_MUTE 0xFFAF50
//Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/ //Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/
#define IR24_BRIGHTER 0xF700FF #define IR24_BRIGHTER 0xF700FF
#define IR24_DARKER 0xF7807F #define IR24_DARKER 0xF7807F
@ -170,6 +180,29 @@
#define IR44_FADE3 0xFF609F // #define IR44_FADE3 0xFF609F //
#define IR44_FADE7 0xFFE01F // #define IR44_FADE7 0xFFE01F //
//Infrared codes for 21-key remote https://images-na.ssl-images-amazon.com/images/I/51NMA0XucnL.jpg
#define IR21_BRIGHTER 0xFFE01F
#define IR21_DARKER 0xFFA857
#define IR21_OFF 0xFF629D
#define IR21_ON 0xFFA25D
#define IR21_RED 0xFF6897
#define IR21_REDDISH 0xFF30CF
#define IR21_ORANGE 0xFF10EF
#define IR21_YELLOWISH 0xFF42BD
#define IR21_GREEN 0xFF9867
#define IR21_GREENISH 0xFF18E7
#define IR21_TURQUOISE 0xFF38C7
#define IR21_CYAN 0xFF4AB5
#define IR21_BLUE 0xFFB04F
#define IR21_DEEPBLUE 0xFF7A85
#define IR21_PURPLE 0xFF5AA5
#define IR21_PINK 0xFF52AD
#define IR21_WHITE 0xFF906F
#define IR21_FLASH 0xFFE21D
#define IR21_STROBE 0xFF22DD
#define IR21_FADE 0xFF02FD
#define IR21_SMOOTH 0xFFC23D
#define COLOR_RED 0xFF0000 #define COLOR_RED 0xFF0000
#define COLOR_REDDISH 0xFF7800 #define COLOR_REDDISH 0xFF7800
#define COLOR_ORANGE 0xFFA000 #define COLOR_ORANGE 0xFFA000

View File

@ -90,7 +90,7 @@
#endif #endif
//version code in format yymmddb (b = daily build) //version code in format yymmddb (b = daily build)
#define VERSION 2001151 #define VERSION 2001281
char versionString[] = "0.9.0-b2"; char versionString[] = "0.9.0-b2";
@ -535,6 +535,9 @@ void loop() {
if (!offMode) strip.service(); if (!offMode) strip.service();
} }
yield(); yield();
#ifdef ESP8266
MDNS.update();
#endif
if (millis() - lastMqttReconnectAttempt > 30000) initMqtt(); if (millis() - lastMqttReconnectAttempt > 30000) initMqtt();
//DEBUG serial logging //DEBUG serial logging

View File

@ -53,7 +53,9 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
} }
oappend("</wv><ws>"); oappend("</wv><ws>");
oappendi(colSec[3]); oappendi(colSec[3]);
oappend("</ws><cy>"); oappend("</ws><ps>");
oappendi((currentPreset < 1) ? 0:currentPreset);
oappend("</ps><cy>");
oappendi(presetCyclingEnabled); oappendi(presetCyclingEnabled);
oappend("</cy><ds>"); oappend("</cy><ds>");
if (realtimeActive) if (realtimeActive)

View File

@ -377,11 +377,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
if (t < strip.getMaxSegments()) main = t; if (t < strip.getMaxSegments()) main = t;
} }
WS2812FX::Segment& mainseg = strip.getSegment(main);
pos = req.indexOf("SV="); //segment selected pos = req.indexOf("SV="); //segment selected
if (pos > 0) strip.getSegment(main).setOption(0, (req.charAt(pos+3) != '0')); if (pos > 0) mainseg.setOption(0, (req.charAt(pos+3) != '0'));
uint16_t startI = strip.getSegment(main).start; uint16_t startI = mainseg.start;
uint16_t stopI = strip.getSegment(main).stop; uint16_t stopI = mainseg.stop;
uint8_t grpI = mainseg.grouping;
uint16_t spcI = mainseg.spacing;
pos = req.indexOf("&S="); //segment start pos = req.indexOf("&S="); //segment start
if (pos > 0) { if (pos > 0) {
startI = getNumVal(&req, pos); startI = getNumVal(&req, pos);
@ -390,7 +393,16 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
if (pos > 0) { if (pos > 0) {
stopI = getNumVal(&req, pos); stopI = getNumVal(&req, pos);
} }
strip.setSegment(main, startI, stopI); pos = req.indexOf("GP="); //segment grouping
if (pos > 0) {
grpI = getNumVal(&req, pos);
if (grpI == 0) grpI = 1;
}
pos = req.indexOf("SP="); //segment spacing
if (pos > 0) {
spcI = getNumVal(&req, pos);
}
strip.setSegment(main, startI, stopI, grpI, spcI);
main = strip.getMainSegmentId(); main = strip.getMainSegmentId();

View File

@ -14,6 +14,7 @@ decode_results results;
unsigned long irCheckedTime = 0; unsigned long irCheckedTime = 0;
uint32_t lastValidCode = 0; uint32_t lastValidCode = 0;
uint16_t irTimesRepeated = 0; uint16_t irTimesRepeated = 0;
uint8_t lastIR6ColourIdx = 0;
//Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control //Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control
@ -83,6 +84,10 @@ void decodeIR(uint32_t code)
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
case 5: decodeIR21(code); break; // white 21-key remote
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
// sets bright plain white
default: return; default: return;
} }
} }
@ -146,10 +151,10 @@ void decodeIR24OLD(uint32_t code)
case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break; case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break; case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break;
case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break; case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
case IR24_OLD_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; break; case IR24_OLD_FLASH : if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
case IR24_OLD_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; break; case IR24_OLD_STROBE : if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
case IR24_OLD_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; case IR24_OLD_FADE : if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR24_OLD_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; case IR24_OLD_SMOOTH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
default: return; default: return;
} }
lastValidCode = code; lastValidCode = code;
@ -179,13 +184,13 @@ void decodeIR24CT(uint32_t code)
case IR24_CT_PURPLE : colorFromUint32(COLOR_PURPLE); break; case IR24_CT_PURPLE : colorFromUint32(COLOR_PURPLE); break;
case IR24_CT_MAGENTA : colorFromUint32(COLOR_MAGENTA); break; case IR24_CT_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
case IR24_CT_PINK : colorFromUint32(COLOR_PINK); break; case IR24_CT_PINK : colorFromUint32(COLOR_PINK); break;
case IR24_CT_COLDWHITE : colorFromUint32(COLOR_COLDWHITE); effectCurrent = 0; break; case IR24_CT_COLDWHITE : colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; break;
case IR24_CT_WARMWHITE : colorFromUint32(COLOR_WARMWHITE); effectCurrent = 0; break; case IR24_CT_WARMWHITE : colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; break;
case IR24_CT_CTPLUS : colorFromUint32(COLOR_COLDWHITE2); effectCurrent = 0; break; case IR24_CT_CTPLUS : colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; break;
case IR24_CT_CTMINUS : colorFromUint32(COLOR_WARMWHITE2); effectCurrent = 0; break; case IR24_CT_CTMINUS : colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; break;
case IR24_CT_MEMORY : { case IR24_CT_MEMORY : {
if (col[3] > 0) col[3] = 0; if (col[3] > 0) col[3] = 0;
else colorFromUint32(COLOR_NEUTRALWHITE); effectCurrent = 0; } break; else colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; } break;
default: return; default: return;
} }
lastValidCode = code; lastValidCode = code;
@ -242,10 +247,10 @@ void decodeIR40(uint32_t code)
case IR40_SLOW : relativeChange(&effectSpeed, -10, 5); break; case IR40_SLOW : relativeChange(&effectSpeed, -10, 5); break;
case IR40_JUMP7 : relativeChange(&effectIntensity, 10); break; case IR40_JUMP7 : relativeChange(&effectIntensity, 10); break;
case IR40_AUTO : relativeChange(&effectIntensity, -10, 5); break; case IR40_AUTO : relativeChange(&effectIntensity, -10, 5); break;
case IR40_JUMP3 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break; case IR40_JUMP3 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
case IR40_FADE3 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; case IR40_FADE3 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR40_FADE7 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break; case IR40_FADE7 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
case IR40_FLASH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; case IR40_FLASH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
} }
lastValidCode = code; lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input colorUpdated(2); //for notifier, IR is considered a button input
@ -298,12 +303,12 @@ void decodeIR44(uint32_t code)
case IR44_BLUEMINUS : relativeChange(&effectIntensity, -10, 5); break; case IR44_BLUEMINUS : relativeChange(&effectIntensity, -10, 5); break;
case IR44_QUICK : relativeChange(&effectSpeed, 10); break; case IR44_QUICK : relativeChange(&effectSpeed, 10); break;
case IR44_SLOW : relativeChange(&effectSpeed, -10, 5); break; case IR44_SLOW : relativeChange(&effectSpeed, -10, 5); break;
case IR44_DIY1 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break; case IR44_DIY1 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
case IR44_DIY2 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; case IR44_DIY2 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR44_DIY3 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break; case IR44_DIY3 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
case IR44_DIY4 : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; case IR44_DIY4 : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
case IR44_DIY5 : if (!applyPreset(5)) effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; break; case IR44_DIY5 : if (!applyPreset(5)) { effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; } break;
case IR44_DIY6 : if (!applyPreset(6)) effectCurrent = FX_MODE_RAIN; effectPalette = 0; break; case IR44_DIY6 : if (!applyPreset(6)) { effectCurrent = FX_MODE_RAIN; effectPalette = 0; } break;
case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break; case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break;
case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break; case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break;
case IR44_JUMP3 : bri = 63; break; case IR44_JUMP3 : bri = 63; break;
@ -315,6 +320,78 @@ void decodeIR44(uint32_t code)
colorUpdated(2); //for notifier, IR is considered a button input colorUpdated(2); //for notifier, IR is considered a button input
} }
void decodeIR21(uint32_t code)
{
switch (code) {
case IR21_BRIGHTER: relativeChange(&bri, 10); break;
case IR21_DARKER: relativeChange(&bri, -10, 5); break;
case IR21_OFF: briLast = bri; bri = 0; break;
case IR21_ON: bri = briLast; break;
case IR21_RED: colorFromUint32(COLOR_RED); break;
case IR21_REDDISH: colorFromUint32(COLOR_REDDISH); break;
case IR21_ORANGE: colorFromUint32(COLOR_ORANGE); break;
case IR21_YELLOWISH: colorFromUint32(COLOR_YELLOWISH); break;
case IR21_GREEN: colorFromUint32(COLOR_GREEN); break;
case IR21_GREENISH: colorFromUint32(COLOR_GREENISH); break;
case IR21_TURQUOISE: colorFromUint32(COLOR_TURQUOISE); break;
case IR21_CYAN: colorFromUint32(COLOR_CYAN); break;
case IR21_BLUE: colorFromUint32(COLOR_BLUE); break;
case IR21_DEEPBLUE: colorFromUint32(COLOR_DEEPBLUE); break;
case IR21_PURPLE: colorFromUint32(COLOR_PURPLE); break;
case IR21_PINK: colorFromUint32(COLOR_PINK); break;
case IR21_WHITE: colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
case IR21_FLASH: if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
case IR21_STROBE: if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
default: return;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
void decodeIR6(uint32_t code)
{
switch (code) {
case IR6_POWER: toggleOnOff(); break;
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
case IR6_VOLUME_UP: /* next effect */ relativeChange(&effectCurrent, 1); break;
case IR6_VOLUME_DOWN:
/* next palette */
relativeChange(&effectPalette, 1);
switch(lastIR6ColourIdx)
{
case 0: colorFromUint32(COLOR_RED); break;
case 1: colorFromUint32(COLOR_REDDISH); break;
case 2:colorFromUint32(COLOR_ORANGE); break;
case 3:colorFromUint32(COLOR_YELLOWISH); break;
case 4:colorFromUint32(COLOR_GREEN); break;
case 5:colorFromUint32(COLOR_GREENISH); break;
case 6:colorFromUint32(COLOR_TURQUOISE); break;
case 7: colorFromUint32(COLOR_CYAN); break;
case 8:colorFromUint32(COLOR_BLUE); break;
case 9:colorFromUint32(COLOR_DEEPBLUE); break;
case 10:colorFromUint32(COLOR_PURPLE); break;
case 11:colorFromUint32(COLOR_PINK); break;
case 12:colorFromUint32(COLOR_WHITE); break;
default:break;
}
lastIR6ColourIdx++;
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0;
break;
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
void initIR() void initIR()
{ {