Compare commits

..

2 Commits
bnb ... master

Author SHA1 Message Date
Thomas Kolb 3ac26d35d2 Make AP more friendly in congested WiFi situations 2023-08-14 23:32:31 +02:00
Thomas Kolb ecfc78c48a Decide on UDP or animation display after showing IP for 30 seconds 2023-08-11 21:46:50 +02:00
15 changed files with 42 additions and 422 deletions

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019-2022 Thomas Kolb
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -11,5 +11,3 @@
#include "RgbwPsychedelicAnimation.h"
#include "SnowfallAnimation.h"
#include "StellarAnimation.h"
#include "ChristmasGlitterAnimation.h"
#include "RacerAnimation.h"

View File

@ -21,8 +21,6 @@ class AnimationController
STELLAR = 6,
RGBW_SINUS = 7,
RGBW_PSYCHEDELIC = 8,
CHRISTMAS_GLITTER = 9,
RACERS = 10,
NUM_DEFAULT_ANIMATIONS
};
@ -42,9 +40,7 @@ class AnimationController
"Fireworks",
"Twinkling Sky",
"RGBW Sinus",
"RGBW Psychedelic",
"Christmas Glitter",
"Racers"
"RGBW Psychedelic"
};
AnimationController(Fader *fader);

View File

@ -1,36 +0,0 @@
#pragma once
#include <random>
#include <list>
#include "Animation.h"
class ChristmasGlitterAnimation : public Animation
{
public:
ChristmasGlitterAnimation(Fader *fader,
const Fader::Color &background_color = Fader::Color{0x06, 0x04, 0x00, 0x04},
const Fader::Color &glitter_color = Fader::Color{0x60, 0x40, 0x00, 0x60},
int fadestep = 1, int background_spawns_per_frame = 20, int spawn_interval_frames = 4);
void loop(uint64_t frame) override;
void stop(void) override
{
m_stopping = true;
}
void reset(void) override;
private:
std::default_random_engine m_gen;
Fader::Color m_backgroundColor;
Fader::Color m_glitterColor;
int m_fadestep;
int m_spawnInterval; // in frames
int m_backgroundSpawnsPerFrame;
bool m_stopping;
};

View File

@ -20,8 +20,8 @@ class FireAnimation : public Animation
void reset(void) override;
private:
static const constexpr unsigned MAX_NEW_ENERGY = 200;
static const constexpr unsigned RM_ENERGY = 5;
static const constexpr unsigned MAX_NEW_ENERGY = 160;
static const constexpr unsigned RM_ENERGY = 7;
static const constexpr unsigned MAX_PULL_ENERGY_PCT = 100;
std::vector<uint32_t> m_energy;

View File

@ -1,49 +0,0 @@
// vim: sw=4 ts=4 sts=4 expandtab
#pragma once
#include <random>
#include <vector>
#include "Animation.h"
#include "fasttrigon.h"
class RacerAnimation : public Animation
{
public:
RacerAnimation(Fader *fader, uint32_t racer_count);
void loop(uint64_t frame) override;
void stop(void) override
{
m_stopping = true;
}
void reset(void) override;
private:
class Racer
{
public:
Racer(Fader *fader, int32_t pos, int32_t speed, const Fader::Color &color);
void move(void);
void render(void) const;
private:
Fader *m_fader;
int32_t m_speed; // in 1/256 LEDs
int32_t m_pos; // in 1/256 LEDs
Fader::Color m_color;
};
std::vector<Racer> m_racers;
std::default_random_engine m_gen;
bool m_stopping;
};

View File

@ -11,7 +11,7 @@ class StellarAnimation : public Animation
StellarAnimation(Fader *fader,
const Fader::Color &background_color = Fader::Color{0x00, 0x02, 0x0c, 0x00},
const Fader::Color &star_color = Fader::Color{0x60, 0x30, 0x00, 0x60},
int fadestep = 1, int spawn_interval_frames = 6);
int fadestep = 1, int spawn_interval_frames = 12);
void loop(uint64_t frame) override;

View File

