mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	add support for SN74HC595 shift register (#1083)
* add support for SN74HC595 shift register * fix linter errors * more linter reported issues fixed * hopefully last linter error cleanup * one more linter fix * looks like the linter is always keeping stuff for later, is this the final fix? * add test Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>
This commit is contained in:
		
							
								
								
									
										54
									
								
								esphome/components/sn74hc595/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								esphome/components/sn74hc595/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome import pins | ||||||
|  | from esphome.const import CONF_ID, CONF_NUMBER, CONF_INVERTED, CONF_DATA_PIN, CONF_CLOCK_PIN | ||||||
|  |  | ||||||
|  | DEPENDENCIES = [] | ||||||
|  | MULTI_CONF = True | ||||||
|  |  | ||||||
|  | sn74hc595_ns = cg.esphome_ns.namespace('sn74hc595') | ||||||
|  |  | ||||||
|  | SN74HC595Component = sn74hc595_ns.class_('SN74HC595Component', cg.Component) | ||||||
|  | SN74HC595GPIOPin = sn74hc595_ns.class_('SN74HC595GPIOPin', cg.GPIOPin) | ||||||
|  |  | ||||||
|  | CONF_SN74HC595 = 'sn74hc595' | ||||||
|  | CONF_LATCH_PIN = 'latch_pin' | ||||||
|  | CONF_OE_PIN = 'oe_pin' | ||||||
|  | CONF_SR_COUNT = 'sr_count' | ||||||
|  | CONFIG_SCHEMA = cv.Schema({ | ||||||
|  |     cv.Required(CONF_ID): cv.declare_id(SN74HC595Component), | ||||||
|  |     cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, | ||||||
|  |     cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, | ||||||
|  |     cv.Required(CONF_LATCH_PIN): pins.gpio_output_pin_schema, | ||||||
|  |     cv.Optional(CONF_OE_PIN): pins.gpio_output_pin_schema, | ||||||
|  |     cv.Optional(CONF_SR_COUNT, default=1): cv.int_range(1, 4) | ||||||
|  | }).extend(cv.COMPONENT_SCHEMA) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     yield cg.register_component(var, config) | ||||||
|  |     data_pin = yield cg.gpio_pin_expression(config[CONF_DATA_PIN]) | ||||||
|  |     cg.add(var.set_data_pin(data_pin)) | ||||||
|  |     clock_pin = yield cg.gpio_pin_expression(config[CONF_CLOCK_PIN]) | ||||||
|  |     cg.add(var.set_clock_pin(clock_pin)) | ||||||
|  |     latch_pin = yield cg.gpio_pin_expression(config[CONF_LATCH_PIN]) | ||||||
|  |     cg.add(var.set_latch_pin(latch_pin)) | ||||||
|  |     oe_pin = yield cg.gpio_pin_expression(config[CONF_OE_PIN]) | ||||||
|  |     cg.add(var.set_oe_pin(oe_pin)) | ||||||
|  |     cg.add(var.set_sr_count(config[CONF_SR_COUNT])) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | SN74HC595_OUTPUT_PIN_SCHEMA = cv.Schema({ | ||||||
|  |     cv.Required(CONF_SN74HC595): cv.use_id(SN74HC595Component), | ||||||
|  |     cv.Required(CONF_NUMBER): cv.int_, | ||||||
|  |     cv.Optional(CONF_INVERTED, default=False): cv.boolean, | ||||||
|  | }) | ||||||
|  | SN74HC595_INPUT_PIN_SCHEMA = cv.Schema({}) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pins.PIN_SCHEMA_REGISTRY.register(CONF_SN74HC595, | ||||||
|  |                                    (SN74HC595_OUTPUT_PIN_SCHEMA, SN74HC595_INPUT_PIN_SCHEMA)) | ||||||
|  | def sn74hc595_pin_to_code(config): | ||||||
|  |     parent = yield cg.get_variable(config[CONF_SN74HC595]) | ||||||
|  |     yield SN74HC595GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_INVERTED]) | ||||||
							
								
								
									
										70
									
								
								esphome/components/sn74hc595/sn74hc595.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								esphome/components/sn74hc595/sn74hc595.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | #include "sn74hc595.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace sn74hc595 { | ||||||
