mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add backlight handling for lcd_pcf8574 (#573)
* Add backlight handling for lcd_pcf8574 Switch the backlight on or off by calling id(mydisplay).backlight() or id(mydisplay).no_backlight() in lamda functions (assuming mydisplay is the custom id for the LCD). * Use abstract method Co-authored-by: Attila Darazs <attila@darazs.com> Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
		
				
					committed by
					
						 Otto Winter
						Otto Winter
					
				
			
			
				
	
			
			
			
						parent
						
							ebe64e24f1
						
					
				
				
					commit
					30a542e763
				
			| @@ -1,12 +1,11 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import display | ||||
| from esphome.const import CONF_DIMENSIONS, CONF_LAMBDA | ||||
| from esphome.const import CONF_DIMENSIONS | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| lcd_base_ns = cg.esphome_ns.namespace('lcd_base') | ||||
| LCDDisplay = lcd_base_ns.class_('LCDDisplay', cg.PollingComponent) | ||||
| LCDDisplayRef = LCDDisplay.operator('ref') | ||||
|  | ||||
|  | ||||
| def validate_lcd_dimensions(value): | ||||
| @@ -28,8 +27,3 @@ def setup_lcd_display(var, config): | ||||
|     yield cg.register_component(var, config) | ||||
|     yield display.register_display(var, config) | ||||
|     cg.add(var.set_dimensions(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1])) | ||||
|  | ||||
|     if CONF_LAMBDA in config: | ||||
|         lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(LCDDisplayRef, 'it')], | ||||
|                                           return_type=cg.void) | ||||
|         cg.add(var.set_writer(lambda_)) | ||||
|   | ||||
| @@ -107,7 +107,7 @@ void LCDDisplay::update() { | ||||
|   for (uint8_t i = 0; i < this->rows_ * this->columns_; i++) | ||||
|     this->buffer_[i] = ' '; | ||||
|  | ||||
|   this->writer_(*this); | ||||
|   this->call_writer(); | ||||
|   this->display(); | ||||
| } | ||||
| void LCDDisplay::command_(uint8_t value) { this->send(value, false); } | ||||
|   | ||||
| @@ -12,11 +12,8 @@ namespace lcd_base { | ||||
|  | ||||
| class LCDDisplay; | ||||
|  | ||||
| using lcd_writer_t = std::function<void(LCDDisplay &)>; | ||||
|  | ||||
| class LCDDisplay : public PollingComponent { | ||||
|  public: | ||||
|   void set_writer(lcd_writer_t &&writer) { this->writer_ = std::move(writer); } | ||||
|   void set_dimensions(uint8_t columns, uint8_t rows) { | ||||
|     this->columns_ = columns; | ||||
|     this->rows_ = rows; | ||||
| @@ -54,11 +51,11 @@ class LCDDisplay : public PollingComponent { | ||||
|   virtual void send(uint8_t value, bool rs) = 0; | ||||
|  | ||||
|   void command_(uint8_t value); | ||||
|   virtual void call_writer() = 0; | ||||
|  | ||||
|   uint8_t columns_; | ||||
|   uint8_t rows_; | ||||
|   uint8_t *buffer_{nullptr}; | ||||
|   lcd_writer_t writer_; | ||||
| }; | ||||
|  | ||||
| }  // namespace lcd_base | ||||
|   | ||||
| @@ -2,7 +2,8 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import lcd_base | ||||
| from esphome.const import CONF_DATA_PINS, CONF_ENABLE_PIN, CONF_RS_PIN, CONF_RW_PIN, CONF_ID | ||||
| from esphome.const import CONF_DATA_PINS, CONF_ENABLE_PIN, CONF_RS_PIN, CONF_RW_PIN, CONF_ID, \ | ||||
|     CONF_LAMBDA | ||||
|  | ||||
| AUTO_LOAD = ['lcd_base'] | ||||
|  | ||||
| @@ -42,3 +43,9 @@ def to_code(config): | ||||
|     if CONF_RW_PIN in config: | ||||
|         rw = yield cg.gpio_pin_expression(config[CONF_RW_PIN]) | ||||
|         cg.add(var.set_rw_pin(rw)) | ||||
|  | ||||
|     if CONF_LAMBDA in config: | ||||
|         lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], | ||||
|                                           [(GPIOLCDDisplay.operator('ref'), 'it')], | ||||
|                                           return_type=cg.void) | ||||
|         cg.add(var.set_writer(lambda_)) | ||||
|   | ||||
| @@ -8,6 +8,7 @@ namespace lcd_gpio { | ||||
|  | ||||
| class GPIOLCDDisplay : public lcd_base::LCDDisplay { | ||||
|  public: | ||||
|   void set_writer(std::function<void(GPIOLCDDisplay &)> &&writer) { this->writer_ = std::move(writer); } | ||||
|   void setup() override; | ||||
|   void set_data_pins(GPIOPin *d0, GPIOPin *d1, GPIOPin *d2, GPIOPin *d3) { | ||||
|     this->data_pins_[0] = d0; | ||||
| @@ -36,10 +37,13 @@ class GPIOLCDDisplay : public lcd_base::LCDDisplay { | ||||
|   void write_n_bits(uint8_t value, uint8_t n) override; | ||||
|   void send(uint8_t value, bool rs) override; | ||||
|  | ||||
|   void call_writer() override { this->writer_(*this); } | ||||
|  | ||||
|   GPIOPin *rs_pin_{nullptr}; | ||||
|   GPIOPin *rw_pin_{nullptr}; | ||||
|   GPIOPin *enable_pin_{nullptr}; | ||||
|   GPIOPin *data_pins_[8]{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; | ||||
|   std::function<void(GPIOLCDDisplay &)> writer_; | ||||
| }; | ||||
|  | ||||
| }  // namespace lcd_gpio | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import lcd_base, i2c | ||||
| from esphome.const import CONF_ID | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| AUTO_LOAD = ['lcd_base'] | ||||
| @@ -18,3 +18,9 @@ def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield lcd_base.setup_lcd_display(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
|     if CONF_LAMBDA in config: | ||||
|         lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], | ||||
|                                           [(PCF8574LCDDisplay.operator('ref'), 'it')], | ||||
|                                           return_type=cg.void) | ||||
|         cg.add(var.set_writer(lambda_)) | ||||
|   | ||||
| @@ -6,9 +6,13 @@ namespace lcd_pcf8574 { | ||||
|  | ||||
| static const char *TAG = "lcd_pcf8574"; | ||||
|  | ||||
| static const uint8_t LCD_DISPLAY_BACKLIGHT_ON = 0x08; | ||||
| static const uint8_t LCD_DISPLAY_BACKLIGHT_OFF = 0x00; | ||||
|  | ||||
| void PCF8574LCDDisplay::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up PCF8574 LCD Display..."); | ||||
|   if (!this->write_bytes(0x08, nullptr, 0)) { | ||||
|   this->backlight_value_ = LCD_DISPLAY_BACKLIGHT_ON; | ||||
|   if (!this->write_bytes(this->backlight_value_, nullptr, 0)) { | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   } | ||||
| @@ -29,7 +33,7 @@ void PCF8574LCDDisplay::write_n_bits(uint8_t value, uint8_t n) { | ||||
|     // Ugly fix: in the super setup() with n == 4 value needs to be shifted left | ||||
|     value <<= 4; | ||||
|   } | ||||
|   uint8_t data = value | 0x08;  // Enable backlight | ||||
|   uint8_t data = value | this->backlight_value_;  // Set backlight state | ||||
|   this->write_bytes(data, nullptr, 0); | ||||
|   // Pulse ENABLE | ||||
|   this->write_bytes(data | 0x04, nullptr, 0); | ||||
| @@ -41,6 +45,14 @@ void PCF8574LCDDisplay::send(uint8_t value, bool rs) { | ||||
|   this->write_n_bits((value & 0xF0) | rs, 0); | ||||
|   this->write_n_bits(((value << 4) & 0xF0) | rs, 0); | ||||
| } | ||||
| void PCF8574LCDDisplay::backlight() { | ||||
|   this->backlight_value_ = LCD_DISPLAY_BACKLIGHT_ON; | ||||
|   this->write_bytes(this->backlight_value_, nullptr, 0); | ||||
| } | ||||
| void PCF8574LCDDisplay::no_backlight() { | ||||
|   this->backlight_value_ = LCD_DISPLAY_BACKLIGHT_OFF; | ||||
|   this->write_bytes(this->backlight_value_, nullptr, 0); | ||||
| } | ||||
|  | ||||
| }  // namespace lcd_pcf8574 | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -9,13 +9,22 @@ namespace lcd_pcf8574 { | ||||
|  | ||||
| class PCF8574LCDDisplay : public lcd_base::LCDDisplay, public i2c::I2CDevice { | ||||
|  public: | ||||
|   void set_writer(std::function<void(PCF8574LCDDisplay &)> &&writer) { this->writer_ = std::move(writer); } | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   void backlight(); | ||||
|   void no_backlight(); | ||||
|  | ||||
|  protected: | ||||
|   bool is_four_bit_mode() override { return true; } | ||||
|   void write_n_bits(uint8_t value, uint8_t n) override; | ||||
|   void send(uint8_t value, bool rs) override; | ||||
|  | ||||
|   void call_writer() override { this->writer_(*this); } | ||||
|  | ||||
|   // Stores the current state of the backlight. | ||||
|   uint8_t backlight_value_; | ||||
|   std::function<void(PCF8574LCDDisplay &)> writer_; | ||||
| }; | ||||
|  | ||||
| }  // namespace lcd_pcf8574 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user