74HC595 and 74HC165

Hi Everyone.

Could somebody help to kick me to the instruction how to describe in yaml the work with 74HC595 (I’m using it for control of 8 switchers) shift out register and 74HC165 (I’m using it for control of 8 buttons) shift in register?

Please do not suggest to use something another hardware. I’m already have the PCB and I want to work with it.

Thanks for any help!

The components are not supported, a custom component should be made for them, so you can do binary_sensors and outputs: - type: binary

Do you know C programming? (Arduino)

yes. On C it is very easy.

byte ReadKey()
{
	digitalWrite(clock_pin, HIGH);
	digitalWrite(inputLatch_pin, LOW);
	digitalWrite(inputLatch_pin, HIGH);
	return shiftIn(miso_pin, clock_pin, MSBFIRST);
}

and

void SetRele()
{
	digitalWrite(clock_pin, LOW);
	digitalWrite(outputLatch_pin, LOW);
	shiftOut(mosi_pin, clock_pin, LSBFIRST, rele_state);
	digitalWrite(outputLatch_pin, HIGH);
}

but I don’t know how to rewrite this code to yaml :frowning:

https://esphome.io/custom/custom_component.html

1 Like

I did a custom component which does port expanding, so basically you have additional binary_sensors and outputs… you might want to check the ape.h (arduino port extender) here.

As the shifters are real world components, I believe they qualify for a bundled component on ESPHome. Please fill in a feature request so we can track this better.

1 Like

Thank you for your answers. I’ll try to create a custom component.

Ehoo! :slight_smile: Thank you very much again!

@Andrew81 could you please share a little more about how you achieved this?

I’m looking at doing a project where I will need to address 30 mosfets - my wife saw that video on reddit where the stairs light up in sequence. My brain says this needs a bunch of shift registers, but, although I sort of understand in principle how that’s done, I’m a little wobbly on the actual implementation.

I looked at @glmnet’s code, but, I feel like if I could see how someone else actually implemented shift registers in ESPHome, it’d be a huge help.

Honestly I’m just trying to get to the point where each light strip is exposed as a switch, and I’ll do the rest of the jiggery pokery in node-RED.

If you have a moment, please share your yaml and .h file. Help an idiot out.

Addressables are not an option?

Hi @glmnet, in an ideal world, yes, addressable would be wonderful. No mosfets, and I would only have to work out how to keep 5V power stable to 15 strings.

But, I don’t have any addressable LEDs, and they are terrifyingly expensive in my country vs single colour 5050 LEDs (about 4 times more per m). Also, I already have plenty of single colour LEDs.

My approach to this project, therefore, was to just have 2 colours: warm white for when people are awake, and red for night time. That way I don’t need to work out how to send colour data to 15 individual stairs, I just have to switch on and off 2 strings per stair (white or red). Easier than RGB data, which would have required 3 mosfets per stair, and 45 actual GPIOs, since I can’t think of a way to send more complex data than ON/OFF via shift register. It’s of course very likely that I just don’t understand shift registers very well.

So my approach will need “only” 2 mosfets per stair, but a lot of shift registers to address all 30 mosfets.

1 Like

Hi. Sorry for delay. I will send the my solution today evening.

You can’t do PWM on the 74HC595 (sorry I assume this is an output shift register)
In any case you can go with the https://esphome.io/components/output/pca9685.html
We should add support for the output shift register anyway but I believe PWM will make it WOW better and those are cheap and already implemented.

You can submit a PR to ESPHome and we can add this component in the next release.

@DeeBeeKay Look at this:
binSwitch.h

#include "esphome.h"

// global variable to store state of bits
byte rele_state = 0;
// pins of the shift register (74HC595)
const byte outputLatch_pin = D1;
const byte clock_pin = D5;
const byte mosi_pin = D7;

class binSwitch : public Component, public Switch
{
  byte pinNum;
  bool SetBit(bool pinValue, byte 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);
    digitalWrite(outputLatch_pin, HIGH);
  }

public:
  // pin - output pin of the shift register (0..7)
  binSwitch(byte 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));
  }
};

yml file

esphome:
  name: switchrefrigerator
  platform: ESP8266
  board: nodemcuv2
  includes:
    - binSwitch.h
...
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);
    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);
    return {switch1,switch2,switch3,switch4,switch5,switch6,switch7,switch8};

  switches:
    - name: "Refrigerator Switch 1"
      id: switch_1
    - name: "Refrigerator Switch 2"
      id: switch_2
    - name: "Refrigerator Switch 3"
      id: switch_3
    - name: "Refrigerator Switch 4"
      id: switch_4
    - name: "Refrigerator Switch 5"
      id: switch_5
    - name: "Refrigerator Switch 6"
      id: switch_6
    - name: "Refrigerator Switch 7"
      id: switch_7
    - name: "Refrigerator Switch 8"
      id: switch_8

I hope this will be helpful for you. Feel free to contact me for any future questions.

Note: shift registers can be merged to a group and in this case you should use an array instead of byte global variable and change logic to push states to the register.

1 Like

@glmnet, I think that currently my code is unusable for a public component. Idealy need to support group of registers. I will learn how been realized current components and will prepare the ready component, but neeed more tme for this :slight_smile:

Great, I’ve seen other people requesting support for this before

Hi @Andrew81 - thank you so much for posting this. Right now I’m reading it and going, “uhhhhhh …”, but I can sort of see what’s up. This is a backburner project for me; my main focus is preventing our farm from dying of drought (ESPHome + flowmeters is rocking for this), but, glowing stairs are important, too.

You’ve given me plenty of food for thought.

Hi @glmnet, you’re correct, I’m thinking of an output shift register.

However, I’m not thinking of sending any sort of brightness data, so I didn’t think PWM was necessary. Surely if I’m just trying to turn on a string of LEDs, I don’t need PWM?

Please correct me if I’m wrong. I’m used to being wrong. It’s how I learn.

Ahh yes, of course you don’t need PWM to turn on LEDs 100% on, 100% off, but hey!, if you have a IC controlling the output and driving the LEDs with a mosfet the only reason you’ll not be able to do PWM will be the shift register and there are other not so expensive options so this was just a question/recommendation. With two PCA9685 you can drive 32 mosfets on a single i2c bus.

It’ll be nice to have the 74HC595 supported in the core.

Good luck with the project!

1 Like

Ooh. Something to research! Thank you for this!