|  |  | ||||||
|  | static const char *TAG = "sn74hc595"; | ||||||
|  |  | ||||||
|  | void SN74HC595Component::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up SN74HC595..."); | ||||||
|  |  | ||||||
|  |   if (this->have_oe_pin_) {  // disable output | ||||||
|  |     pinMode(this->oe_pin_->get_pin(), OUTPUT); | ||||||
|  |     digitalWrite(this->oe_pin_->get_pin(), HIGH); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // initialize output pins | ||||||
|  |   pinMode(this->clock_pin_->get_pin(), OUTPUT); | ||||||
|  |   pinMode(this->data_pin_->get_pin(), OUTPUT); | ||||||
|  |   pinMode(this->latch_pin_->get_pin(), OUTPUT); | ||||||
|  |   digitalWrite(this->clock_pin_->get_pin(), LOW); | ||||||
|  |   digitalWrite(this->data_pin_->get_pin(), LOW); | ||||||
|  |   digitalWrite(this->latch_pin_->get_pin(), LOW); | ||||||
|  |  | ||||||
|  |   // send state to shift register | ||||||
|  |   this->write_gpio_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SN74HC595Component::dump_config() { ESP_LOGCONFIG(TAG, "SN74HC595:"); } | ||||||
|  |  | ||||||
|  | bool SN74HC595Component::digital_read_(uint8_t pin) { return bitRead(this->output_bits_, pin); } | ||||||
|  |  | ||||||
|  | void SN74HC595Component::digital_write_(uint8_t pin, bool value) { | ||||||
|  |   bitWrite(this->output_bits_, pin, value); | ||||||
|  |   this->write_gpio_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool SN74HC595Component::write_gpio_() { | ||||||
|  |   for (int i = this->sr_count_ - 1; i >= 0; i--) { | ||||||
|  |     uint8_t data = (uint8_t)(this->output_bits_ >> (8 * i) & 0xff); | ||||||
|  |     shiftOut(this->data_pin_->get_pin(), this->clock_pin_->get_pin(), MSBFIRST, data); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // pulse latch to activate new values | ||||||
|  |   digitalWrite(this->latch_pin_->get_pin(), HIGH); | ||||||
|  |   digitalWrite(this->latch_pin_->get_pin(), LOW); | ||||||
|  |  | ||||||
|  |   // enable output if configured | ||||||
|  |   if (this->have_oe_pin_) { | ||||||
|  |     digitalWrite(this->oe_pin_->get_pin(), LOW); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float SN74HC595Component::get_setup_priority() const { return setup_priority::IO; } | ||||||
|  |  | ||||||
|  | void SN74HC595GPIOPin::setup() {} | ||||||
|  |  | ||||||
|  | bool SN74HC595GPIOPin::digital_read() { return this->parent_->digital_read_(this->pin_) != this->inverted_; } | ||||||
|  |  | ||||||
|  | void SN74HC595GPIOPin::digital_write(bool value) { | ||||||
|  |   this->parent_->digital_write_(this->pin_, value != this->inverted_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SN74HC595GPIOPin::SN74HC595GPIOPin(SN74HC595Component *parent, uint8_t pin, bool inverted) | ||||||
|  |     : GPIOPin(pin, OUTPUT, inverted), parent_(parent) {} | ||||||
|  |  | ||||||
|  | }  // namespace sn74hc595 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										55
									
								
								esphome/components/sn74hc595/sn74hc595.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								esphome/components/sn74hc595/sn74hc595.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/esphal.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace sn74hc595 { | ||||||
|  |  | ||||||
|  | class SN74HC595Component : public Component { | ||||||
|  |  public: | ||||||
|  |   SN74HC595Component() = default; | ||||||
|  |  | ||||||
|  |   void setup() override; | ||||||
|  |   float get_setup_priority() const override; | ||||||
|  |   void dump_config() override; | ||||||
|  |  | ||||||
|  |   void set_data_pin(GPIOPin *pin) { data_pin_ = pin; } | ||||||
|  |   void set_clock_pin(GPIOPin *pin) { clock_pin_ = pin; } | ||||||
|  |   void set_latch_pin(GPIOPin *pin) { latch_pin_ = pin; } | ||||||
|  |   void set_oe_pin(GPIOPin *pin) { | ||||||
|  |     oe_pin_ = pin; | ||||||
|  |     have_oe_pin_ = true; | ||||||
|  |   } | ||||||
|  |   void set_sr_count(uint8_t count) { sr_count_ = count; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   friend class SN74HC595GPIOPin; | ||||||
|  |   bool digital_read_(uint8_t pin); | ||||||
|  |   void digital_write_(uint8_t pin, bool value); | ||||||
|  |   bool write_gpio_(); | ||||||
|  |  | ||||||
|  |   GPIOPin *data_pin_; | ||||||
|  |   GPIOPin *clock_pin_; | ||||||
|  |   GPIOPin *latch_pin_; | ||||||
|  |   GPIOPin *oe_pin_; | ||||||
|  |   uint8_t sr_count_; | ||||||
|  |   bool have_oe_pin_{false}; | ||||||
|  |   uint32_t output_bits_{0x00}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Helper class to expose a SC74HC595 pin as an internal output GPIO pin. | ||||||
|  | class SN74HC595GPIOPin : public GPIOPin { | ||||||
|  |  public: | ||||||
|  |   SN74HC595GPIOPin(SN74HC595Component *parent, uint8_t pin, bool inverted = false); | ||||||
|  |  | ||||||
|  |   void setup() override; | ||||||
|  |   bool digital_read() override; | ||||||
|  |   void digital_write(bool value) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   SN74HC595Component *parent_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace sn74hc595 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -1187,13 +1187,13 @@ light: | |||||||
|             if (initial_run) { |             if (initial_run) { | ||||||
|               it[0] = current_color; |               it[0] = current_color; | ||||||
|             } |             } | ||||||
|              |  | ||||||
|     - wled: |     - wled: | ||||||
|         port: 11111 |         port: 11111 | ||||||
|          |  | ||||||
|     - adalight: |     - adalight: | ||||||
|         uart_id: adalight_uart |         uart_id: adalight_uart | ||||||
|          |  | ||||||
|     - automation: |     - automation: | ||||||
|         name: Custom Effect |         name: Custom Effect | ||||||
|         sequence: |         sequence: | ||||||
| @@ -1465,6 +1465,14 @@ switch: | |||||||
|         id: my_stepper |         id: my_stepper | ||||||
|         position: 0 |         position: 0 | ||||||
|  |  | ||||||
|  |   - platform: gpio | ||||||
|  |     name: "SN74HC595 Pin #0" | ||||||
|  |     pin: | ||||||
|  |       sn74hc595: sn74hc595_hub | ||||||
|  |       # Use pin number 0 | ||||||
|  |       number: 0 | ||||||
|  |       inverted: False | ||||||
|  |  | ||||||
| fan: | fan: | ||||||
|   - platform: binary |   - platform: binary | ||||||
|     output: gpio_26 |     output: gpio_26 | ||||||
| @@ -1715,3 +1723,11 @@ text_sensor: | |||||||
|     name: "BSSID" |     name: "BSSID" | ||||||
|   mac_address: |   mac_address: | ||||||
|     name: "Mac Address" |     name: "Mac Address" | ||||||
|  |  | ||||||
|  | sn74hc595: | ||||||
|  |   - id: 'sn74hc595_hub' | ||||||
|  |     data_pin: GPIO21 | ||||||
|  |     clock_pin: GPIO23 | ||||||
|  |     latch_pin: GPIO22 | ||||||
|  |     oe_pin: GPIO32 | ||||||
|  |     sr_count: 2 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user