74HC595 and 74HC165

Finally it works!
Here is my conf for using 32Bit Outputs and 32BitInputs, using 4x74HC595 and 4x74HC165

Because of the channel-numbering (it used to start with 0, i want it to start with 1) i made a little change with the Clock toggeling.

Binswitch.h (for 74HC595):

#include "esphome.h"

//  global variable to store state of bits
uint64_t output_state = 0;
// pins of the Output shift register (74HC595)
const byte outputLatch_pin = 15;
const byte clock_pin = 14;
const byte mosi_pin = 13;

class binSwitch : public Component, public Switch
{
 byte pinNum;
 bool SetBit(bool pinValue, uint64_t number)
 {
   if (pinValue)
     bitSet(output_state, number);
   else
     bitClear(output_state, number);
   SetOutputs();
   return pinValue;
 }
 void SetOutputs()
 {
   digitalWrite(clock_pin, LOW);
   digitalWrite(outputLatch_pin, LOW);
   shiftOut(mosi_pin, clock_pin, LSBFIRST, output_state);
   shiftOut(mosi_pin, clock_pin, LSBFIRST, output_state >> 8);
   shiftOut(mosi_pin, clock_pin, LSBFIRST, output_state >> 16);
   shiftOut(mosi_pin, clock_pin, LSBFIRST, output_state >> 24);
   digitalWrite(outputLatch_pin, HIGH);
 }
public:
 // pin - output pin of the shift register (0..31)
 binSwitch(byte pin) { pinNum = pin; publish_state(false);}
 void setup() override
 {
   publish_state(false);
   pinMode(outputLatch_pin, OUTPUT);
   pinMode(clock_pin, OUTPUT);
   pinMode(mosi_pin, OUTPUT);
   digitalWrite(outputLatch_pin, HIGH);
   SetOutputs();
 }
 void write_state(bool state) override
 {
   publish_state(SetBit(state, pinNum));
 }
};

and 74HC165.h:

#include "esphome.h"

class SN74HC165Component : public PollingComponent, public BinarySensor 
{
  byte pinNum;
  private:
    const byte LATCH = 4;  // ESP pin number that should be connected to pin 1 of 74hc165s
    const byte DATA  = 5;  // ESP pin number that should be connected to pin 9 of first 74hc165
    const byte CLOCK = 2; // ESP pin number that should be connected to pin 2 of 74hc165s

  bool getBit(unsigned long x, byte n) 
  {
    bool value = bitRead(x, n);
    return value;
  }
  
  unsigned long shiftinput= 1;
  unsigned long oldshiftinput= 0;

 public:
  SN74HC165Component (byte pin) : PollingComponent(100) { pinNum = pin; }   // Change the number inside "PollingComponent(100)" to change update interval in miliseconds 
  float get_setup_priority() const override { return esphome::setup_priority::HARDWARE; }

  void setup() override 
  {
    pinMode(LATCH, OUTPUT); 
    pinMode(CLOCK, OUTPUT); 
    pinMode(DATA, INPUT); 
    digitalWrite(CLOCK, LOW); 
    digitalWrite(CLOCK, HIGH); 
    digitalWrite(LATCH, HIGH);
  }

  void update() override 
  {
    digitalWrite(CLOCK, LOW); 
    digitalWrite(CLOCK, HIGH); 
    digitalWrite(LATCH, LOW); 
    digitalWrite(LATCH, HIGH); 

    shiftinput = shiftIn(DATA, CLOCK, LSBFIRST);
    shiftinput |= shiftIn(DATA, CLOCK, LSBFIRST) << 8;
    shiftinput |= shiftIn(DATA, CLOCK, LSBFIRST) << 16;
    shiftinput |= shiftIn(DATA, CLOCK, LSBFIRST) << 24;
    
    if (shiftinput != oldshiftinput) 
    {
      publish_state(getBit(shiftinput, pinNum));
      oldshiftinput = shiftinput;
    }  
  }
};

and here the ESPhome yaml:

esphome:
  name: test_esp_shift
  platform: ESP8266
  board: d1_mini
  includes:
    - binSwitch.h
    - 74HC165.h
    
wifi:
  ssid: "yourSSID"
  password: "yourPW"
  
  manual_ip:
    static_ip: 192.168.2.244
    gateway: 192.168.2.1
    subnet: 255.255.252.0

# Enable Home Assistant API
api:
  password: "yourPW"

ota:
  password: "yourPW"

web_server:
  port: 80


