mirror of https://github.com/esphome/esphome.git
Merge b1e955ce6e
into c7c0d97a5e
This commit is contained in:
commit
77b1cb5974
|
@ -403,6 +403,7 @@ esphome/components/version/* @esphome/core
|
|||
esphome/components/voice_assistant/* @jesserockz
|
||||
esphome/components/wake_on_lan/* @willwill2will54
|
||||
esphome/components/waveshare_epaper/* @clydebarrow
|
||||
esphome/components/waveshare_epaper_1in9_i2c/* @nanomad
|
||||
esphome/components/web_server_base/* @OttoWinter
|
||||
esphome/components/web_server_idf/* @dentra
|
||||
esphome/components/weikai/* @DrCoolZic
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CODEOWNERS = ["@nanomad"]
|
|
@ -0,0 +1,76 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import display, i2c
|
||||
from esphome.const import (
|
||||
CONF_BUSY_PIN,
|
||||
CONF_FULL_UPDATE_EVERY,
|
||||
CONF_I2C_ID,
|
||||
CONF_ID,
|
||||
CONF_LAMBDA,
|
||||
CONF_RESET_PIN,
|
||||
)
|
||||
|
||||
UNITS = {
|
||||
"f": "f",
|
||||
"c": "c",
|
||||
}
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
waveshare_epaper_1in9_i2c_ns = cg.esphome_ns.namespace("waveshare_epaper_1in9_i2c")
|
||||
WaveShareEPaper1in9I2C = waveshare_epaper_1in9_i2c_ns.class_(
|
||||
"WaveShareEPaper1in9I2C", cg.PollingComponent
|
||||
)
|
||||
WaveShareEPaper1in9I2CRef = WaveShareEPaper1in9I2C.operator("ref")
|
||||
|
||||
|
||||
CONF_COMMAND_ADDRESS = "command_address"
|
||||
CONF_DATA_ADDRESS = "data_address"
|
||||
CONF_TEMPERATURE_UNIT = "temperature_unit"
|
||||
|
||||
CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(WaveShareEPaper1in9I2C),
|
||||
cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Required(CONF_BUSY_PIN): pins.gpio_input_pin_schema,
|
||||
cv.GenerateID(CONF_I2C_ID): cv.use_id(i2c.I2CBus),
|
||||
cv.Optional(CONF_COMMAND_ADDRESS, default=0x3C): cv.int_range(min=0, max=0xFF),
|
||||
cv.Optional(CONF_DATA_ADDRESS, default=0x3D): cv.int_range(min=0, max=0xFF),
|
||||
cv.Optional(CONF_FULL_UPDATE_EVERY): cv.uint32_t,
|
||||
cv.Optional(CONF_TEMPERATURE_UNIT, default="c"): cv.enum(UNITS),
|
||||
}
|
||||
).extend(cv.polling_component_schema("1s"))
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await display.register_display(var, config)
|
||||
|
||||
reset_pin = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||
cg.add(var.set_reset_pin(reset_pin))
|
||||
|
||||
busy_pin = await cg.gpio_pin_expression(config[CONF_BUSY_PIN])
|
||||
cg.add(var.set_busy_pin(busy_pin))
|
||||
|
||||
i2c_bus = await cg.get_variable(config[CONF_I2C_ID])
|
||||
|
||||
command_address = config[CONF_COMMAND_ADDRESS]
|
||||
cg.add(var.create_command_device(i2c_bus, command_address))
|
||||
|
||||
data_address = config[CONF_DATA_ADDRESS]
|
||||
cg.add(var.create_data_device(i2c_bus, data_address))
|
||||
|
||||
temperature_unit = config[CONF_TEMPERATURE_UNIT]
|
||||
cg.add(var.set_temperature_unit(temperature_unit))
|
||||
|
||||
if CONF_FULL_UPDATE_EVERY in config:
|
||||
cg.add(var.set_full_update_every(config[CONF_FULL_UPDATE_EVERY]))
|
||||
|
||||
if CONF_LAMBDA in config:
|
||||
lambda_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA],
|
||||
[(WaveShareEPaper1in9I2CRef, "it")],
|
||||
return_type=cg.void,
|
||||
)
|
||||
cg.add(var.set_writer(lambda_))
|
|
@ -0,0 +1,66 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
#include "i2c_commands.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace waveshare_epaper_1in9_i2c {
|
||||
|
||||
static const int16_t TEMPERATURE_X10_MIN = -99;
|
||||
static const int16_t TEMPERATURE_X10_MAX = 1999;
|
||||
|
||||
static const int16_t HUMIDITY_X10_MIN = -99;
|
||||
static const int16_t HUMIDITY_X10_MAX = 999;
|
||||
|
||||
static const unsigned LUT_SIZE = 7;
|
||||
|
||||
// 5S waveform for better anti-ghosting
|
||||
static const uint8_t LUT_5S[LUT_SIZE] = {CMD_WAVEFORM_SET, 0x28, 0x20, 0xA8, 0xA0, 0x50, 0x65};
|
||||
|
||||
// White extinction diagram + black out diagram
|
||||
static const uint8_t LUT_DU_WB[LUT_SIZE] = {CMD_WAVEFORM_SET, 0x80, 0x00, 0xC0, 0x80, 0x80, 0x62};
|
||||
|
||||
static const unsigned FRAMEBUFFER_SIZE = 15;
|
||||
|
||||
static const uint8_t CHAR_EMPTY = 0x00;
|
||||
static const uint8_t CHAR_CELSIUS = 0x05;
|
||||
static const uint8_t CHAR_FAHRENHEIT = 0x06;
|
||||
|
||||
static const unsigned CHAR_SLOTS = 2;
|
||||
static const uint8_t CHAR_MINUS_SIGN[CHAR_SLOTS] = {0b01000100, 0b00000};
|
||||
static const uint8_t CHAR_DIGITS[10][CHAR_SLOTS] = {
|
||||
{0xbf, 0xff}, // 0
|
||||
{0x00, 0xff}, // 1
|
||||
{0xfd, 0x17}, // 2
|
||||
{0xf5, 0xff}, // 3
|
||||
{0x47, 0xff}, // 4
|
||||
{0xf7, 0x1d}, // 5
|
||||
{0xff, 0x1d}, // 6
|
||||
{0x21, 0xff}, // 7
|
||||
{0xff, 0xff}, // 8
|
||||
{0xf7, 0xff}, // 9
|
||||
};
|
||||
|
||||
static const unsigned TEMPERATURE_DIGITS_LEN = 4;
|
||||
static const unsigned HUMIDITY_DIGITS_LEN = 3;
|
||||
|
||||
static const unsigned TEMPERATURE_DOT_INDEX = 4;
|
||||
static const unsigned HUMIDITY_DOT_IDX = 8;
|
||||
static const unsigned HUMIDITY_PERCENTAGE_IDX = 10;
|
||||
static const unsigned INDICATORS_IDX = 13; // Framebuffer position for °C/F/low power/BT indicators
|
||||
|
||||
// Bitmask to show the decimal dot
|
||||
static const unsigned DOT_MASK = 0b0000000000100000;
|
||||
|
||||
// Bitmask to show humidity % sign
|
||||
static const unsigned PERCENT_MASK = 0b0000000000100000;
|
||||
|
||||
// Bitmask to enable the low power indicator (empty battery symbol)
|
||||
static const unsigned LOW_POWER_ON_MASK = 0b0000000000010000;
|
||||
|
||||
// Bitmask to enable the BT indicator
|
||||
static const unsigned BT_ON_MASK = 0b0000000000001000;
|
||||
|
||||
} // namespace waveshare_epaper_1in9_i2c
|
||||
} // namespace esphome
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "display_constants.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace waveshare_epaper_1in9_i2c {
|
||||
|
||||
static inline uint8_t get_pixel(int number, int order) { return number < 0 ? CHAR_EMPTY : CHAR_DIGITS[number][order]; }
|
||||
|
||||
} // namespace waveshare_epaper_1in9_i2c
|
||||
} // namespace esphome
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace waveshare_epaper_1in9_i2c {
|
||||
|
||||
static const uint8_t CMD_POWER_OFF = 0x28;
|
||||
static const uint8_t CMD_POWER_ON = 0x2B;
|
||||
|
||||
static const uint8_t CMD_RAM_ADDR_0 = 0x40;
|
||||
|
||||
static const uint8_t CMD_WAVEFORM_SET = 0x82;
|
||||
|
||||
static const uint8_t CMD_DCDC_BOOST_X8 = 0xA7;
|
||||
|
||||
static const uint8_t CMD_DATA_1_LATCH_OFF = 0xA8;
|
||||
static const uint8_t CMD_DATA_1_LATCH_ON = 0xA9;
|
||||
|
||||
static const uint8_t CMD_DATA_2_LATCH_OFF = 0xAA;
|
||||
static const uint8_t CMD_DATA_2_LATCH_ON = 0xAB;
|
||||
|
||||
static const uint8_t CMD_SLEEP_OFF = 0xAC;
|
||||
static const uint8_t CMD_SLEEP_ON = 0xAD;
|
||||
|
||||
static const uint8_t CMD_DISPLAY_OFF = 0xAE;
|
||||
static const uint8_t CMD_DISPLAY_ON = 0xAF;
|
||||
|
||||
} // namespace waveshare_epaper_1in9_i2c
|
||||
} // namespace esphome
|
|
@ -0,0 +1,305 @@
|
|||
#include "waveshare_epaper_1in9_i2c.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include "i2c_commands.h"
|
||||
#include "display_utils.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace waveshare_epaper_1in9_i2c {
|
||||
|
||||
static const char *const TAG = "waveshare_epaper_1in9_i2c";
|
||||
|
||||
void WaveShareEPaper1in9I2C::setup() {
|
||||
ESP_LOGD(TAG, "Setting up WaveShareEPaper1in9I2C...");
|
||||
this->reset_pin_->setup();
|
||||
this->busy_pin_->setup();
|
||||
this->init_screen_();
|
||||
this->write_lut_(LUT_5S);
|
||||
this->wait_for_idle_();
|
||||
this->display();
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::update() {
|
||||
ESP_LOGV(TAG, "WaveShareEPaper1in9I2C::update Called...");
|
||||
|
||||
if (this->writer_.has_value()) {
|
||||
(*this->writer_)(*this);
|
||||
}
|
||||
|
||||
this->display();
|
||||
}
|
||||
|
||||
void HOT WaveShareEPaper1in9I2C::display() {
|
||||
if (this->display_state_.is_changed()) {
|
||||
this->display_state_.flip();
|
||||
|
||||
ESP_LOGD(TAG, "WaveShareEPaper1in9I2C::update Display has changed, performing a refresh...");
|
||||
|
||||
int16_t temperature = this->display_state_.temperature_x10.current;
|
||||
bool valid_temperature = temperature >= TEMPERATURE_X10_MIN && temperature <= TEMPERATURE_X10_MAX;
|
||||
bool temperature_minus_sign = valid_temperature && temperature < 0;
|
||||
temperature = abs(temperature);
|
||||
|
||||
int16_t humidity = this->display_state_.humidity_x10.current;
|
||||
bool valid_humidity = humidity >= HUMIDITY_X10_MIN && humidity <= HUMIDITY_X10_MAX;
|
||||
bool humidity_minus_sign = valid_humidity && humidity < 0;
|
||||
humidity = abs(humidity);
|
||||
|
||||
int temperature_digits[TEMPERATURE_DIGITS_LEN] = {-1, -1, -1, -1};
|
||||
int humidity_digits[HUMIDITY_DIGITS_LEN] = {-1, -1, -1};
|
||||
|
||||
if (valid_temperature) {
|
||||
ESP_LOGV(TAG, "WaveShareEPaper1in9I2C::update Temperature is valid, extracting digits (%d)...", temperature);
|
||||
|
||||
temperature_digits[3] = temperature % 10;
|
||||
temperature_digits[2] = (temperature % 100) / 10;
|
||||
temperature_digits[1] = (temperature % 1000) / 100;
|
||||
temperature_digits[0] = temperature / 1000;
|
||||
|
||||
// Hide leading zeros
|
||||
if (temperature_digits[0] == 0) {
|
||||
temperature_digits[0] = -1;
|
||||
if (temperature_digits[1] == 0) {
|
||||
temperature_digits[1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG, "WaveShareEPaper1in9I2C::update Temperature digits: %d %d %d %d", temperature_digits[0],
|
||||
temperature_digits[1], temperature_digits[2], temperature_digits[3]);
|
||||
}
|
||||
|
||||
if (valid_humidity) {
|
||||
ESP_LOGV(TAG, "WaveShareEPaper1in9I2C::update Humidity is valid, extracting digits (%d)...", humidity);
|
||||
|
||||
humidity_digits[2] = humidity % 10;
|
||||
humidity_digits[1] = (humidity % 100) / 10;
|
||||
humidity_digits[0] = humidity / 100;
|
||||
|
||||
// Hide leading zeros
|
||||
if (humidity_digits[0] == 0) {
|
||||
humidity_digits[0] = -1;
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG, "WaveShareEPaper1in9I2C::update Humidity digits: %d %d %d", humidity_digits[0], humidity_digits[1],
|
||||
humidity_digits[2]);
|
||||
}
|
||||
|
||||
uint8_t new_image[FRAMEBUFFER_SIZE] = {
|
||||
temperature_minus_sign ? CHAR_EMPTY : get_pixel(temperature_digits[0], 1),
|
||||
temperature_minus_sign ? CHAR_MINUS_SIGN[0] : get_pixel(temperature_digits[1], 0),
|
||||
temperature_minus_sign ? CHAR_MINUS_SIGN[1] : get_pixel(temperature_digits[1], 1),
|
||||
get_pixel(temperature_digits[2], 0),
|
||||
get_pixel(temperature_digits[2], 1),
|
||||
humidity_minus_sign ? CHAR_MINUS_SIGN[0] : get_pixel(humidity_digits[0], 0),
|
||||
humidity_minus_sign ? CHAR_MINUS_SIGN[1] : get_pixel(humidity_digits[0], 1),
|
||||
get_pixel(humidity_digits[1], 0),
|
||||
get_pixel(humidity_digits[1], 1),
|
||||
get_pixel(humidity_digits[2], 0),
|
||||
get_pixel(humidity_digits[2], 1),
|
||||
get_pixel(temperature_digits[3], 0),
|
||||
get_pixel(temperature_digits[3], 1),
|
||||
CHAR_EMPTY, // С°/F°/power/bluetooth
|
||||
CHAR_EMPTY // Position 14 must always be empty
|
||||
};
|
||||
|
||||
if (valid_temperature) {
|
||||
new_image[TEMPERATURE_DOT_INDEX] |= DOT_MASK;
|
||||
if (this->display_state_.display_temperature_unit.current) {
|
||||
new_image[INDICATORS_IDX] |= this->display_state_.is_celsius.current ? CHAR_CELSIUS : CHAR_FAHRENHEIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_humidity) {
|
||||
new_image[HUMIDITY_DOT_IDX] |= DOT_MASK;
|
||||
if (this->display_state_.display_percent.current) {
|
||||
new_image[HUMIDITY_PERCENTAGE_IDX] |= PERCENT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->display_state_.low_power.current) {
|
||||
new_image[INDICATORS_IDX] |= LOW_POWER_ON_MASK;
|
||||
}
|
||||
|
||||
if (this->display_state_.bluetooth.current) {
|
||||
new_image[INDICATORS_IDX] |= BT_ON_MASK;
|
||||
}
|
||||
|
||||
bool partial_refresh = this->at_update_ != 0;
|
||||
this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
|
||||
|
||||
ESP_LOGD(TAG, "WaveShareEPaper1in9I2C::refreshing...");
|
||||
if (partial_refresh) {
|
||||
this->write_lut_(LUT_DU_WB);
|
||||
} else {
|
||||
this->write_lut_(LUT_5S);
|
||||
}
|
||||
this->wait_for_idle_();
|
||||
this->write_screen_(new_image);
|
||||
}
|
||||
|
||||
this->deep_sleep_();
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::reset_screen_() {
|
||||
ESP_LOGV(TAG, "WaveShareEPaper1in9I2C::reset_screen");
|
||||
|
||||
this->send_reset_(true);
|
||||
delay(200); // NOLINT
|
||||
this->send_reset_(false);
|
||||
delay(20);
|
||||
this->send_reset_(true);
|
||||
delay(200); // NOLINT
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the busy_pin goes LOW
|
||||
**/
|
||||
void HOT WaveShareEPaper1in9I2C::wait_for_idle_() {
|
||||
ESP_LOGVV(TAG, "WaveShareEPaper1in9I2C::wait_for_idle_... waiting for screen idle");
|
||||
while (this->busy_pin_->digital_read() != 1) { //=1 BUSY;
|
||||
delay(10);
|
||||
}
|
||||
ESP_LOGVV(TAG, "WaveShareEPaper1in9I2C::wait_for_idle_... screen no longer busy");
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::init_screen_() {
|
||||
ESP_LOGD(TAG, "WaveShareEPaper1in9I2C::init_screen...");
|
||||
this->reset_screen_();
|
||||
this->wait_for_idle_();
|
||||
|
||||
this->send_commands_(&CMD_POWER_ON, 1);
|
||||
delay(10);
|
||||
|
||||
uint8_t data[] = {
|
||||
CMD_DCDC_BOOST_X8, // DCDC Boost x8
|
||||
0xE8 // TSON
|
||||
};
|
||||
this->send_commands_(data, 2);
|
||||
delay(10);
|
||||
|
||||
this->apply_temperature_compensation();
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::apply_temperature_compensation() {
|
||||
ESP_LOGVV(TAG, "WaveShareEPaper1in9I2C::apply_temperature_compensation...");
|
||||
|
||||
if (this->compensation_temp_ < 10) {
|
||||
uint8_t data[] = {0x7E, 0x81, 0xB4};
|
||||
this->send_commands_(data, 3);
|
||||
} else {
|
||||
uint8_t data[] = {0x7E, 0x81, 0xB4};
|
||||
this->send_commands_(data, 3);
|
||||
}
|
||||
|
||||
delay(10);
|
||||
|
||||
uint8_t frame_time;
|
||||
if (this->compensation_temp_ < 5) {
|
||||
frame_time = 0x31; // (49+1)*20ms=1000ms
|
||||
} else if (this->compensation_temp_ < 10) {
|
||||
frame_time = 0x22; // (34+1)*20ms=700ms
|
||||
} else if (this->compensation_temp_ < 15) {
|
||||
frame_time = 0x18; // (24+1)*20ms=500ms;
|
||||
} else if (this->compensation_temp_ < 20) {
|
||||
frame_time = 0x13; // (19+1)*20ms=400ms
|
||||
} else {
|
||||
frame_time = 0x0e; // (14+1)*20ms=300ms
|
||||
}
|
||||
uint8_t data[] = {
|
||||
0xe7, // Set default frame time
|
||||
frame_time // Computed frame time
|
||||
};
|
||||
this->send_commands_(data, 2);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::write_lut_(const uint8_t lut[LUT_SIZE]) {
|
||||
ESP_LOGVV(TAG, "WaveShareEPaper1in9I2C::write_lut...");
|
||||
this->send_commands_(lut, LUT_SIZE);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::write_screen_(const uint8_t framebuffer[FRAMEBUFFER_SIZE]) {
|
||||
ESP_LOGV(TAG, "WaveShareEPaper1in9I2C::write_screen...");
|
||||
uint8_t before_write_data[] = {
|
||||
CMD_SLEEP_OFF, // Close the sleep
|
||||
CMD_POWER_ON, // Turn on the power
|
||||
CMD_RAM_ADDR_0, // Write RAM address
|
||||
CMD_DATA_1_LATCH_ON, // Turn on the first SRAM
|
||||
CMD_DATA_1_LATCH_OFF // Shut down the first SRAM
|
||||
};
|
||||
this->send_commands_(before_write_data, 5);
|
||||
|
||||
// Write the image to the screen
|
||||
this->send_data_(framebuffer, FRAMEBUFFER_SIZE);
|
||||
uint8_t bg_color = this->inverted_colors_ ? 0x03 : 0x00;
|
||||
this->send_data_(&bg_color, 1);
|
||||
|
||||
uint8_t after_write_data_1[] = {
|
||||
CMD_DATA_2_LATCH_ON, // Turn on the second SRAM
|
||||
CMD_DATA_2_LATCH_OFF, // Shut down the second SRAM
|
||||
CMD_DISPLAY_ON // display on
|
||||
};
|
||||
this->send_commands_(after_write_data_1, 3);
|
||||
|
||||
this->wait_for_idle_();
|
||||
|
||||
uint8_t after_write_data_2[] = {
|
||||
CMD_DISPLAY_OFF, // Display off
|
||||
CMD_POWER_OFF, // HV OFF
|
||||
CMD_SLEEP_ON // Sleep in
|
||||
};
|
||||
this->send_commands_(after_write_data_2, 3);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::deep_sleep_() {
|
||||
this->send_commands_(&CMD_POWER_OFF, 1);
|
||||
this->wait_for_idle_();
|
||||
this->send_commands_(&CMD_SLEEP_ON, 1);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::set_temperature_unit(const char *unit) {
|
||||
this->display_state_.is_celsius.future = (strcasecmp(unit, "c") == 0);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::set_temperature(float temperature) {
|
||||
this->display_state_.temperature_x10.future = (int16_t) 10.0 * temperature;
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::set_humidity(float humidity) {
|
||||
this->display_state_.humidity_x10.future = (int16_t) 10.0 * humidity;
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::display_low_power_indicator(bool is_low_power) {
|
||||
this->display_state_.low_power.future = is_low_power;
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::display_bluetooth_indicator(bool is_bluetooth) {
|
||||
this->display_state_.bluetooth.future = is_bluetooth;
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::display_percent(bool display_percent) {
|
||||
this->display_state_.display_percent.future = display_percent;
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::display_temperature_unit(bool display_temperature_unit) {
|
||||
this->display_state_.display_temperature_unit.future = display_temperature_unit;
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Waveshare E-Paper 1.9in I2C");
|
||||
ESP_LOGCONFIG(TAG, " I2C Command Address: 0x%02X", this->command_device_address_);
|
||||
ESP_LOGCONFIG(TAG, " I2C Data Address: 0x%02X", this->data_device_address_);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::send_commands_(const uint8_t *data, uint8_t len, bool stop) {
|
||||
this->command_device_.write(data, len, stop);
|
||||
}
|
||||
|
||||
void WaveShareEPaper1in9I2C::send_data_(const uint8_t *data, uint8_t len, bool stop) {
|
||||
this->data_device_.write(data, len, stop);
|
||||
}
|
||||
} // namespace waveshare_epaper_1in9_i2c
|
||||
} // namespace esphome
|
|
@ -0,0 +1,120 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
#include "display_constants.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace waveshare_epaper_1in9_i2c {
|
||||
|
||||
template<typename T> struct ValueState {
|
||||
T current;
|
||||
T future;
|
||||
|
||||
bool is_changed() { return this->current != this->future; }
|
||||
void flip() { this->current = this->future; }
|
||||
};
|
||||
|
||||
struct DisplayState {
|
||||
ValueState<int16_t> temperature_x10{TEMPERATURE_X10_MAX + 1, TEMPERATURE_X10_MAX + 1};
|
||||
ValueState<int16_t> humidity_x10{HUMIDITY_X10_MAX + 1, HUMIDITY_X10_MAX + 1};
|
||||
ValueState<bool> low_power{false, false};
|
||||
ValueState<bool> bluetooth{false, false};
|
||||
ValueState<bool> is_celsius{true, true};
|
||||
ValueState<bool> display_percent{true, true};
|
||||
ValueState<bool> display_temperature_unit{true, true};
|
||||
|
||||
bool is_changed() {
|
||||
return this->temperature_x10.is_changed() || this->humidity_x10.is_changed() || this->low_power.is_changed() ||
|
||||
this->bluetooth.is_changed() || this->is_celsius.is_changed() || this->display_percent.is_changed() ||
|
||||
this->display_temperature_unit.is_changed();
|
||||
}
|
||||
void flip() {
|
||||
this->temperature_x10.flip();
|
||||
this->humidity_x10.flip();
|
||||
this->low_power.flip();
|
||||
this->bluetooth.flip();
|
||||
this->is_celsius.flip();
|
||||
this->display_percent.flip();
|
||||
this->display_temperature_unit.flip();
|
||||
}
|
||||
};
|
||||
|
||||
class WaveShareEPaper1in9I2C;
|
||||
|
||||
using waveshare_epaper_1in9_i2c_writer_t = std::function<void(WaveShareEPaper1in9I2C &)>;
|
||||
|
||||
class WaveShareEPaper1in9I2C : public PollingComponent {
|
||||
public:
|
||||
void set_writer(waveshare_epaper_1in9_i2c_writer_t &&writer) { this->writer_ = writer; }
|
||||
|
||||
void setup() override;
|
||||
void update() override;
|
||||
void display();
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::PROCESSOR; };
|
||||
|
||||
void create_command_device(i2c::I2CBus *bus, uint8_t address) {
|
||||
this->command_device_.set_i2c_address(address);
|
||||
this->command_device_.set_i2c_bus(bus);
|
||||
this->command_device_address_ = address;
|
||||
}
|
||||
|
||||
void create_data_device(i2c::I2CBus *bus, uint8_t address) {
|
||||
this->data_device_.set_i2c_address(address);
|
||||
this->data_device_.set_i2c_bus(bus);
|
||||
this->data_device_address_ = address;
|
||||
}
|
||||
|
||||
void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void set_busy_pin(GPIOPin *busy_pin) { this->busy_pin_ = busy_pin; }
|
||||
void set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
|
||||
|
||||
void set_temperature_for_compensation(float temp) { this->compensation_temp_ = temp; }
|
||||
void set_temperature(float temp);
|
||||
void set_temperature_unit(const char *unit);
|
||||
|
||||
void set_humidity(float humidity);
|
||||
|
||||
void display_percent(bool display_percent);
|
||||
void display_temperature_unit(bool display_temperature_unit);
|
||||
|
||||
void display_low_power_indicator(bool is_low_power);
|
||||
void display_bluetooth_indicator(bool is_bluetooth);
|
||||
|
||||
void apply_temperature_compensation();
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
float compensation_temp_{20};
|
||||
bool inverted_colors_{false};
|
||||
|
||||
DisplayState display_state_;
|
||||
|
||||
uint32_t full_update_every_{30};
|
||||
uint32_t at_update_{0};
|
||||
|
||||
uint8_t command_device_address_;
|
||||
i2c::I2CDevice command_device_;
|
||||
|
||||
uint8_t data_device_address_;
|
||||
i2c::I2CDevice data_device_;
|
||||
GPIOPin *reset_pin_;
|
||||
GPIOPin *busy_pin_;
|
||||
optional<waveshare_epaper_1in9_i2c_writer_t> writer_{};
|
||||
|
||||
void init_screen_();
|
||||
void reset_screen_();
|
||||
void wait_for_idle_();
|
||||
void write_lut_(const uint8_t lut[LUT_SIZE]);
|
||||
void write_screen_(const uint8_t framebuffer[FRAMEBUFFER_SIZE]);
|
||||
void deep_sleep_();
|
||||
|
||||
void send_commands_(const uint8_t *data, uint8_t len, bool stop = true);
|
||||
void send_data_(const uint8_t *data, uint8_t len, bool stop = true);
|
||||
void send_reset_(bool value) { this->reset_pin_->digital_write(value); };
|
||||
};
|
||||
} // namespace waveshare_epaper_1in9_i2c
|
||||
} // namespace esphome
|
|
@ -666,6 +666,26 @@ display:
|
|||
number: GPIO1
|
||||
allow_other_uses: true
|
||||
|
||||
- platform: waveshare_epaper_1in9_i2c
|
||||
command_address: 0x3C
|
||||
data_address: 0x3D
|
||||
busy_pin:
|
||||
number: GPIO23
|
||||
allow_other_uses: true
|
||||
reset_pin:
|
||||
number: GPIO23
|
||||
allow_other_uses: true
|
||||
update_interval: 5s
|
||||
full_update_every: 30
|
||||
lambda: |-
|
||||
static float value1 = 218.3;
|
||||
it.display_low_power_indicator(true);
|
||||
it.display_bluetooth_indicator(true);
|
||||
it.display_temperature_unit(true);
|
||||
it.display_percent(true);
|
||||
it.set_temperature(value1);
|
||||
it.set_humidity(value1);
|
||||
|
||||
number:
|
||||
- platform: tuya
|
||||
id: tuya_number
|
||||
|
|
Loading…
Reference in New Issue