Skip to content

Commit

Permalink
Merge pull request #782 from SignalK/pwm_output_params
Browse files Browse the repository at this point in the history
Refactor PWMOutput
  • Loading branch information
mairas authored Nov 12, 2024
2 parents 85336c1 + cb568a2 commit 32b0717
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 65 deletions.
6 changes: 2 additions & 4 deletions examples/smart_switch/remote_switch_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "sensesp/transforms/click_type.h"
#include "sensesp/transforms/debounce.h"
#include "sensesp/transforms/press_repeater.h"
#include "sensesp/transforms/repeat_report.h"
#include "sensesp/transforms/repeat.h"
#include "sensesp_app.h"
#include "sensesp_app_builder.h"

Expand Down Expand Up @@ -88,9 +88,7 @@ void setup() {

auto click_type = new ClickType(config_path_button_c);

ConfigItem(click_type)
->set_title("Click Type")
->set_sort_order(1000);
ConfigItem(click_type)->set_title("Click Type")->set_sort_order(1000);

pr->connect_to(click_type)->connect_to(controller->click_consumer_);

Expand Down
2 changes: 1 addition & 1 deletion src/sensesp/controllers/smart_switch_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class SmartSwitchController : public ValueProducer<bool>, FileSystemSaveable {
std::set<SyncPath> sync_paths_;
};

const String ConfigSchema(const SmartSwitchController& obj) {
inline const String ConfigSchema(const SmartSwitchController& obj) {
return R"({"type":"object","properties":{"sync_paths":{"title":"Sync on double click","type":"array","items":{"type":"string"}}} })";
}

Expand Down
45 changes: 18 additions & 27 deletions src/sensesp/system/pwm_output.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "sensesp.h"

#include "pwm_output.h"

#include <algorithm>
Expand All @@ -6,23 +8,22 @@ namespace sensesp {

// For info on frequency and resolution for ESP32, see
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/ledc.html#ledc-api-supported-range-frequency-duty-resolution
constexpr int CHANNEL_FREQUENCY = 5000;
constexpr int CHANNEL_RESOLUTION = 13;
constexpr int PWMRANGE = 4095;

std::map<uint8_t, int8_t> PWMOutput::channel_to_pin_;

PWMOutput::PWMOutput(int pin, int pwm_channel) {
PWMOutput::PWMOutput(int pin, int pwm_channel, int channel_frequency,
int channel_resolution)
: ValueConsumer<float>(),
pwm_channel_{static_cast<uint8_t>(pwm_channel)},
channel_frequency_{channel_frequency},
channel_resolution_{channel_resolution},
pwmrange_{static_cast<int>(pow(2, channel_resolution) - 1)} {
if (pin >= 0) {
default_channel_ = assign_channel(pin, pwm_channel);
pwm_channel_ = assign_channel(pin, pwm_channel);
}
}

void PWMOutput::set(const float& new_value) {
uint8_t pwm_channel = default_channel_;

set_pwm(pwm_channel, new_value);
}
void PWMOutput::set(const float& new_value) { set_pwm(new_value); }

int PWMOutput::assign_channel(int pin, int pwm_channel) {
if (pwm_channel == -1) {
Expand All @@ -40,34 +41,24 @@ int PWMOutput::assign_channel(int pin, int pwm_channel) {
ESP_LOGD(__FILENAME__, "PWM channel %d assigned to pin %d", pwm_channel, pin);

pinMode(pin, OUTPUT);
#ifdef ESP32
ledcSetup(pwm_channel, CHANNEL_FREQUENCY, CHANNEL_RESOLUTION);
ledcSetup(pwm_channel, channel_frequency_, channel_resolution_);
ledcAttachPin(pin, pwm_channel);
#endif

return pwm_channel;
}

void PWMOutput::set_pwm(int pwm_channel, float value) {
void PWMOutput::set_pwm(float value) {
std::map<uint8_t, int8_t>::iterator it;
it = channel_to_pin_.find(pwm_channel);
it = channel_to_pin_.find(pwm_channel_);
if (it != channel_to_pin_.end()) {
int pin = it->second;
int const output_val = value * PWMRANGE;
int const output_val = value * pwmrange_;
ESP_LOGD(__FILENAME__, "Outputting %d to pwm channel %d (pin %d)",
output_val, pwm_channel, pin);

#ifdef ESP32
uint32_t levels = pow(2, CHANNEL_RESOLUTION);
uint32_t duty =
((levels - 1) / PWMRANGE) * std::min(output_val, (int)PWMRANGE);
ledcWrite(pwm_channel, duty);
#else
analogWrite(pin, output_val);
#endif
output_val, pwm_channel_, pin);
ledcWrite(pwm_channel_, output_val);
} else {
ESP_LOGW(__FILENAME__, "No pin assigned to channel %d. Ignoring set_pwm()",
pwm_channel);
pwm_channel_);
}
}

Expand Down
20 changes: 12 additions & 8 deletions src/sensesp/system/pwm_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class PWMOutput : public ValueConsumer<float> {
* to. Pass -1 if you would like the system to auto-select the
* next unassigned pin.
*/
PWMOutput(int pin = -1, int pwm_channel = -1);
PWMOutput(int pin = -1, int pwm_channel = -1, int channel_frequency = 5000,
int channel_resolution = 13);

/**
* Sets the duty cycle of the specified pwm_channel to new_value. If
Expand All @@ -50,6 +51,14 @@ class PWMOutput : public ValueConsumer<float> {
*/
virtual void set(const float& new_value) override;

protected:
int channel_frequency_;
int channel_resolution_;
int pwmrange_;

static std::map<uint8_t, int8_t> channel_to_pin_;
uint8_t pwm_channel_{};

/**
* Assigns the specified GPIO pin to the specified pwm channel.
* @param pin the GPIO pin used for the pwm output
Expand All @@ -59,19 +68,14 @@ class PWMOutput : public ValueConsumer<float> {
* @returns The actual pwm channel assigned to the GPIO pin
* to the pin
*/
static int assign_channel(int pin, int pwm_channel = -1);
int assign_channel(int pin, int pwm_channel = -1);

/**
* Sets duty cycle on specified pwm channel
* @param pwm_channel The pwm_channel assigned to the GPIO pin
* @param value A number between 0.0 and 1.0, where 1.0 is the maximum
* duty cycle the output pin supports.
*/
static void set_pwm(int pwm_channel, float value);

protected:
static std::map<uint8_t, int8_t> channel_to_pin_;
uint8_t default_channel_{};
void set_pwm(float value);
};

} // namespace sensesp
Expand Down
27 changes: 9 additions & 18 deletions src/sensesp/system/rgb_led.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ namespace sensesp {
RgbLed::RgbLed(int led_r_pin, int led_g_pin, int led_b_pin, String config_path,
long int led_on_rgb, long int led_off_rgb, bool common_anode)
: FileSystemSaveable(config_path),
led_r_channel_((led_r_pin < 0) ? -1
: PWMOutput::assign_channel(led_r_pin)),
led_g_channel_((led_g_pin < 0) ? -1
: PWMOutput::assign_channel(led_g_pin)),
led_b_channel_((led_b_pin < 0) ? -1
: PWMOutput::assign_channel(led_b_pin)),
led_r_output_{std::make_shared<PWMOutput>(led_r_pin)},
led_g_output_{std::make_shared<PWMOutput>(led_g_pin)},
led_b_output_{std::make_shared<PWMOutput>(led_b_pin)},
led_on_rgb_{led_on_rgb},
led_off_rgb_{led_off_rgb},
common_anode_{common_anode} {
Expand Down Expand Up @@ -52,20 +49,14 @@ bool RgbLed::from_json(const JsonObject& config) {
}

void RgbLed::set_color(long new_value) {
if (led_r_channel_ >= 0) {
float r = get_pwm(new_value, 16, common_anode_);
PWMOutput::set_pwm(led_r_channel_, r);
}
float r = get_pwm(new_value, 16, common_anode_);
led_r_output_->set(r);

if (led_g_channel_ >= 0) {
float g = get_pwm(new_value, 8, common_anode_);
PWMOutput::set_pwm(led_g_channel_, g);
}
float g = get_pwm(new_value, 8, common_anode_);
led_g_output_->set(g);

if (led_b_channel_ >= 0) {
float b = get_pwm(new_value, 0, common_anode_);
PWMOutput::set_pwm(led_b_channel_, b);
}
float b = get_pwm(new_value, 0, common_anode_);
led_b_output_->set(b);
}

const String ConfigSchema(const RgbLed& obj) {
Expand Down
12 changes: 5 additions & 7 deletions src/sensesp/system/rgb_led.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef SENSESP_SYSTEM_RGB_LED_H
#define SENSESP_SYSTEM_RGB_LED_H

#include "pwm_output.h"
#include "sensesp/system/lambda_consumer.h"
#include "sensesp/ui/config_item.h"
#include "valueconsumer.h"
Expand Down Expand Up @@ -56,9 +57,7 @@ class RgbLed : public FileSystemSaveable {
*/

LambdaConsumer<long> rgb_consumer_ =
LambdaConsumer<long>([this](long new_value) {
set_color(new_value);
});
LambdaConsumer<long>([this](long new_value) { set_color(new_value); });

/**
* Used to set the current display state of the LED with a simple on/off
Expand All @@ -78,15 +77,14 @@ class RgbLed : public FileSystemSaveable {
virtual bool from_json(const JsonObject& config) override;

protected:
int led_r_channel_;
int led_g_channel_;
int led_b_channel_;
std::shared_ptr<PWMOutput> led_r_output_ = nullptr;
std::shared_ptr<PWMOutput> led_g_output_ = nullptr;
std::shared_ptr<PWMOutput> led_b_output_ = nullptr;
long led_on_rgb_;
long led_off_rgb_;
bool common_anode_;

void set_color(long new_value);

};

const String ConfigSchema(const RgbLed& obj);
Expand Down

0 comments on commit 32b0717

Please sign in to comment.