74HC595 and 74HC165

Perfect !!!, thank you very much, I used the74HC959 to monitor the different radiators and air conditioners in the house, the software works perfect !!! The only bad thing is that I do not understand how it works, even though I have studied C ++ and its classes, but there are many variables in the .h, and I do not understand it. Any guide that can help me?
Thank you.

I have tried to expand to 32 Outputs but some bits are always copied on the outputs (4x74595)

esphome:
  name: test_esp_shift
  platform: ESP8266
  board: d1_mini
  includes:
    - binSwitch.h

wifi:
  ssid: "xxxxxx"
  password: "xxxxxxxxxx"
  
  manual_ip:
    static_ip: 192.168.2.244
    gateway: 192.168.2.1
    subnet: 255.255.252.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Test Esp Fallback Hotspot"
    password: "xxxxxxxxxx"

captive_portal:

# Enable logging
logger:

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

ota:
  password: "xxxxxxx"

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

#include "esphome.h"

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

class binSwitch : public Component, public Switch
{
  long pinNum;
  bool SetBit(bool pinValue, long number)
  {
    if (pinValue)
      bitSet(rele_state, number);
    else
      bitClear(rele_state, number);
    SetRele();
    return pinValue;
  }
  void SetRele()
  {
    digitalWrite(clock_pin, LOW);
    digitalWrite(outputLatch_pin, LOW);
    shiftOut(mosi_pin, clock_pin, MSBFIRST, rele_state);
    digitalWrite(outputLatch_pin, HIGH);
  }

public:
  // pin - output pin of the shift register (0..7)
  binSwitch(long pin) { pinNum = pin; }
  void setup() override
  {
    pinMode(outputLatch_pin, OUTPUT);
    pinMode(clock_pin, OUTPUT);
    pinMode(mosi_pin, OUTPUT);
    digitalWrite(outputLatch_pin, HIGH);
    SetRele();
  }
  void write_state(bool state) override
  {
    publish_state(SetBit(state, pinNum));
  }
};

i also put in some “longs” instead of byte because of 32Bit, but it will not run.
Is there an error?

Can BitSet and BitClear 32Bits or only 8?

I think that the cause of your problem is shiftOut function, because it allow toput only byte. You need to call it 4 times and shift your long state to 8 bites right.

you are right!
this works fine:

#include "esphome.h"

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

class binSwitch : public Component, public Switch
{
  long pinNum;
  bool SetBit(bool pinValue, long number)
  {
    if (pinValue)
      bitSet(rele_state, number);
    else
      bitClear(rele_state, number);
    SetRele();
    return pinValue;
  }
  void SetRele()
  {
    digitalWrite(clock_pin, LOW);
    digitalWrite(outputLatch_pin, LOW);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state >> 8);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state >> 16);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state >> 24);
    digitalWrite(outputLatch_pin, HIGH);
  }

public:
  // pin - output pin of the shift register (0..7)
  binSwitch(long pin) { pinNum = pin; }
  void setup() override
  {
    pinMode(outputLatch_pin, OUTPUT);
    pinMode(clock_pin, OUTPUT);
    pinMode(mosi_pin, OUTPUT);
    digitalWrite(outputLatch_pin, HIGH);
    SetRele();
  }
  void write_state(bool state) override
  {
    publish_state(SetBit(state, pinNum));
  }
};

thank you!

One thing is strange yet:
On the website of esp there are 32 Switches with States like this:
Switch 1 OFF Toggle
Switch 2 OFF Toggle
until
Switch 32 ### Toggle

