feat: shuffle mode

This commit is contained in:
2025-11-15 16:53:23 +01:00
parent 331258692b
commit 7aec14cbb9
14 changed files with 167 additions and 2358 deletions
@@ -7,6 +7,7 @@ struct {
const char *mqttBroker = "mqttBroker"; // example: "172.16.16.10"
const char *mqttPrefix = "mqttPrefix"; // example: "SomeTag"
const char *spitServer = "spitServer"; // example: "172.16.16.10"
const char *motorPower = "motorPower"; // example: "50"
} ConfigKeys;
// MQTT Topics
+116 -41
View File
@@ -17,7 +17,7 @@
// activeState.speed = (min .5 / max 3)
#include "watchMain.hpp"
#include "interconConfig.hpp"
#include "config.hpp"
using namespace spit;
@@ -104,7 +104,7 @@ void testPictoIllum(Cli::CArgs args) {
int p = std::stoi(args[0]);
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(p));
} catch (const std::exception &e) {
ESP_LOGI(TAG, "Failed to parse %s and %s", args[0].c_str(), args[1].c_str());
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
@@ -121,10 +121,10 @@ void testMovement(Cli::CArgs args) {
activeState.profile = std::min(4, std::stoi(args[1]));
}
if (args.size() >= 3) {
activeState.minJumps = std::min(20, std::stoi(args[2])) ;
activeState.minJumps = std::min(20, std::stoi(args[2]));
}
if (args.size() >= 4) {
activeState.minJumps = std::min(40, std::stoi(args[3])) ;
activeState.minJumps = std::min(40, std::stoi(args[3]));
}
commandQueue.enqueue(std::make_unique<MoveCommand>(MoveType::StepTo, p));
} catch (const std::exception &e) {
@@ -132,6 +132,25 @@ void testMovement(Cli::CArgs args) {
}
}
void testFeedback(Cli::CArgs args) {
ESP_LOGI(TAG, "on triggerMovement:");
if (args.size() != 1) {
pShell->writeLine("need target position (1..6) or 0 for moving");
return;
}
try {
int p = std::stoi(args[0]);
if (p == 0) {
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StartMoving, 0));
} else {
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StepAt, p));
}
} catch (const std::exception &e) {
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
void setConfig(Cli::CArgs args) {
if (args.size() != 2) {
pShell->writeLine("Needs string key and value");
@@ -175,11 +194,11 @@ void setDynamics(Cli::CArgs args) {
}
}
void showProcessValues(Cli::CArgs args) {
void showProcessValues(Cli::CArgs args) {
pShell->writeLine("Process values:");
char buff[256];
char buff[256];
sprintf(buff, "%02x,%02x,%02x", activeState.color.getRed(),activeState.color.getGreen(),activeState.color.getBlue());
sprintf(buff, "%02x,%02x,%02x", activeState.color.getRed(), activeState.color.getGreen(), activeState.color.getBlue());
pShell->writeLine(std::string{" Color RGB: "} + buff);
sprintf(buff, "%.2f / %.2f", activeState.accel, activeState.speed);
pShell->writeLine(std::string{" Accel/Speed: "} + buff);
@@ -187,9 +206,22 @@ void showProcessValues(Cli::CArgs args) {
pShell->writeLine(std::string{" Provile: "} + std::to_string((int)activeState.profile));
}
void startDemoMovement(Cli::CArgs args) {
ESP_LOGI(TAG, "on startDemoMovement:");
commandQueue.enqueue(std::make_unique<MoveCommand>(MoveType::Demo));
void setSyslogLevel(Cli::CArgs args) {
if (args.size() != 1) {
pShell->writeLine("Needs SyslogLevel Warning = 4, Notice = 5, Informational = 6, Debug = 7");
return;
}
try {
auto lvl = std::stoi(args[0]);
if (lvl >= (int)Syslog::Severity::Warning && lvl <= (int)Syslog::Severity::Debug) {
Syslog::setSeverity((Syslog::Severity)lvl);
} else {
pShell->writeLine("New level was not accepted");
}
} catch (const std::exception &e) {
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
/**
@@ -209,8 +241,11 @@ static void telnetSocketTask(int addrFamily) {
{"update", "Start OTA-Update-Process",
[](Cli::CArgs a) { startUpdate(a); }});
pShell->addBinding(
{"logserver_set", "Set log server config ip",
{"setLogserver", "Set log server config ip",
[](Cli::CArgs a) { setLogServerConfig(a); }});
pShell->addBinding(
{"setLogLevel", "Set severity log server",
[](Cli::CArgs a) { setSyslogLevel(a); }});
pShell->addBinding(
{"getcfg", "Get configuration value for key",
@@ -220,7 +255,7 @@ static void telnetSocketTask(int addrFamily) {
[](Cli::CArgs a) { setConfig(a); }});
pShell->addBinding(
{"dyn_set", "set dynamics of movement (velocity,accelerations) as floats",
{"setDyn", "set dynamics of movement (velocity,accelerations) as floats",
[](Cli::CArgs a) { setDynamics(a); }});
pShell->addBinding(
{"tstMove", "start movement (profile-idx,steps) as integers ",
@@ -228,9 +263,12 @@ static void telnetSocketTask(int addrFamily) {
pShell->addBinding(
{"tstIllum", "test illumination command 0=off /1..6",
[](Cli::CArgs a) { testPictoIllum(a); }});
pShell->addBinding(
{"tstFb", "test feedback-channel to control 0=Move /1..6=FinalPos",
[](Cli::CArgs a) { testFeedback(a); }});
pShell->addBinding(
{"showData", "Show process values that are input by DMX, MQTT and SPIT",
[](Cli::CArgs a) { showProcessValues(a); }});
[](Cli::CArgs a) { showProcessValues(a); }});
},
[](TcpSession &session) {
pShell->process();
@@ -404,28 +442,28 @@ static void initialize_ethernet(void) {
}
namespace Effect {
extern const WaveForm_t OffsetPulseWave{gau8_offsetPulse, cu16_TemplateLength};
extern const WaveForm_t InitSlopeWave{gau8_initSlope, cu16_TemplateLength};
extern const WaveForm_t OffsetSlopeWave{gau8_offsetSlope, cu16_TemplateLength};
extern const WaveForm_t FullSlopeWave{gau8_fullSlope, cu16_TemplateLength};
extern const WaveForm_t FullPulseWave{gau8_fullPulse, cu16_TemplateLength};
extern const WaveForm_t OffsetPulseWave{gau8_offsetPulse, cu16_TemplateLength};
extern const WaveForm_t InitSlopeWave{gau8_initSlope, cu16_TemplateLength};
extern const WaveForm_t OffsetSlopeWave{gau8_offsetSlope, cu16_TemplateLength};
extern const WaveForm_t FullSlopeWave{gau8_fullSlope, cu16_TemplateLength};
extern const WaveForm_t FullPulseWave{gau8_fullPulse, cu16_TemplateLength};
const Macro macDemoStart = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macDemoStart = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macDemoPulse = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 2, StateMachine::UpdateIdle, 0xFF},
{64, 1, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
};
const Macro macDemoPulse = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 2, StateMachine::UpdateIdle, 0xFF},
{64, 1, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
};
const Macro macDemoFlicker = {
{16, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateFlicker, 0xFF},
};
}
const Macro macDemoFlicker = {
{16, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateFlicker, 0xFF},
};
} // namespace Effect
void LightingTask() {
ESP_LOGI(TAG, "Start Lighting");
@@ -520,7 +558,20 @@ void MovementTask() {
{LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3},
{GPIO_NUM_21, GPIO_NUM_20, GPIO_NUM_23, GPIO_NUM_22},
};
StepperDriverDrv8833 stepperDriver(stepperPins, MicroSteps, 0.25F);
float power = 0.25F;
// try
// {
// auto pwr = store.getValue(ConfigKeys.motorPower);
// power = std::stof(pwr);
// }
// catch(...)
// {
// std::cerr << e.what() << '\n';
// ESP_LOGI("Stepper", "Applying default");
// }
StepperDriverDrv8833 stepperDriver(stepperPins, MicroSteps, power);
stepperDriver.setPos(0);
StepperConfig stepperCfg{1.8F, MicroSteps};
@@ -583,6 +634,33 @@ void MovementTask() {
// pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(newPos));
// responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StepAt, newPos));
}
} else if (cmd->type == MoveType::Shuffle) {
Syslog::logv(Syslog::Severity::Informational,
"Starting Shuffle mode");
while (true) {
int pos = Random::randomWithIn(1,6);
int profile = Random::randomWithIn(0,3);
if (stepper.isIdle()) {
Syslog::logv(Syslog::Severity::Notice,
"Running Stepper to %i by min%i steps with prof=%i a=%.2f w=%.2f",
pos, activeState.minJumps, activeState.profile, activeState.accel, activeState.speed);
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(0));
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StartMoving, 0));
auto &as = activeState;
watch.moveTo(pos, profile, as.minJumps, as.accel, as.speed);
}
// int delay = Random::randomWithIn(20000,100000)/portTICK_PERIOD_MS;
int delay = Random::randomWithIn(2000,3000)/portTICK_PERIOD_MS;
Syslog::logv(Syslog::Severity::Informational,
"ShuffleMode Wait for %i", delay);
auto cmd = commandQueue.dequeue(delay);
if (cmd) {
if (cmd->type != MoveType::Shuffle) {
commandQueue.enqueue(std::move(cmd));
break;
}
}
}
} else if (cmd->type == MoveType::Demo) {
ESP_LOGI(TAG, "Running Demo");
for (size_t i = ProfileGenerator::Smooth; i < ProfileGenerator::NumProfiles; i++) {
@@ -666,7 +744,7 @@ void onProjectUpdate(SClient::ProjUpdate state, string projectId) {
}
bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) {
return true; // Bypass veto
return true; // Bypass veto
if (!knownType || !createdByClient) { // Don't allow foreign SPITTypes
return false;
}
@@ -913,12 +991,11 @@ void app_main(void) {
initialize_ethernet();
NvsApi::init();
static fos::Task lightingTask(LightingTask, "Lights", 0x8000uL);
static fos::Task movementTask(MovementTask, "Motor", 0x8000uL);
static fos::Task movementTask(MovementTask, "Motor", 0x8000uL, fos::Task::MAX_PRIORITY-4 );
etherActive.take();
fos::Task::delayMs(10000);
ESP_LOGI(TAG, "Start net services");
// esp_log_level_set("SPIT", esp_log_level_t::ESP_LOG_DEBUG);
static int ipVersion = AF_INET;
static fos::TaskT<int> telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096);
@@ -942,10 +1019,8 @@ void app_main(void) {
while (true) {
fos::Task::delayMs(5000);
// ToDo send
Syslog::logv(Syslog::Severity::Notice, "Health state");
// ESP_LOGI(TAG, "Min heap size: %" PRIu32 " / FreeHeap %" PRIu32 "\n",
// ESP_LOGI(TAG, "Min heap size: %u / FreeHeap %lu",
// heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT),
// esp_get_free_heap_size());
Syslog::logv(Syslog::Severity::Notice, "Min heap size: %u / FreeHeap %lu",
heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT),
esp_get_free_heap_size());
}
}
+1
View File
@@ -40,6 +40,7 @@
#include "nvsFunctions.hpp"
#include "mqttClient.hpp"
#include "watchFace.hpp"
#include "random.hpp"
// #include "esp_chip_info.h"
// #include "esp_flash.h"