@ -14,8 +14,6 @@ class Fader
Color(int16_t ir = 0, int16_t ig = 0, int16_t ib = 0, int16_t iw = 0) : r(ir), g(ig), b(ib), w(iw) {}
Color(const Color &c) : r(c.r), g(c.g), b(c.b), w(c.w) {}
void operator += (const Color &color)
{
this->r += color.r;
@ -44,18 +42,12 @@ class Fader
Fader(std::size_t nstrips, std::size_t nmodules_per_strip, uint8_t fadestep = 1, uint32_t flip_strips_mask = 0x00);
void set_color(uint32_t pos, const Color &color);
void set_color(uint32_t strip, uint32_t module, const Color &color);
void set_color(const Color &color); // for all LEDs
void fade_color(uint32_t pos, const Color &color);
void fade_color(uint32_t strip, uint32_t module, const Color &color);
void fade_color(const Color &color); // for all LEDs
void add_color(uint32_t pos, const Color &color);
void add_color(uint32_t strip, uint32_t module, const Color &color);
void set_color(const Color &color); // for all LEDs
void fade_color(const Color &color); // for all LEDs
void add_color(const Color &color); // for all LEDs
void set_fadestep(uint8_t newFadestep);
void update(void);
@ -73,11 +65,6 @@ class Fader
std::size_t modules_per_strip(void) { return m_modulesPerStrip; }
std::size_t strips(void) { return m_strips; }
uint32_t make_module_idx(uint32_t strip, uint32_t module) const;
uint32_t get_led_idx(uint32_t module_pos) const;
uint32_t get_strip_idx(uint32_t module_pos) const;
private:
/*!
* Fade the colour value in cur towards target.
@ -88,6 +75,8 @@ class Fader
*/
bool update_fade(int16_t *cur, const int16_t *target);
inline uint32_t make_module_idx(uint32_t strip, uint32_t module);
std::size_t m_strips;
std::size_t m_modulesPerStrip;
uint8_t m_fadestep;

View File

@ -8,9 +8,9 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32-evb]
[env:nodemcu-32s]
platform = espressif32 @ 5.2.0
board = esp32-evb
board = nodemcu-32s
framework = arduino
monitor_speed = 115200

View File

@ -82,14 +82,6 @@ void AnimationController::changeAnimation(AnimationController::DefaultAnimation
anim.reset(new RgbwPsychedelicAnimation(m_fader));
break;
case CHRISTMAS_GLITTER:
anim.reset(new ChristmasGlitterAnimation(m_fader));
break;
case RACERS:
anim.reset(new RacerAnimation(m_fader, m_fader->strips() * m_fader->modules_per_strip() / 8));
break;
default:
return; // unknown id, do nothing
}

View File

@ -1,58 +0,0 @@
#include "Animation/ChristmasGlitterAnimation.h"
#include <iostream>
ChristmasGlitterAnimation::ChristmasGlitterAnimation(Fader *fader,
const Fader::Color &background_color, const Fader::Color &glitter_color,
int fadestep, int background_spawns_per_frame, int spawn_interval_frames)
: Animation(fader),
m_backgroundColor(background_color),
m_glitterColor(glitter_color),
m_fadestep(fadestep),
m_spawnInterval(spawn_interval_frames),
m_backgroundSpawnsPerFrame(background_spawns_per_frame)
{
reset();
}
void ChristmasGlitterAnimation::loop(uint64_t frame)
{
int nled = m_fader->modules_per_strip();
int nstrip = m_fader->strips();
if(frame == 0) {
m_fader->set_fadestep(m_fadestep);
m_fader->fade_color(m_backgroundColor);
}
// create new pixels
std::uniform_int_distribution<int> stripRng(0, nstrip-1);
std::uniform_int_distribution<int> ledRng(0, nled-1);
if(!m_stopping) {
if((frame % m_spawnInterval) == 0) {
int strip = stripRng(m_gen);
int led = ledRng(m_gen);
m_fader->add_color(strip, led, m_glitterColor);
m_fader->fade_color(strip, led, Fader::Color{0x10,0x06,0,0x03});
}
for(size_t i = 0; i < m_backgroundSpawnsPerFrame; i++) {
int strip = stripRng(m_gen);
int led = ledRng(m_gen);
m_fader->add_color(strip, led, m_backgroundColor);
m_fader->fade_color(strip, led, Fader::Color{0x10,0x06,0,0x03});
}
}
m_fader->update();
m_running = !m_stopping || m_fader->something_changed();
}
void ChristmasGlitterAnimation::reset(void)
{
m_stopping = false;
m_running = true;
}

View File

