Added PWM live control and get_led_duty_cycle

This commit is contained in:
PhosphorosVR
2025-08-22 01:01:49 +02:00
parent 21e8dbe264
commit 5a201d875e
10 changed files with 84 additions and 6 deletions

View File

@@ -11,5 +11,5 @@ idf_component_register(
INCLUDE_DIRS
"CommandManager"
"CommandManager/commands"
REQUIRES ProjectConfig cJSON CameraManager OpenIrisTasks wifiManager Helpers
REQUIRES ProjectConfig cJSON CameraManager OpenIrisTasks wifiManager Helpers LEDManager
)

View File

@@ -24,6 +24,7 @@ std::unordered_map<std::string, CommandType> commandTypeMap = {
{"switch_mode", CommandType::SWITCH_MODE},
{"get_device_mode", CommandType::GET_DEVICE_MODE},
{"set_led_duty_cycle", CommandType::SET_LED_DUTY_CYCLE},
{"get_led_duty_cycle", CommandType::GET_LED_DUTY_CYCLE},
};
std::function<CommandResult()> CommandManager::createCommand(const CommandType type, std::string_view json) const
@@ -93,6 +94,9 @@ std::function<CommandResult()> CommandManager::createCommand(const CommandType t
case CommandType::SET_LED_DUTY_CYCLE:
return [this, json]
{ return updateLEDDutyCycleCommand(this->registry, json); };
case CommandType::GET_LED_DUTY_CYCLE:
return [this]
{ return getLEDDutyCycleCommand(this->registry); };
default:
return nullptr;
}

View File

@@ -45,6 +45,7 @@ enum class CommandType
SWITCH_MODE,
GET_DEVICE_MODE,
SET_LED_DUTY_CYCLE,
GET_LED_DUTY_CYCLE,
};
class CommandManager

View File

@@ -8,7 +8,8 @@ enum class DependencyType
{
project_config,
camera_manager,
wifi_manager
wifi_manager,
led_manager
};
class DependencyRegistry

View File

@@ -1,4 +1,5 @@
#include "device_commands.hpp"
#include "LEDManager.hpp"
// Implementation inspired by SummerSigh work, initial PR opened in openiris repo, adapted to this rewrite
CommandResult setDeviceModeCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload)
@@ -96,6 +97,13 @@ CommandResult updateLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> regi
const auto projectConfig = registry->resolve<ProjectConfig>(DependencyType::project_config);
projectConfig->setLEDDUtyCycleConfig(dutyCycle);
// Try to apply the change live via LEDManager if available
auto ledMgr = registry->resolve<LEDManager>(DependencyType::led_manager);
if (ledMgr)
{
ledMgr->setExternalLEDDutyCycle(static_cast<uint8_t>(dutyCycle));
}
cJSON_Delete(parsedJson);
return CommandResult::getSuccessResult("LED duty cycle set");
@@ -107,6 +115,15 @@ CommandResult restartDeviceCommand()
return CommandResult::getSuccessResult("Device restarted");
}
CommandResult getLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry)
{
const auto projectConfig = registry->resolve<ProjectConfig>(DependencyType::project_config);
const auto deviceCfg = projectConfig->getDeviceConfig();
int duty = deviceCfg.led_external_pwm_duty_cycle;
auto result = std::format("{{ \"led_external_pwm_duty_cycle\": {} }}", duty);
return CommandResult::getSuccessResult(result);
}
CommandResult startStreamingCommand()
{
activateStreaming(false); // Don't disable setup interfaces by default

View File

@@ -14,6 +14,7 @@ CommandResult setDeviceModeCommand(std::shared_ptr<DependencyRegistry> registry,
CommandResult updateOTACredentialsCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload);
CommandResult updateLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload);
CommandResult getLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry);
CommandResult restartDeviceCommand();

View File

@@ -177,6 +177,29 @@ void LEDManager::toggleLED(const bool state) const
gpio_set_level(blink_led_pin, state);
}
void LEDManager::setExternalLEDDutyCycle(uint8_t dutyPercent)
{
#ifdef CONFIG_LED_EXTERNAL_CONTROL
dutyPercent = std::min<uint8_t>(100, dutyPercent);
const uint32_t dutyCycle = (static_cast<uint32_t>(dutyPercent) * 255) / 100;
ESP_LOGI(LED_MANAGER_TAG, "Updating external LED duty to %u%% (raw %lu)", dutyPercent, dutyCycle);
// Persist into config immediately so it survives reboot
if (this->deviceConfig)
{
this->deviceConfig->setLEDDUtyCycleConfig(dutyPercent);
}
// Apply to LEDC hardware live
// We configured channel 0 in setup with LEDC_LOW_SPEED_MODE
ESP_ERROR_CHECK_WITHOUT_ABORT(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, dutyCycle));
ESP_ERROR_CHECK_WITHOUT_ABORT(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
#else
(void)dutyPercent; // unused
ESP_LOGW(LED_MANAGER_TAG, "CONFIG_LED_EXTERNAL_CONTROL not enabled; ignoring duty update");
#endif
}
void HandleLEDDisplayTask(void *pvParameter)
{
auto *ledManager = static_cast<LEDManager *>(pvParameter);

View File

@@ -48,6 +48,10 @@ public:
void handleLED();
size_t getTimeToDelayFor() const { return timeToDelayFor; }
// Apply new external LED PWM duty cycle immediately (0-100)
void setExternalLEDDutyCycle(uint8_t dutyPercent);
uint8_t getExternalLEDDutyCycle() const { return deviceConfig ? deviceConfig->getDeviceConfig().led_external_pwm_duty_cycle : 0; }
private:
void toggleLED(bool state) const;
void displayCurrentPattern();