Skip to content

Commit

Permalink
Use non-volatile storage to store and retrieve output config
Browse files Browse the repository at this point in the history
  • Loading branch information
niliha committed Aug 4, 2023
1 parent 8b6a7a0 commit 3845262
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/ArtnetHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void ArtnetHandler::handleConfig(uint16_t length, uint8_t *data) {
return;
}

std::array<int, 4> lightsPerOutput = {data[0], data[1], data[2], data[3]};
std::array<uint8_t, 4> lightsPerOutput = {data[0], data[1], data[2], data[3]};
int checksum = std::accumulate(lightsPerOutput.begin(), lightsPerOutput.end(), 0);
if (checksum != data[4]) {
Serial.printf("ERROR: Calculated config checksum %d does not match with %d\n", checksum, data[4]);
Expand Down
23 changes: 9 additions & 14 deletions src/FastLedHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,25 @@

template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDER = RGB> class FastLedHandler {
public:
FastLedHandler(const std::array<int, PIN_COUNT> &lightsPerPin, int pixelsPerLight = 144)
FastLedHandler(const std::array<uint8_t, PIN_COUNT> &lightsPerPin, int pixelsPerLight = 144)
: PIXELS_PER_LIGHT_(pixelsPerLight),
PIXEL_COUNT_(PIXELS_PER_LIGHT_ * std::accumulate(lightsPerPin.begin(), lightsPerPin.end(), 0))
PIXEL_COUNT_(PIXELS_PER_LIGHT_ * std::accumulate(lightsPerPin.begin(), lightsPerPin.end(), 0)),
fastLedPixels_(PIXEL_COUNT_)

{
fastLedPixels_.resize(PIXEL_COUNT_);
setupFastled(lightsPerPin);
}

void write(std::vector<CRGB> &frame) {
void write(const std::vector<CRGB> &frame) {
assert(frame.size() == fastLedPixels_.size());

fastLedPixels_ = frame;
FastLED.show();
}

void applyConfig(PixelConfig& pixelConfig) {
// TODO:
}

void testLeds() {
Serial.println("Testing LEDs...");
std::vector<CRGB> colors{CRGB::Red, CRGB::Green, CRGB::Blue};
for (const auto color : colors) {
for (const auto color : std::vector<CRGB>{CRGB::Red, CRGB::Green, CRGB::Blue}) {
auto millisBefore = millis();
FastLED.showColor(color);
auto passedMillis = millis() - millisBefore;
Expand All @@ -42,10 +37,10 @@ template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDE
FastLED.clear(true);
delay(500);
}
delay(2000);
delay(1000);
}

int getPixelCount() {
int getPixelCount() const {
return PIXEL_COUNT_;
}

Expand All @@ -56,10 +51,9 @@ template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDE
const int PIXEL_COUNT_;

// The vector holding color values for each pixel.
// It's size is set in configure() and must not be changed afterwards!
std::vector<CRGB> fastLedPixels_;

void setupFastled(const std::array<int, PIN_COUNT> &lightsPerPin) {
void setupFastled(const std::array<uint8_t, PIN_COUNT> &lightsPerPin) {
static_assert(PIN_COUNT == 4, "setupFastLed() is hardcoded to handle exactly 4 pins!");
// We can't use a loop here since addLeds() template parameters must be known at
// compile-time
Expand All @@ -84,6 +78,7 @@ template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDE
lightsPerPin[3] * PIXELS_PER_LIGHT_);
pixelOffset += lightsPerPin[3] * PIXELS_PER_LIGHT_;
}

FastLED.setCorrection(TypicalLEDStrip);
}
};
4 changes: 2 additions & 2 deletions src/Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ namespace Network {
bool connectToWifi(std::string wifiSsid, std::string wifiPassword) {
WiFi.begin(wifiSsid.c_str(), wifiPassword.c_str());
// Wait for connection
Serial.println("Connecting to WiFi...");
Serial.print("Connecting to WiFi... ");
for (unsigned i = 0; i <= 20; i++) {
if (WiFi.status() == WL_CONNECTED) {
Serial.print("SUCCESS! IP address: ");
Serial.print(" SUCCESS! IP address: ");
Serial.println(WiFi.localIP());
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions src/PixelConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#include <array>

struct PixelConfig {
std::array<int, 4> lightsPerOutput;
std::array<uint8_t, 4> lightsPerOutput;

PixelConfig(std::array<int,4> lightsPerOutput) {
PixelConfig(std::array<uint8_t,4> lightsPerOutput) {
this->lightsPerOutput = lightsPerOutput;
}
};
54 changes: 45 additions & 9 deletions src/PixelDriver.hpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
#pragma once

#include <Preferences.h>
#include <variant>

#include "ArtnetHandler.hpp"
#include "FastLedHandler.hpp"
#include "PixelConfig.hpp"

#include <variant>

template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDER = RGB> class PixelDriver {
public:
PixelDriver(const std::array<int, PIN_COUNT> &lightsPerPin, int pixelsPerLight = 144, int baudrate = 3000000,
PixelDriver(const std::array<uint8_t, PIN_COUNT> &defaultLightsPerPin, int pixelsPerLight = 144, int baudrate = 3000000,
int frameQueueCapacity = 3)
: fastLedHandler_(lightsPerPin, pixelsPerLight), artnetQueue_(frameQueueCapacity),
artnetHandler_(artnetQueue_, fastLedHandler_.getPixelCount(), baudrate), lastFrameMillis_(millis()) {
// The watchdog on core 0 is not reset anymore, since the idle task is not resumed.
// It is disabled to avoid watchdog timeouts (resulting in a reboot).
: fastLedHandler_(loadLightsPerOutputConfig(defaultLightsPerPin), pixelsPerLight),
artnetQueue_(frameQueueCapacity), artnetHandler_(artnetQueue_, fastLedHandler_.getPixelCount(), baudrate),
lastFrameMillis_(millis()) {
// The Artnet task on core 0 does not block/sleep to reduce latency.
// Therefore, the watchdog on core 0 is not reset anymore, since the idle task is not resumed.
// It is disabled to avoid watchdog timeouts resulting in a reboot.
disableCore0WDT();
}

Expand All @@ -34,11 +37,44 @@ template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDE
}

private:
static constexpr const char *PREFERENCE_NAMESPACE = "ravelights";
static constexpr const char *LIGHTS_PER_OUTPUT_PREFERENCE_KEY = "output_config";

FastLedHandler<PIN_COUNT, PINS, RGB_ORDER> fastLedHandler_;
ArtnetHandler artnetHandler_;
BlockingRingBuffer<std::variant<PixelFrame, PixelConfig>> artnetQueue_;
unsigned long lastFrameMillis_;

std::array<uint8_t, PIN_COUNT> loadLightsPerOutputConfig(const std::array<uint8_t, PIN_COUNT> &defaultConfig) {
Preferences preferences;
preferences.begin(PREFERENCE_NAMESPACE, false);
if (!preferences.isKey(LIGHTS_PER_OUTPUT_PREFERENCE_KEY)) {
preferences.end();
Serial.printf("Using default lights per output config (%d, %d, %d, %d)\n", defaultConfig[0],
defaultConfig[1], defaultConfig[2], defaultConfig[3]);
return defaultConfig;
}

std::array<uint8_t, 4> lightsPerOutput;
preferences.getBytes(LIGHTS_PER_OUTPUT_PREFERENCE_KEY, lightsPerOutput.data(), 4);
preferences.end();
Serial.printf("Using lights per output config from flash (%d, %d, %d, %d)\n", lightsPerOutput[0],
lightsPerOutput[1], lightsPerOutput[2], lightsPerOutput[3]);
return lightsPerOutput;
}

void applyPixelConfig(const PixelConfig &pixelConfig){
Preferences preferences;
preferences.begin(PREFERENCE_NAMESPACE, false);
preferences.putBytes(LIGHTS_PER_OUTPUT_PREFERENCE_KEY, pixelConfig.lightsPerOutput.data(),
pixelConfig.lightsPerOutput.size());
preferences.end();

Serial.printf("Restarting ESP32 to apply new config (%d, %d, %d, %d)...\n", pixelConfig.lightsPerOutput[0],
pixelConfig.lightsPerOutput[1], pixelConfig.lightsPerOutput[2], pixelConfig.lightsPerOutput[3]);
ESP.restart();
}

void fastledTask() {
Serial.printf("fastledTask: started on core %d\n", xPortGetCoreID());

Expand All @@ -54,8 +90,8 @@ template <int PIN_COUNT, const std::array<int, PIN_COUNT> &PINS, EOrder RGB_ORDE
Serial.printf("%d ms since last frame\n", millis() - lastFrameMillis_);
lastFrameMillis_ = millis();
} else if constexpr (std::is_same_v<T, PixelConfig>) {
Serial.printf("TODO: Applying PixelConfig...\n");
fastLedHandler_.applyConfig(arg);
Serial.printf("Applying PixelConfig...\n");
applyPixelConfig(arg);
}
},
pixelVariant);
Expand Down
10 changes: 6 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "PixelDriver.hpp"
#include "WifiCredentials.hpp"
#include <Arduino.h>
#include <nvs_flash.h>

/* BEGIN USER CONFIG */
// Specify the maximum number of pins to which lights are to be connected in a specific scenario.
Expand All @@ -16,19 +17,20 @@ extern constexpr std::array<int, MAX_PIN_COUNT> PINS = {19};
// If there are no lights connected to a specific, set lightCount to 0.
// TODO: Receive lightsPerPin through artnet and store/load to/from non-volatile storage.
// std::array<int, MAX_PIN_COUNT> lightsPerPin = {1, 1, 1, 1};
std::array<int, MAX_PIN_COUNT> lightsPerPin = {5};
std::array<uint8_t, MAX_PIN_COUNT> lightsPerPin = {5,0,0,0};
const EOrder RGB_ORDER = EOrder::RGB;
/* END USER CONFIG */

void setup() {
Serial.begin(115200);

/*
// nvs_flash_erase(); // erase the NVS partition and...
// nvs_flash_init(); // initialize the NVS partition.

if (!Network::connectToWifi(WifiCredentials::ssid, WifiCredentials::password)) {
ESP.restart();
}
*/
Network::initWifiAccessPoint(WifiCredentials::ssid, WifiCredentials::password);
// Network::initWifiAccessPoint(WifiCredentials::ssid, WifiCredentials::password);

PixelDriver<MAX_PIN_COUNT, PINS, RGB_ORDER> pixelDriver(lightsPerPin, PIXELS_PER_LIGHT);
pixelDriver.testLeds();
Expand Down

0 comments on commit 3845262

Please sign in to comment.