@ -6,7 +6,7 @@ FireAnimation::FireAnimation(Fader *fader, bool cold)
m_energySmooth(fader->modules_per_strip() * fader->strips()),
m_stopping(false)
{
m_colorMapIndices.assign({0, 100, 160, 200, 225, 255});
m_colorMapIndices.assign({0, 70, 120, 200, 225, 255});
if(cold) {
m_colorMapColors.emplace_back(Fader::Color{ 0, 0, 0, 0});
@ -160,12 +160,9 @@ void FireAnimation::loop(uint64_t frame)
Fader::Color color;
for(std::size_t strip = 0; strip < nstrip; strip++) {
for(std::size_t led = 0; led < nled; led+=4) {
colormap(m_energySmooth[idx(strip, led/4)], &color);
for(int i = 0; i < 4; i++) {
m_fader->fade_color(strip, led+i, color);
}
for(std::size_t led = 0; led < nled; led++) {
colormap(m_energySmooth[idx(strip, led)], &color);
m_fader->fade_color(strip, led, color);
}
}
}

View File

@ -1,116 +0,0 @@
#include <algorithm>
#include "Animation/RacerAnimation.h"
/********* Racer *********/
RacerAnimation::Racer::Racer(Fader *fader, int32_t pos, int32_t speed, const Fader::Color &color)
: m_fader(fader),
m_speed(speed),
m_pos(pos),
m_color(color)
{
}
void RacerAnimation::Racer::move(void)
{
int32_t maxpos = m_fader->strips() * m_fader->modules_per_strip() * 256;
m_pos += m_speed;
if(m_pos >= maxpos) {
m_pos = maxpos - (m_pos % maxpos);
m_speed = -m_speed;
} else if(m_pos < 0) {
m_pos = -m_pos;
m_speed = -m_speed;
}
}
void RacerAnimation::Racer::render(void) const
{
int32_t idx1 = m_pos / 256;
int32_t idx2 = m_pos / 256 + 1;
int32_t scale1 = (idx2 * 256) - m_pos;
int32_t scale2 = m_pos - (idx1 * 256);
m_fader->add_color(idx1,
Fader::Color{
static_cast<int16_t>(m_color.r * scale1 / 256),
static_cast<int16_t>(m_color.g * scale1 / 256),
static_cast<int16_t>(m_color.b * scale1 / 256),
static_cast<int16_t>(m_color.w * scale1 / 256)
});
m_fader->add_color(idx2,
Fader::Color{
static_cast<int16_t>(m_color.r * scale2 / 256),
static_cast<int16_t>(m_color.g * scale2 / 256),
static_cast<int16_t>(m_color.b * scale2 / 256),
static_cast<int16_t>(m_color.w * scale2 / 256)
});
}
/********* RacerAnimation *********/
RacerAnimation::RacerAnimation(Fader *fader, uint32_t racer_count)
: Animation(fader)
{
reset();
int32_t maxpos = m_fader->strips() * m_fader->modules_per_strip() * 256;
std::uniform_int_distribution<int32_t> posRng(0, maxpos);
std::uniform_int_distribution<int32_t> speedRng(-128, 128);
std::uniform_int_distribution<int16_t> colorRng(0, 255);
std::uniform_int_distribution<int16_t> whiteRng(0, 48);
m_racers.reserve(racer_count);
for(size_t i = 0; i < racer_count; i++) {
int32_t speed = speedRng(m_gen);
if(speed == 0) {
speed++;
}
m_racers.emplace_back(Racer{
fader,
posRng(m_gen),
speed,
Fader::Color{
colorRng(m_gen),
colorRng(m_gen),
colorRng(m_gen),
whiteRng(m_gen),
}
});
}
}
void RacerAnimation::loop(uint64_t frame)
{
if(!m_stopping) {
// clear the frame buffer
m_fader->set_color(Fader::Color{0, 0, 0, 0});
// move snow flakes and render
for(auto &flake: m_racers) {
flake.move();
flake.render();
}
} else {
m_fader->set_fadestep(4);
m_fader->fade_color(Fader::Color{0, 0, 0, 0});
}
m_fader->update();
if(m_stopping && !m_fader->something_changed()) {
m_running = false;
}
}
void RacerAnimation::reset(void)
{
m_stopping = false;
m_running = true;
}

View File

@ -12,12 +12,8 @@ Fader::Fader(std::size_t nstrips, std::size_t nmodules_per_strip, uint8_t fadest
void Fader::set_color(uint32_t strip, uint32_t module, const Fader::Color &color)
{
uint32_t idx = make_module_idx(strip, module);
set_color(idx, color);
}
void Fader::set_color(uint32_t pos, const Fader::Color &color)
{
m_targetColor[pos] = m_curColor[pos] = color;
m_targetColor[idx] = m_curColor[idx] = color;
m_somethingChanged = true;
}
@ -25,15 +21,11 @@ void Fader::set_color(uint32_t pos, const Fader::Color &color)
void Fader::add_color(uint32_t strip, uint32_t module, const Fader::Color &color)
{
uint32_t idx = make_module_idx(strip, module);
add_color(idx, color);
}
void Fader::add_color(uint32_t pos, const Fader::Color &color)
{
m_curColor[pos] += color;
m_curColor[pos].normalize();
m_targetColor[pos] += color;
m_targetColor[pos].normalize();
m_curColor[idx] += color;
m_curColor[idx].normalize();
m_targetColor[idx] += color;
m_targetColor[idx].normalize();
m_somethingChanged = true;
}
@ -41,12 +33,8 @@ void Fader::add_color(uint32_t pos, const Fader::Color &color)
void Fader::fade_color(uint32_t strip, uint32_t module, const Fader::Color &color)
{
uint32_t idx = make_module_idx(strip, module);
fade_color(idx, color);
}
void Fader::fade_color(uint32_t pos, const Fader::Color &color)
{
m_targetColor[pos] = color;
m_targetColor[idx] = color;
m_somethingChanged = true;
}
@ -121,7 +109,7 @@ void Fader::update(void)
}
}
uint32_t Fader::make_module_idx(uint32_t strip, uint32_t module) const
uint32_t Fader::make_module_idx(uint32_t strip, uint32_t module)
{
strip = (strip + STRIP_OFFSET) % m_strips;
@ -131,22 +119,3 @@ uint32_t Fader::make_module_idx(uint32_t strip, uint32_t module) const
}
return strip * m_modulesPerStrip + module;
}
uint32_t Fader::get_strip_idx(uint32_t module_pos) const
{
return ((module_pos / m_strips) + m_strips - STRIP_OFFSET) % m_strips;
}
uint32_t Fader::get_led_idx(uint32_t module_pos) const
{
uint32_t strip = get_strip_idx(module_pos);
uint32_t led = module_pos % m_modulesPerStrip;
bool flip = m_flipStripsMask & (1 << strip);
if(flip) {
led = m_modulesPerStrip - led - 1;
}
return led;
}

