Implement light fading

This commit is contained in:
GHOSCHT 2023-03-31 12:29:07 +02:00
parent 0af1561820
commit 851cbb6e52
No known key found for this signature in database

View file

@ -1,7 +1,9 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include <FreeRTOS/Mutex.h>
#include <FreeRTOS/Queue.h> #include <FreeRTOS/Queue.h>
#include <FreeRTOS/Task.h> #include <FreeRTOS/Task.h>
#include <FreeRTOS/Util.h>
#include <etl/optional.h> #include <etl/optional.h>
#include <etl/span.h> #include <etl/span.h>
@ -11,13 +13,18 @@ using LightAction = etl::pair<LightActionType, etl::optional<uint8_t>>;
template <int... PIN> class Controller { template <int... PIN> class Controller {
public: public:
Controller(size_t actionQueueSize, UBaseType_t priority, BaseType_t coreID) Controller(size_t actionQueueSize, UBaseType_t controllerPriority,
BaseType_t controllerCoreID, UBaseType_t faderPriority,
BaseType_t faderCoreID)
: lightPins{PIN...}, lightActions{actionQueueSize}, : lightPins{PIN...}, lightActions{actionQueueSize},
lightControllerTask{exec, "control lights", stackDepth, lightControllerTask{exec, "control lights", stackDepth,
this, priority, coreID} { this, controllerPriority, controllerCoreID},
lightFaderTask{execFade, "fade lights", stackDepth,
this, faderPriority, faderCoreID} {
for (int pin : lightPins) { for (int pin : lightPins) {
pinMode(pin, OUTPUT); pinMode(pin, OUTPUT);
} }
lightStatesCurrent.second.unlock();
} }
freertos::Queue<LightAction> &getActionQueue() { return lightActions; } freertos::Queue<LightAction> &getActionQueue() { return lightActions; }
@ -26,10 +33,7 @@ public:
private: private:
static void exec(void *controllerPtr) { static void exec(void *controllerPtr) {
Controller<PIN...> *controller{ Controller *controller{static_cast<Controller *>(controllerPtr)};
static_cast<Controller<PIN...> *>(controllerPtr)};
etl::array<uint8_t, sizeof...(PIN)> lightStates;
const uint8_t step = 5;
while (true) { while (true) {
auto action{controller->getActionQueue().pop()}; auto action{controller->getActionQueue().pop()};
@ -39,45 +43,84 @@ private:
switch (type) { switch (type) {
case LightActionType::INCREASE: case LightActionType::INCREASE:
if (index.has_value() && index.value() < lightStates.size() && if (index.has_value() &&
lightStates[index.value()] <= 255 - step) { index.value() < controller->lightStatesFinal.size() &&
lightStates[index.value()] += step; controller->lightStatesFinal[index.value()] <=
255 - controller->step) {
controller->lightStatesFinal[index.value()] += controller->step;
} }
break; break;
case LightActionType::DECREASE: case LightActionType::DECREASE:
if (index.has_value() && index.value() < lightStates.size() && if (index.has_value() &&
lightStates[index.value()] >= 0) { index.value() < controller->lightStatesFinal.size() &&
lightStates[index.value()] -= step; controller->lightStatesFinal[index.value()] >= 0) {
controller->lightStatesFinal[index.value()] -= controller->step;
} }
break; break;
case LightActionType::TOGGLE: case LightActionType::TOGGLE:
if (index.has_value() && index.value() < lightStates.size()) { if (index.has_value() &&
lightStates[index.value()] = index.value() < controller->lightStatesFinal.size()) {
lightStates[index.value()] == 0 ? 255 : 0; controller->lightStatesCurrent.second.lock();
controller->lightStatesFinal[index.value()] =
controller->lightStatesFinal[index.value()] == 0 ? 255 : 0;
controller->lightStatesCurrent.first[index.value()] =
controller->lightStatesFinal[index.value()];
controller->lightStatesCurrent.second.unlock();
} }
break; break;
case LightActionType::ON: case LightActionType::ON:
lightStates.fill(255); controller->lightStatesCurrent.second.lock();
controller->lightStatesFinal.fill(255);
controller->lightStatesCurrent.first.fill(255);
controller->lightStatesCurrent.second.unlock();
break; break;
case LightActionType::OFF: case LightActionType::OFF:
lightStates.fill(0); controller->lightStatesCurrent.second.lock();
controller->lightStatesFinal.fill(0);
controller->lightStatesCurrent.first.fill(0);
controller->lightStatesCurrent.second.unlock();
break; break;
default: default:
break; break;
} }
for (size_t lightIndex = 0; lightIndex < lightStates.size();
++lightIndex) {
analogWrite(controller->getPins()[lightIndex],
lightStates[lightIndex]);
}
} }
} }
} }
static void execFade(void *controllerPtr) {
Controller *controller{static_cast<Controller *>(controllerPtr)};
while (true) {
freertos::sleep(controller->fadeRate);
controller->lightStatesCurrent.second.lock();
for (size_t i = 0; i < controller->lightStatesFinal.size(); i++) {
if (controller->lightStatesCurrent.first[i] <
controller->lightStatesFinal[i]) {
controller->lightStatesCurrent.first[i] += 1;
} else if (controller->lightStatesCurrent.first[i] >
controller->lightStatesFinal[i]) {
controller->lightStatesCurrent.first[i] -= 1;
}
}
for (size_t lightIndex = 0;
lightIndex < controller->lightStatesCurrent.first.size();
++lightIndex) {
analogWrite(controller->getPins()[lightIndex],
controller->lightStatesCurrent.first[lightIndex]);
}
controller->lightStatesCurrent.second.unlock();
}
}
static const uint32_t stackDepth = 2048; static const uint32_t stackDepth = 2048;
const uint8_t step = 5;
const size_t fadeRate = 50;
etl::array<int, sizeof...(PIN)> lightPins; etl::array<int, sizeof...(PIN)> lightPins;
freertos::Queue<LightAction> lightActions; freertos::Queue<LightAction> lightActions;
freertos::Task lightControllerTask; freertos::Task lightControllerTask;
freertos::Task lightFaderTask;
etl::array<uint8_t, sizeof...(PIN)> lightStatesFinal;
etl::pair<etl::array<uint8_t, sizeof...(PIN)>, freertos::Mutex>
lightStatesCurrent;
}; };
} // namespace LightController } // namespace LightController