mirror of
https://github.com/esphome/esphome.git
synced 2024-12-04 20:48:21 +01:00
MAX6921: Replace "intensity" (0-16) with "brightness" in percent
Expose action "set_brightness".
This commit is contained in:
parent
45580f2638
commit
b9ee2b2deb
3 changed files with 80 additions and 41 deletions
|
@ -1,8 +1,8 @@
|
|||
from esphome import pins
|
||||
from esphome import pins, automation
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import display, spi
|
||||
from esphome.const import CONF_ID, CONF_INTENSITY, CONF_LAMBDA
|
||||
from esphome.const import CONF_ID, CONF_BRIGHTNESS, CONF_LAMBDA
|
||||
|
||||
|
||||
DEPENDENCIES = ["spi", "esp32"]
|
||||
|
@ -41,6 +41,8 @@ MAX6921Component = max6921_ns.class_(
|
|||
"MAX6921Component", cg.PollingComponent, spi.SPIDevice
|
||||
)
|
||||
MAX6921ComponentRef = MAX6921Component.operator("ref")
|
||||
SetBrightnessAction = max6921_ns.class_("SetBrightnessAction", automation.Action)
|
||||
|
||||
|
||||
# optional "demo_mode" configuration
|
||||
CONF_DEMO_MODE_OFF = "off"
|
||||
|
@ -105,6 +107,7 @@ OUT_PIN_MAPPING_SCHEMA = cv.Schema(
|
|||
)
|
||||
)
|
||||
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
display.BASIC_DISPLAY_SCHEMA.extend(
|
||||
{
|
||||
|
@ -112,7 +115,7 @@ CONFIG_SCHEMA = (
|
|||
cv.Required(CONF_LOAD_PIN): pins.gpio_input_pin_schema,
|
||||
cv.Required(CONF_BLANK_PIN): pins.internal_gpio_output_pin_schema,
|
||||
cv.Required(CONF_OUT_PIN_MAPPING): OUT_PIN_MAPPING_SCHEMA,
|
||||
cv.Optional(CONF_INTENSITY, default=16): cv.int_range(min=0, max=16),
|
||||
cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.templatable(cv.percentage),
|
||||
cv.Optional(CONF_DEMO_MODE, default=CONF_DEMO_MODE_OFF): cv.enum(
|
||||
DEMO_MODES
|
||||
),
|
||||
|
@ -150,7 +153,7 @@ async def to_code(config):
|
|||
cg.ArrayInitializer(*[tuple[1] for tuple in sorted_list_of_tuples])
|
||||
)
|
||||
)
|
||||
cg.add(var.set_intensity(config[CONF_INTENSITY]))
|
||||
cg.add(var.set_brightness(config[CONF_BRIGHTNESS]))
|
||||
cg.add(var.set_demo_mode(config[CONF_DEMO_MODE]))
|
||||
|
||||
if CONF_LAMBDA in config:
|
||||
|
@ -158,3 +161,34 @@ async def to_code(config):
|
|||
config[CONF_LAMBDA], [(MAX6921ComponentRef, "it")], return_type=cg.void
|
||||
)
|
||||
cg.add(var.set_writer(lambda_))
|
||||
|
||||
|
||||
ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(MAX6921Component),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
ACTION_SET_BRIGHTNESS_SCHEMA = cv.All(
|
||||
automation.maybe_simple_id(
|
||||
ACTION_SCHEMA.extend(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_BRIGHTNESS): cv.templatable(cv.percentage),
|
||||
}
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"max6921.set_brightness", SetBrightnessAction, ACTION_SET_BRIGHTNESS_SCHEMA
|
||||
)
|
||||
async def max6921_set_brightness_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
template_ = await cg.templatable(config[CONF_BRIGHTNESS], args, float)
|
||||
cg.add(var.set_brightness(template_))
|
||||
return var
|
||||
|
|
|
@ -135,19 +135,19 @@ void MAX6921Component::init_display_(void) {
|
|||
const uint8_t PWM_RESOLUTION = 8;
|
||||
|
||||
// setup PWM for blank pin (intensity)...
|
||||
this->display_.intensity.pwm_channel = 0;
|
||||
freq = ledcSetup(this->display_.intensity.pwm_channel, PWM_FREQ_WANTED, PWM_RESOLUTION);
|
||||
this->display_.brightness.pwm_channel = 0;
|
||||
freq = ledcSetup(this->display_.brightness.pwm_channel, PWM_FREQ_WANTED, PWM_RESOLUTION);
|
||||
if (freq != 0) {
|
||||
ledcAttachPin(this->display_.intensity.pwm_pin->get_pin(), this->display_.intensity.pwm_channel);
|
||||
this->display_.intensity.max_duty = pow(2,PWM_RESOLUTION); // max. duty value for given resolution
|
||||
this->display_.intensity.duty_quotient = this->display_.intensity.max_duty / MAX_DISPLAY_INTENSITY; // pre-calc fixed duty quotient (256 / 16)
|
||||
ledcAttachPin(this->display_.brightness.pwm_pin->get_pin(), this->display_.brightness.pwm_channel);
|
||||
this->display_.brightness.max_duty = pow(2,PWM_RESOLUTION); // max. duty value for given resolution
|
||||
this->display_.brightness.duty_quotient = this->display_.brightness.max_duty / MAX_DISPLAY_INTENSITY; // pre-calc fixed duty quotient (256 / 16)
|
||||
ESP_LOGD(TAG, "Prepare intensity PWM: pin=%u, channel=%u, freq=%uHz, resolution=%ubit, duty quotient=%u",
|
||||
this->display_.intensity.pwm_pin->get_pin(),
|
||||
this->display_.intensity.pwm_channel, freq, PWM_RESOLUTION,
|
||||
this->display_.intensity.duty_quotient);
|
||||
this->display_.brightness.pwm_pin->get_pin(),
|
||||
this->display_.brightness.pwm_channel, freq, PWM_RESOLUTION,
|
||||
this->display_.brightness.duty_quotient);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to configure PWM -> set to max. intensity");
|
||||
pinMode(this->display_.intensity.pwm_pin->get_pin(), OUTPUT);
|
||||
pinMode(this->display_.brightness.pwm_pin->get_pin(), OUTPUT);
|
||||
this->disable_blank(); // enable display (max. intensity)
|
||||
}
|
||||
|
||||
|
@ -286,16 +286,16 @@ int MAX6921Component::set_display(uint8_t start_pos, const char *str) {
|
|||
|
||||
void MAX6921Component::update_display_(void) {
|
||||
// handle display intensity...
|
||||
if (this->display_.intensity.config_changed) {
|
||||
if (this->display_.brightness.config_changed) {
|
||||
// calc duty for low-active BLANK pin...
|
||||
uint32_t inverted_duty = this->display_.intensity.max_duty - \
|
||||
this->display_.intensity.duty_quotient * \
|
||||
this->display_.intensity.config_value;
|
||||
ESP_LOGD(TAG, "Change display intensity to %u (off-time duty=%u/%u)",
|
||||
this->display_.intensity.config_value, inverted_duty,
|
||||
this->display_.intensity.max_duty);
|
||||
ledcWrite(this->display_.intensity.pwm_channel, inverted_duty);
|
||||
this->display_.intensity.config_changed = false;
|
||||
uint32_t inverted_duty = this->display_.brightness.max_duty - \
|
||||
this->display_.brightness.max_duty * \
|
||||
this->display_.brightness.config_value;
|
||||
ESP_LOGD(TAG, "Change display brightness to %.1f (off-time duty=%u/%u)",
|
||||
this->display_.brightness.config_value, inverted_duty,
|
||||
this->display_.brightness.max_duty);
|
||||
ledcWrite(this->display_.brightness.pwm_channel, inverted_duty);
|
||||
this->display_.brightness.config_changed = false;
|
||||
}
|
||||
|
||||
// handle demo modes...
|
||||
|
@ -386,7 +386,7 @@ void MAX6921Component::dump_config() {
|
|||
char seg_name[3];
|
||||
ESP_LOGCONFIG(TAG, "MAX6921:");
|
||||
LOG_PIN(" LOAD Pin: ", this->load_pin_);
|
||||
ESP_LOGCONFIG(TAG, " BLANK Pin: GPIO%u", this->display_.intensity.pwm_pin->get_pin());
|
||||
ESP_LOGCONFIG(TAG, " BLANK Pin: GPIO%u", this->display_.brightness.pwm_pin->get_pin());
|
||||
// display segment to DOUTx mapping...
|
||||
for (uint i=0; i<this->display_.seg_to_out_map.size(); i++) {
|
||||
if (i < 7) {
|
||||
|
@ -401,23 +401,19 @@ void MAX6921Component::dump_config() {
|
|||
ESP_LOGCONFIG(TAG, " Display position %2u: OUT%u", i, this->display_.pos_to_out_map[i]);
|
||||
}
|
||||
// ESP_LOGCONFIG(TAG, " Number of digits: %u", this->display_.num_digits);
|
||||
ESP_LOGCONFIG(TAG, " Intensity: %u", this->display_.intensity.config_value);
|
||||
ESP_LOGCONFIG(TAG, " Brightness: %.1f", this->display_.brightness.config_value);
|
||||
ESP_LOGCONFIG(TAG, " Demo mode: %u", this->display_.demo_mode);
|
||||
}
|
||||
|
||||
void MAX6921Component::set_intensity(uint8_t intensity) {
|
||||
void MAX6921Component::set_brightness(float brightness) {
|
||||
if (!this->setup_finished) {
|
||||
ESP_LOGD(TAG, "Set intensity: setup not finished -> discard intensity value");
|
||||
ESP_LOGD(TAG, "Set brightness: setup not finished -> discard brightness value");
|
||||
return;
|
||||
}
|
||||
if (intensity > MAX_DISPLAY_INTENSITY) {
|
||||
ESP_LOGV(TAG, "Invalid intensity: %u (0..%u)", intensity, MAX_DISPLAY_INTENSITY);
|
||||
intensity = MAX_DISPLAY_INTENSITY;
|
||||
}
|
||||
if ((intensity == 0) || (intensity != this->display_.intensity.config_value)) {
|
||||
this->display_.intensity.config_value = intensity;
|
||||
ESP_LOGD(TAG, "Set intensity: %u", this->display_.intensity.config_value);
|
||||
this->display_.intensity.config_changed = true;
|
||||
if ((brightness == 0.0) || (brightness != this->display_.brightness.config_value)) {
|
||||
this->display_.brightness.config_value = brightness;
|
||||
ESP_LOGD(TAG, "Set brightness: %.1f", this->display_.brightness.config_value);
|
||||
this->display_.brightness.config_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/time.h"
|
||||
#include "esphome/components/spi/spi.h"
|
||||
|
@ -20,18 +21,18 @@ enum demo_mode_t {
|
|||
|
||||
typedef struct {
|
||||
InternalGPIOPin *pwm_pin;
|
||||
uint config_value; // intensity from 0..16
|
||||
float config_value; // brightness in percent (0.0-1.0)
|
||||
bool config_changed;
|
||||
uint32_t max_duty;
|
||||
uint32_t duty_quotient;
|
||||
uint8_t pwm_channel;
|
||||
}display_intensity_t;
|
||||
}display_brightness_t;
|
||||
|
||||
typedef struct {
|
||||
std::vector<uint8_t> seg_to_out_map;
|
||||
std::vector<uint8_t> pos_to_out_map;
|
||||
uint num_digits;
|
||||
display_intensity_t intensity;
|
||||
display_brightness_t brightness;
|
||||
uint8_t *out_buf_;
|
||||
size_t out_buf_size_;
|
||||
uint seg_out_smallest;
|
||||
|
@ -52,9 +53,9 @@ class MAX6921Component : public PollingComponent,
|
|||
float get_setup_priority() const override;
|
||||
uint8_t print(uint8_t pos, const char *str);
|
||||
uint8_t print(const char *str);
|
||||
void set_blank_pin(InternalGPIOPin *pin) { this->display_.intensity.pwm_pin = pin; }
|
||||
void set_blank_pin(InternalGPIOPin *pin) { this->display_.brightness.pwm_pin = pin; }
|
||||
void set_brightness(float brightness);
|
||||
void set_demo_mode(demo_mode_t mode) { this->display_.demo_mode = mode; }
|
||||
void set_intensity(uint8_t intensity);
|
||||
void set_load_pin(GPIOPin *load) { this->load_pin_ = load; }
|
||||
void set_num_digits(uint8_t num_digits) { this->display_.num_digits = num_digits; }
|
||||
void set_seg_to_out_pin_map(const std::vector<uint8_t> &pin_map) { this->display_.seg_to_out_map = pin_map; }
|
||||
|
@ -75,10 +76,10 @@ class MAX6921Component : public PollingComponent,
|
|||
display_t display_;
|
||||
uint8_t *ascii_out_data_;
|
||||
void clear_display(int pos=-1);
|
||||
void disable_blank() { digitalWrite(this->display_.intensity.pwm_pin->get_pin(), LOW); } // display on
|
||||
void disable_blank() { digitalWrite(this->display_.brightness.pwm_pin->get_pin(), LOW); } // display on
|
||||
void IRAM_ATTR HOT disable_load() { this->load_pin_->digital_write(false); }
|
||||
static void display_refresh_task(void *pv);
|
||||
void enable_blank() { digitalWrite(this->display_.intensity.pwm_pin->get_pin(), HIGH); } // display off
|
||||
void enable_blank() { digitalWrite(this->display_.brightness.pwm_pin->get_pin(), HIGH); } // display off
|
||||
void IRAM_ATTR HOT enable_load() { this->load_pin_->digital_write(true); }
|
||||
demo_mode_t get_demo_mode(void) { return this->display_.demo_mode; }
|
||||
int set_display(uint8_t pos, const char *str);
|
||||
|
@ -91,5 +92,13 @@ class MAX6921Component : public PollingComponent,
|
|||
void update_display_();
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetBrightnessAction : public Action<Ts...>, public Parented<MAX6921Component> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(float, brightness)
|
||||
|
||||
void play(Ts... x) override { this->parent_->set_brightness(this->brightness_.value(x...)); }
|
||||
};
|
||||
|
||||
|
||||
} // namespace max6921
|
||||
} // namespace esphome
|
||||
|
|
Loading…
Reference in a new issue