View File

@ -6,7 +6,7 @@
#include <WiFiMulti.h>
#include <SPIFFS.h>
#include <ETH.h>
#include <esp_wifi.h>
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
@ -26,12 +26,10 @@
#include "coreids.h"
#define HOSTNAME "zamusiclight"
const uint32_t FRAME_INTERVAL_US = 16666;
const uint32_t NUM_STRIPS = 2;
const uint32_t NUM_LEDS = 150;
const uint32_t FLIP_STRIPS_MASK = 0x00000002;
const uint32_t NUM_STRIPS = 8;
const uint32_t NUM_LEDS = 16;
const uint32_t FLIP_STRIPS_MASK = 0x000000AA;
std::array<strand_t, 1> STRANDS { // Avoid using any of the strapping pins on the ESP32, anything >=32, 16, 17... not much left.
strand_t {.rmtChannel = 0, .gpioNum = 4, .ledType = LED_SK6812W_V1, .brightLimit = 32, .numPixels = NUM_LEDS * NUM_STRIPS},
@ -53,45 +51,6 @@ UpdateServer *updateServer;
AnimationController animController(&ledFader);
static bool eth_connected = false;
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname(HOSTNAME);
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex()) {
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
bool initLEDs()
{
/****************************************************************************
@ -231,20 +190,20 @@ static void ledFSM(void)
animController.loop();
if(((WiFi.status() == WL_CONNECTED) || (WiFi.getMode() == WIFI_MODE_AP)) &&
udpProto.check()) {
// UDP packet received -> transition to UDP state
nextState = UDP;
ledState = TRANSITION;
// ensure the correct animation plays after UDP transfers stop
animController.changeAnimation(loadSavedAnimation(), false);
}
// change to last used animation after some time
if((millis() - stateEnteredTime) > 20000) {
// change to last used animation or UDP visualization after some time
if((millis() - stateEnteredTime) > 30000) {
// load the saved animation
// FIXME: does not work with transition because of restart() call in ANIMATION state
animController.changeAnimation(loadSavedAnimation(), false);
ledState = ANIMATION;
if(((WiFi.status() == WL_CONNECTED) || (WiFi.getMode() == WIFI_MODE_AP)) &&
udpProto.check()) {
// UDP packet received -> transition to UDP state
nextState = UDP;
ledState = TRANSITION;
} else {
ledState = ANIMATION;
}
}
break;
@ -397,7 +356,7 @@ void wifi_setup(void)
{
Serial.println("Trying to connect...");
WiFi.setHostname(HOSTNAME);
WiFi.setHostname("mlmini");
for(size_t tries = 0; tries < 10; tries++)
{
@ -426,6 +385,10 @@ void wifi_setup(void)
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP("🕯️💡☀️", "Licht234");
WiFi.setTxPower(WIFI_POWER_2dBm);
esp_wifi_set_bandwidth(WIFI_IF_AP, WIFI_BW_HT20);
esp_wifi_config_11b_rate(WIFI_IF_AP, true);
esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_11N);
WiFi.enableAP(true);
animController.changeAnimation(std::unique_ptr<Animation>(new ConnectionEstablishedAnimation(&ledFader, false)));
@ -476,8 +439,6 @@ void setup()
NULL, /* Task handle to keep track of created task */
CORE_ID_LED);
WiFi.onEvent(WiFiEvent);
// Connect the WiFi network (or start an AP if that doesn't work)
for (auto &net : Config::instance().getWLANList())
{
@ -488,8 +449,6 @@ void setup()
wifi_setup();
ETH.begin();
// start the UDP server
udpProto.start(2703);