switch:
- platform: custom
  lambda: |-
    auto switch1 = new binSwitch(0);
    auto switch2 = new binSwitch(1);
    auto switch3 = new binSwitch(2);
    auto switch4 = new binSwitch(3);
    auto switch5 = new binSwitch(4);
    auto switch6 = new binSwitch(5);
    auto switch7 = new binSwitch(6);
    auto switch8 = new binSwitch(7);
    auto switch9 = new binSwitch(8);
    auto switch10 = new binSwitch(9);
    auto switch11 = new binSwitch(10);
    auto switch12 = new binSwitch(11);
    auto switch13 = new binSwitch(12);
    auto switch14 = new binSwitch(13);
    auto switch15 = new binSwitch(14);
    auto switch16 = new binSwitch(15);
    auto switch17 = new binSwitch(16);
    auto switch18 = new binSwitch(17);
    auto switch19 = new binSwitch(18);
    auto switch20 = new binSwitch(19);
    auto switch21 = new binSwitch(20);
    auto switch22 = new binSwitch(21);
    auto switch23 = new binSwitch(22);
    auto switch24 = new binSwitch(23);
    auto switch25 = new binSwitch(24);
    auto switch26 = new binSwitch(25);
    auto switch27 = new binSwitch(26);
    auto switch28 = new binSwitch(27);
    auto switch29 = new binSwitch(28);
    auto switch30 = new binSwitch(29);
    auto switch31 = new binSwitch(30);
    auto switch32 = new binSwitch(31);
    App.register_component(switch1);
    App.register_component(switch2);
    App.register_component(switch3);
    App.register_component(switch4);
    App.register_component(switch5);
    App.register_component(switch6);
    App.register_component(switch7);
    App.register_component(switch8);
    App.register_component(switch9);
    App.register_component(switch10);
    App.register_component(switch11);
    App.register_component(switch12);
    App.register_component(switch13);
    App.register_component(switch14);
    App.register_component(switch15);
    App.register_component(switch16);
    App.register_component(switch17);
    App.register_component(switch18);
    App.register_component(switch19);
    App.register_component(switch20);
    App.register_component(switch21);
    App.register_component(switch22);
    App.register_component(switch23);
    App.register_component(switch24);
    App.register_component(switch25);
    App.register_component(switch26);
    App.register_component(switch27);
    App.register_component(switch28);
    App.register_component(switch29);
    App.register_component(switch30);
    App.register_component(switch31);
    App.register_component(switch32);
    return {switch1,switch2,switch3,switch4,switch5,switch6,switch7,switch8,switch9,switch10,switch11,switch12,switch13,switch14,switch15,switch16,switch17,switch18,switch19,switch20,switch21,switch22,switch23,switch24,switch25,switch26,switch27,switch28,switch29,switch30,switch31,switch32};

  switches:
    - name: "Switch 1"
      id: switch_1
    - name: "Switch 2"
      id: switch_2
    - name: "Switch 3"
      id: switch_3
    - name: "Switch 4"
      id: switch_4
    - name: "Switch 5"
      id: switch_5
    - name: "Switch 6"
      id: switch_6
    - name: "Switch 7"
      id: switch_7
    - name: "Switch 8"
      id: switch_8
    - name: "Switch 9"
      id: switch_9
    - name: "Switch 10"
      id: switch_10
    - name: "Switch 11"
      id: switch_11
    - name: "Switch 12"
      id: switch_12
    - name: "Switch 13"
      id: switch_13
    - name: "Switch 14"
      id: switch_14
    - name: "Switch 15"
      id: switch_15
    - name: "Switch 16"
      id: switch_16
    - name: "Switch 17"
      id: switch_17
    - name: "Switch 18"
      id: switch_18
    - name: "Switch 19"
      id: switch_19
    - name: "Switch 20"
      id: switch_20
    - name: "Switch 21"
      id: switch_21
    - name: "Switch 22"
      id: switch_22
    - name: "Switch 23"
      id: switch_23
    - name: "Switch 24"
      id: switch_24
    - name: "Switch 25"
      id: switch_25
    - name: "Switch 26"
      id: switch_26
    - name: "Switch 27"
      id: switch_27
    - name: "Switch 28"
      id: switch_28
    - name: "Switch 29"
      id: switch_29
    - name: "Switch 30"
      id: switch_30
    - name: "Switch 31"
      id: switch_31
    - name: "Switch 32"
      id: switch_32

