Rich Noordam
Published © LGPL

Using the ESP32S with 74595 Shift Registers

Example of using the ESP32S with 74595 shift registers to run a relay board. Easily extended to as many relays as you may need.

BeginnerProtip1 hour7,292
Using the ESP32S with 74595 Shift Registers

Things used in this project

Hardware components

ESP32S
×1
Shift Register- Serial to Parallel
Texas Instruments Shift Register- Serial to Parallel
×2
Solderless Breadboard Full Size
Solderless Breadboard Full Size
×2
Jumper wires (generic)
Jumper wires (generic)
×1
16 channel 5v Relay board
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Fritz for example

ESP32 30 pin fritz part

Code

74595 Relay Driver

Arduino
The code uses pins:
25- Serial Pin
26- RCLK
27- SRCLK

(same code but different pins than the NodeMCU example I have)
#include <Wire.h>

class RelayDriver
{
  public: int zone;      // zoneID to turn on.
  public: bool isActive;
  private: long onTime;     // milliseconds of on-time
  // base byte array to send bytes from 
  private: byte dataArray[9]; // array  to handle the 74595 chip states
  // set pins for relay control
  private: int SER_Pin = 25;   //pin 14 on the 75HC595 data, pin 25 on the esp32
  private: int RCLK_Pin = 26;  //pin 12 on the 75HC595 latch, pin 26 on esp32
  private: int SRCLK_Pin = 27; //pin 11 on the 75HC595 clk, pin 27 on esp32
  // Timing variable
  unsigned long previousMillis;   // will store the last time the relays were updated.

  // Constructor - creates a RelayDriver and initializes the member variables and state
  public: RelayDriver(){
    dataArray[0] = 0x00; //0b00000000 # All Off (sent twice shuts all off
    dataArray[1] = 0x01; //0b00000001 # Position 1 of chip on 
    dataArray[2] = 0x02; //0b00000010 # Position 2 of chip on 
    dataArray[3] = 0x04; //0b00000100 # Position 3 of chip on 
    dataArray[4] = 0x08; //0b00001000 # Position 4 of chip on 
    dataArray[5] = 0x10; //0b00010000 # Position 5 of chip on 
    dataArray[6] = 0x20; //0b00100000 # Position 6 of chip on 
    dataArray[7] = 0x40; //0b01000000 # Position 7 of chip on 
    dataArray[8] = 0x80; //0b10000000 # Position 8 of chip on 
    previousMillis = 0;
    isActive = false;
    onTime = 0;
    // set pins.    
    pinMode(RCLK_Pin, OUTPUT);
    pinMode(SRCLK_Pin, OUTPUT);
    pinMode(SER_Pin, OUTPUT);
    // write initial state (All Off)
    digitalWrite(RCLK_Pin, 0);
    shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);
    shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);
    digitalWrite(RCLK_Pin, 1);
  }
  public: void Update()  // base update to turn everything OFF if running.
  {
    unsigned long currentMillis = millis();
    if (isActive){
      if(currentMillis - previousMillis >= onTime)
      {
        // write initial state (All Off)
        digitalWrite(RCLK_Pin, 0);
        shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);
        shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);
        digitalWrite(RCLK_Pin, 1);
        isActive=false;
      }
    } else {
      // shut all off always to be safe. (should be off)
      // keeps the 'static' at bay in circuit too, as it resets it often.
      digitalWrite(RCLK_Pin, 0);
      shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);
      shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);
      digitalWrite(RCLK_Pin, 1);
      isActive=false;
    }
  }
  public: void Update(int InZone, int InrunTimeSec) // this update changes the state, and sets timers
  {
    // zone is 2 parts, chip 2 gets sent first.
    // example: all off send 0,0 twice
    // example: position 1, send 0, 1 
    // example: position 9, send 1, 0
    unsigned long currentMillis = millis();
    if (isActive){ 
      // do nothing, as it's already running.
    } else {
      // is off, turn on and set vals.
      onTime = InrunTimeSec * 1000; 
      previousMillis = currentMillis;
      zone = InZone;
      digitalWrite(RCLK_Pin, 0);
      if (zone <= 8){ // lower set
        shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);         // shift second bit out as zeros/OFF
        shiftOut(SER_Pin, SRCLK_Pin, dataArray[zone]);      // shift out zone we want on
      } else { // upper set
        int relayPos = zone - 8;
        shiftOut(SER_Pin, SRCLK_Pin, dataArray[relayPos]);  // shift out zone we want on
        shiftOut(SER_Pin, SRCLK_Pin, dataArray[0]);         // shift second bit out as zeros/OFF
      }
      digitalWrite(RCLK_Pin, 1);
      isActive=true;
    }
}
  // this does the changing of the 74595 chips.
  void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
      //internal function setup
    int i=0;
    int pinState;

    //clear everything out just in case to
    //prepare shift register for bit shifting
    digitalWrite(myDataPin, 0);
    digitalWrite(myClockPin, 0);

    //cycle down through byte
    for (i=7; i>=0; i--)  {
      digitalWrite(myClockPin, 0);
      //if the value passed to myDataOut and a bitmask result 
      // true then set pinState to 1.
      if ( myDataOut & (1<<i) ) {
        pinState= 1;
      }
      else {  
        pinState= 0;
      }
      //Sets the pin to HIGH or LOW depending on pinState
      digitalWrite(myDataPin, pinState);
      //register shifts bits on upstroke of clock pin  
      digitalWrite(myClockPin, 1);
      //zero the data pin after shift to prevent bleed through
      digitalWrite(myDataPin, 0);
    }
    //stop shifting
    digitalWrite(myClockPin, 0);
}
};
 
RelayDriver relayDriver;

void setup() 
{ 
  Serial.begin(115200);
} 
 
void loop() 
{
  String incomingString;
  if (Serial.available()){
    incomingString = Serial.readString(); // read the incoming data as string:
    int tildeIndex = incomingString.indexOf('~');
    int strLen = incomingString.length();
    String zoneStr = incomingString.substring(0,tildeIndex);
    String secToRunStr = incomingString.substring(tildeIndex+1, strLen);
    int zone = zoneStr.toInt();
    int secToRun = secToRunStr.toInt();
    Serial.print(" zone:");
    Serial.print(zoneStr);
    Serial.print(" secToRun:");
    Serial.println(secToRunStr);
    relayDriver.Update(zone, secToRun);
  } else {
    relayDriver.Update();
  }
}

Credits

Rich Noordam
10 projects • 33 followers
Many interests, computing obviously being one of them. MS SQL Server Database Administration, Reporting, Data Science, and more.
Contact

Comments

Please log in or sign up to comment.