Add TM1561 support (#893)

* Add TM1561 support

* Fixed after clang-tidy

* Fixed after clang-tidy

* Fixed after clang-tidy, updated lib_deps

* Fixed after clang-tidy, updated formatting

* Added actions, removed from display domain

* Protected methods naming

* float casting

* float casting
This commit is contained in:
Evgeny 2019-12-04 13:11:53 +01:00 committed by Otto Winter
parent 7f895abc24
commit 31d964c16a
7 changed files with 215 additions and 0 deletions

3
.gitignore vendored
View file

@ -10,6 +10,9 @@ __pycache__/
*.sublime-project *.sublime-project
*.sublime-workspace *.sublime-workspace
# Intellij Idea
.idea
# Hide some OS X stuff # Hide some OS X stuff
.DS_Store .DS_Store
.AppleDouble .AppleDouble

View file

@ -0,0 +1,61 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins, automation
from esphome.const import CONF_ID, CONF_CLK_PIN, CONF_LEVEL, CONF_BRIGHTNESS
tm1651_ns = cg.esphome_ns.namespace('tm1651')
TM1651Display = tm1651_ns.class_('TM1651Display', cg.Component)
SetLevelAction = tm1651_ns.class_('SetLevelAction', automation.Action)
SetBrightnessAction = tm1651_ns.class_('SetBrightnessAction', automation.Action)
validate_level = cv.All(cv.int_range(min=0, max=100))
TM1651_BRIGHTNESS_OPTIONS = {
1: TM1651Display.TM1651_BRIGHTNESS_LOW,
2: TM1651Display.TM1651_BRIGHTNESS_MEDIUM,
3: TM1651Display.TM1651_BRIGHTNESS_HIGH
}
CONF_DIO_PIN = 'dio_pin'
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(TM1651Display),
cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_schema,
cv.Required(CONF_DIO_PIN): pins.internal_gpio_output_pin_schema,
})
def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
clk_pin = yield cg.gpio_pin_expression(config[CONF_CLK_PIN])
cg.add(var.set_clk_pin(clk_pin))
dio_pin = yield cg.gpio_pin_expression(config[CONF_DIO_PIN])
cg.add(var.set_dio_pin(dio_pin))
# https://platformio.org/lib/show/6865/TM1651
cg.add_library('6865', '1.0.0')
@automation.register_action('tm1651.set_level', SetLevelAction, cv.maybe_simple_value({
cv.GenerateID(): cv.use_id(TM1651Display),
cv.Required(CONF_LEVEL): cv.templatable(validate_level),
}, key=CONF_LEVEL))
def tm1651_set_level_to_code(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
yield cg.register_parented(var, config[CONF_ID])
template_ = yield cg.templatable(config[CONF_LEVEL], args, cg.uint8)
cg.add(var.set_level(template_))
yield var
@automation.register_action('tm1651.set_brightness', SetBrightnessAction, cv.maybe_simple_value({
cv.GenerateID(): cv.use_id(TM1651Display),
cv.Required(CONF_BRIGHTNESS): cv.templatable(validate_level),
}, key=CONF_BRIGHTNESS))
def tm1651_set_brightness_to_code(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
yield cg.register_parented(var, config[CONF_ID])
template_ = yield cg.templatable(config[CONF_BRIGHTNESS], args, cg.uint8)
cg.add(var.set_brightness(template_))
yield var

View file

@ -0,0 +1,69 @@
#include "tm1651.h"
#include "esphome/core/log.h"
namespace esphome {
namespace tm1651 {
static const char *TAG = "tm1651.display";
static const uint8_t TM1651_MAX_LEVEL = 7;
static const uint8_t MAX_INPUT_LEVEL = 100;
static const uint8_t TM1651_BRIGHTNESS_LOW = 0;
static const uint8_t TM1651_BRIGHTNESS_MEDIUM = 2;
static const uint8_t TM1651_BRIGHTNESS_HIGH = 7;
void TM1651Display::setup() {
ESP_LOGCONFIG(TAG, "Setting up TM1651...");
uint8_t clk = clk_pin_->get_pin();
uint8_t dio = dio_pin_->get_pin();
battery_display_ = new TM1651(clk, dio);
battery_display_->init();
battery_display_->clearDisplay();
}
void TM1651Display::dump_config() {
ESP_LOGCONFIG(TAG, "TM1651 Battery Display");
LOG_PIN(" CLK: ", clk_pin_);
LOG_PIN(" DIO: ", dio_pin_);
}
void TM1651Display::set_level(uint8_t new_level) {
this->level_ = calculate_level_(new_level);
this->repaint_();
}
void TM1651Display::set_brightness(uint8_t new_brightness) {
this->brightness_ = calculate_brightness_(new_brightness);
this->repaint_();
}
void TM1651Display::repaint_() {
battery_display_->set(this->brightness_);
battery_display_->displayLevel(this->level_);
}
uint8_t TM1651Display::calculate_level_(uint8_t new_level) {
if (new_level == 0) {
return 0;
}
float calculated_level = TM1651_MAX_LEVEL / (float) (MAX_INPUT_LEVEL / (float) new_level);
return (uint8_t) roundf(calculated_level);
}
uint8_t TM1651Display::calculate_brightness_(uint8_t new_brightness) {
if (new_brightness <= 1) {
return TM1651_BRIGHTNESS_LOW;
} else if (new_brightness == 2) {
return TM1651_BRIGHTNESS_MEDIUM;
} else if (new_brightness >= 3) {
return TM1651_BRIGHTNESS_HIGH;
}
return TM1651_BRIGHTNESS_LOW;
}
} // namespace tm1651
} // namespace esphome

View file

@ -0,0 +1,56 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/esphal.h"
#include "esphome/core/automation.h"
#include <TM1651.h>
namespace esphome {
namespace tm1651 {
class TM1651Display : public Component {
public:
void set_clk_pin(GPIOPin *pin) { clk_pin_ = pin; }
void set_dio_pin(GPIOPin *pin) { dio_pin_ = pin; }
void setup() override;
void dump_config() override;
void set_level(uint8_t);
void set_brightness(uint8_t);
protected:
TM1651 *battery_display_;
GPIOPin *clk_pin_;
GPIOPin *dio_pin_;
uint8_t brightness_;
uint8_t level_;
void repaint_();
uint8_t calculate_level_(uint8_t);
uint8_t calculate_brightness_(uint8_t);
};
template<typename... Ts> class SetLevelAction : public Action<Ts...>, public Parented<TM1651Display> {
public:
TEMPLATABLE_VALUE(uint8_t, level)
void play(Ts... x) override {
auto level = this->level_.value(x...);
this->parent_->set_level(level);
}
};
template<typename... Ts> class SetBrightnessAction : public Action<Ts...>, public Parented<TM1651Display> {
public:
TEMPLATABLE_VALUE(uint8_t, brightness)
void play(Ts... x) override {
auto brightness = this->brightness_.value(x...);
this->parent_->set_brightness(brightness);
}
};
} // namespace tm1651
} // namespace esphome

View file

@ -18,6 +18,7 @@ lib_deps =
NeoPixelBus-esphome@2.5.2 NeoPixelBus-esphome@2.5.2
ESPAsyncTCP-esphome@1.2.2 ESPAsyncTCP-esphome@1.2.2
1655@1.0.2 ; TinyGPSPlus (has name conflict) 1655@1.0.2 ; TinyGPSPlus (has name conflict)
6865@1.0.0 ; TM1651 Battery Display
build_flags = build_flags =
-Wno-reorder -Wno-reorder
-DUSE_WEB_SERVER -DUSE_WEB_SERVER

View file

@ -1454,6 +1454,11 @@ display:
lambda: |- lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height()); it.rectangle(0, 0, it.get_width(), it.get_height());
tm1651:
id: tm1651_battery
clk_pin: GPIO23
dio_pin: GPIO23
remote_receiver: remote_receiver:
pin: GPIO32 pin: GPIO32
dump: all dump: all

View file

@ -138,6 +138,21 @@ api:
then: then:
- dfplayer.random - dfplayer.random
- service: battery_level
variables:
level: int
then:
- tm1651.set_level:
id: tm1651_battery
level: !lambda 'return level;'
- service: battery_brightness
variables:
brightness: int
then:
- tm1651.set_brightness:
id: tm1651_battery
brightness: !lambda 'return brightness;'
wifi: wifi:
ssid: 'MySSID' ssid: 'MySSID'
password: 'password1' password: 'password1'
@ -651,3 +666,8 @@ dfplayer:
dfplayer.is_playing dfplayer.is_playing
then: then:
logger.log: 'Playback finished event' logger.log: 'Playback finished event'
tm1651:
id: tm1651_battery
clk_pin: D6
dio_pin: D5