binary_sensor:
  - platform: custom
    lambda: |-
      auto X01 = new SN74HC165Component(0);
      auto X02 = new SN74HC165Component(1);
      auto X03 = new SN74HC165Component(2);
      auto X04 = new SN74HC165Component(3);
      auto X05 = new SN74HC165Component(4);
      auto X06 = new SN74HC165Component(5);
      auto X07 = new SN74HC165Component(6);
      auto X08 = new SN74HC165Component(7);
      auto X09 = new SN74HC165Component(8);
      auto X10 = new SN74HC165Component(9);
      auto X11 = new SN74HC165Component(10);
      auto X12 = new SN74HC165Component(11);
      auto X13 = new SN74HC165Component(12);
      auto X14 = new SN74HC165Component(13);
      auto X15 = new SN74HC165Component(14);
      auto X16 = new SN74HC165Component(15);
      auto X17 = new SN74HC165Component(16);
      auto X18 = new SN74HC165Component(17);
      auto X19 = new SN74HC165Component(18);
      auto X20 = new SN74HC165Component(19);
      auto X21 = new SN74HC165Component(20);
      auto X22 = new SN74HC165Component(21);
      auto X23 = new SN74HC165Component(22);
      auto X24 = new SN74HC165Component(23);
      auto X25 = new SN74HC165Component(24);
      auto X26 = new SN74HC165Component(25);
      auto X27 = new SN74HC165Component(26);
      auto X28 = new SN74HC165Component(27);
      auto X29 = new SN74HC165Component(28);
      auto X30 = new SN74HC165Component(29);
      auto X31 = new SN74HC165Component(30);
      auto X32 = new SN74HC165Component(31);
      App.register_component(X01);
      App.register_component(X02);
      App.register_component(X03);
      App.register_component(X04);
      App.register_component(X05);
      App.register_component(X06);
      App.register_component(X07);
      App.register_component(X08);
      App.register_component(X09);
      App.register_component(X10);
      App.register_component(X11);
      App.register_component(X12);
      App.register_component(X13);
      App.register_component(X14);
      App.register_component(X15);
      App.register_component(X16);
      App.register_component(X17);
      App.register_component(X18);
      App.register_component(X19);
      App.register_component(X20);
      App.register_component(X21);
      App.register_component(X22);
      App.register_component(X23);
      App.register_component(X24);
      App.register_component(X25);
      App.register_component(X26);
      App.register_component(X27);
      App.register_component(X28);
      App.register_component(X29);
      App.register_component(X30);
      App.register_component(X31);
      App.register_component(X32);
      return {X01,X02,X03,X04,X05,X06,X07,X08,X09,X10,X11,X12,X13,X14,X15,X16,X17,X18,X19,X20,X21,X22,X23,X24,X25,X26,X27,X28,X29,X30,X31,X32};

    binary_sensors:
     - name: "Input 1"
     - name: "Input 2"
     - name: "Input 3"
     - name: "Input 4"
     - name: "Input 5"
     - name: "Input 6"
     - name: "Input 7"
     - name: "Input 8"
     - name: "Input 9"
     - name: "Input 10"
     - name: "Input 11"
     - name: "Input 12"
     - name: "Input 13"
     - name: "Input 14"
     - name: "Input 15"
     - name: "Input 16"
     - name: "Input 17"
     - name: "Input 18"
     - name: "Input 19"
     - name: "Input 20"
     - name: "Input 21"
     - name: "Input 22"
     - name: "Input 23"
     - name: "Input 24"
     - name: "Input 25"
     - name: "Input 26"
     - name: "Input 27"
     - name: "Input 28"
     - name: "Input 29"
     - name: "Input 30"
     - name: "Input 31"
     - name: "Input 32"     

in HA there are two Cards:
Outputs:

type: entities
entities:
  - entity: switch.switch_1
  - entity: switch.switch_2
  - entity: switch.switch_3
  - entity: switch.switch_4
  - entity: switch.switch_5
  - entity: switch.switch_6
  - entity: switch.switch_7
  - entity: switch.switch_8
  - entity: switch.switch_9
  - entity: switch.switch_10
  - entity: switch.switch_11
  - entity: switch.switch_12
  - entity: switch.switch_13
  - entity: switch.switch_14
  - entity: switch.switch_15
  - entity: switch.switch_16
  - entity: switch.switch_17
  - entity: switch.switch_18
  - entity: switch.switch_19
  - entity: switch.switch_20
  - entity: switch.switch_21
  - entity: switch.switch_22
  - entity: switch.switch_23
  - entity: switch.switch_24
  - entity: switch.switch_25
  - entity: switch.switch_26
  - entity: switch.switch_27
  - entity: switch.switch_28
  - entity: switch.switch_29
  - entity: switch.switch_30
  - entity: switch.switch_31
  - entity: switch.switch_32
state_color: true
title: ESP Shiftboard Outputs

and for Inputs:

type: entities
entities:
  - entity: binary_sensor.input_1
  - entity: binary_sensor.input_2
  - entity: binary_sensor.input_3
  - entity: binary_sensor.input_4
  - entity: binary_sensor.input_5
  - entity: binary_sensor.input_6
  - entity: binary_sensor.input_7
  - entity: binary_sensor.input_8
  - entity: binary_sensor.input_9
  - entity: binary_sensor.input_10
  - entity: binary_sensor.input_11
  - entity: binary_sensor.input_12
  - entity: binary_sensor.input_13
  - entity: binary_sensor.input_14
  - entity: binary_sensor.input_15
  - entity: binary_sensor.input_16
  - entity: binary_sensor.input_17
  - entity: binary_sensor.input_18
  - entity: binary_sensor.input_19
  - entity: binary_sensor.input_20
  - entity: binary_sensor.input_21
  - entity: binary_sensor.input_22
  - entity: binary_sensor.input_23
  - entity: binary_sensor.input_24
  - entity: binary_sensor.input_25
  - entity: binary_sensor.input_26
  - entity: binary_sensor.input_27
  - entity: binary_sensor.input_28
  - entity: binary_sensor.input_29
  - entity: binary_sensor.input_30
  - entity: binary_sensor.input_31
  - entity: binary_sensor.input_32
state_color: true
title: ESP Shiftboard Inputs

I hope this helps someone!

2 Likes