here (###) is at the start of the esp no state! Only blank!
If i toggle, there comes the right state.
Why is there a blank state at the beginning?

EDIT: seems to be as auto switch can only be 0 to 31…
if i add some more switches it’s also blank from 32 to xx.

Hm… How many 595 you are connected? The long type contains only 4 bytes and 32 bites. If you have connected more than 4 of 595 shift registers, then you should use an array of long for example…

i have connected exactly 4 74HC595 with 32Bits.

Then I see no problem. You add 32 switches from 0 to 31 and everything should work.

May be need to override get_state or something else, like how the write_state:

  void write_state(bool state) override
  {
    publish_state(SetBit(state, pinNum));
  }

Try to change the constructor:

binSwitch(byte pin) { 
  pinNum = pin;
  publish_state(false);
}

there is no change if i change the contructor.

I also tried to renumber Ch.32 to 0 but that also didn’t change anything.
Here the part of the yaml:

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

and the binSwitch.h:

#include "esphome.h"

//  global variable to store state of bits
uint64_t rele_state = 0;
// pins of the 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(rele_state, number);
    else
      bitClear(rele_state, number);
    SetRele();
    return pinValue;
  }
  void SetRele()
  {
    digitalWrite(clock_pin, LOW);
    digitalWrite(outputLatch_pin, LOW);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state >> 8);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state >> 16);
    shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_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
  {
    pinMode(outputLatch_pin, OUTPUT);
    pinMode(clock_pin, OUTPUT);
    pinMode(mosi_pin, OUTPUT);
    digitalWrite(outputLatch_pin, HIGH);
    SetRele();
  }
  void write_state(bool state) override
  {
    publish_state(SetBit(state, pinNum));
  }
};

Well, it is not important because after the first switching of CH.32 everything is ok.
Just not ‘nice’…

Now I am trying to extend this for 32 Inputs (74HC165)…

@Andrew81

Can you help me setting this up for 32 Inputs?

#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;
// pins of the Input shift register (74HC165)
const byte inputLatch_pin = 4;
const byte clock_pin = 14;
const byte miso_pin = 5;

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);
  }
  uint64_t GetInputs()
  {
	digitalWrite(clock_pin, HIGH);
	digitalWrite(inputLatch_pin, LOW);
	digitalWrite(inputLatch_pin, HIGH);
	return shiftIn(miso_pin, clock_pin, MSBFIRST);
  }
public:
  // pin - output pin of the shift register (0..31)
  binSwitch(byte pin) { pinNum = pin; publish_state(false);}
  void setup() override
  {
    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));
  }
};

Try to insert this call into setup method : publish_state(false);

  uint64_t GetInputs()
  {
	digitalWrite(clock_pin, HIGH);
	digitalWrite(inputLatch_pin, LOW);
	digitalWrite(inputLatch_pin, HIGH);
	return shiftIn(miso_pin, clock_pin, MSBFIRST);
  }

shiftIn is working with byte too. You should call it 4 times and shift result to 8 bites.

Also, I don’t quite understand when you want to call the GetInputs method?
It looks more like 74HC165 needs to be moved to a separate class and inherited from Button.

that also makes no state @Ch.32 :frowning:

I have made 2 Arduino Shields, 32 Outputs and 32 Inputs.
On the Inputs there are some contacts and switches wich i would like to receive in HA.
So i thought one Program for the ESP wich handles both In and Outputs would be great.
Shouldn’t be there Entitys instead of Switches for the Inputs?
And how do i write those 8Bit-shifting? I am always a little confused when using the 165…

First, inputs cannot be switches or buttons. It’s more of a sensor. Therefore, a separate component must be created for the inputs. You also need some kind of polling interval for this sensor. I have not tried to create components for sensors, but I think that nothing complicated should be.

  uint64_t GetInputs()
  {
    uint64_t result = 0;
	digitalWrite(clock_pin, HIGH);
	digitalWrite(inputLatch_pin, LOW);
	digitalWrite(inputLatch_pin, HIGH);
	result = shiftIn(miso_pin, clock_pin, MSBFIRST) << 24;
	result += shiftIn(miso_pin, clock_pin, MSBFIRST) << 16;
	result += shiftIn(miso_pin, clock_pin, MSBFIRST) << 8;
	result += shiftIn(miso_pin, clock_pin, MSBFIRST);
    return result;
  }

Sorry but i can’t get it together to make the right code for the inputs, so please can you help me to get them into the esphome listing?

Can someone help me get this thing running please?

check my comment in here :
https://community.home-assistant.io/t/esphome-input-shift-registers/376116/2

Don’t know if this post MIGHT be helpful?

oh i just saw that today!
Sounds great, i will test it in a few days!

Thank you for sharing!