Shift Registers - WTF

Okay,

Obviously tons of threads about shift registers on this forum. I've read more than a dozen to include how to articles, youtube videos etc.... none of them have helped. I'm about ready to smash the HC595s I have with a hammer to be honest. I'm new to programming in general and I need help with shift registers. I'm only asking for help because I've been stuck on the shift registers for days now. I can't take it any longer. I can do digitalWrites all day.

Devices:

Heltec Automation LoRa WiFi ESP32 v2
Breadboard
12 x LEDs (3 x single colors LEDs and 3 by RGB)
2 x 74HC595N shift registers
12 220ohm resisters

End result is the be able to receive a String (FR for example) over the air and if that String matches a case or if statement or whatever, run the associated command. In the case of the example, FR would tell the system to turn on the Front Red LED (RGB) which is currently on register 1 pin 3 (output 4).

I can get the 8-bit LED examples to run all day long and I can get the 16-bit examples with 16 LEDs and 2 registers to work as well. So everything is connected correctly but I cannot grasp the concept of what needs to happen to turn on a specific LED or multiple LEDs in the case of an RGB.

I don't really have anything in the Loop section of my code yet because I haven't figured out what to put there. I just put a bunch of comments in the code to kind of detail what I'm doing.

I plan on doing a lot more with this code but I have to get the lights functioning before I add other functionality like deep sleep for the radio, or whatever.

Can someone please please help me figure this out.

LED_Receiver_Billy_V1.1_test.ino (5.04 KB)

I use my Arduino Helpers library for these kinds of things. It allows you to simply call digitalWrite to turn on/off the shift register outputs.
Here's an example that shows how to drive RGB LEDs with it: RGB-LED-Chaser.ino

Pieter

Thanks Pieter! I'll check out the library that you mentioned. Any idea why every example of how to use a shift register ONLY shows how you do what the example you gave me shows? lol I can loop all day long through the 8 pins or 16 pins (2 x registers) but no example I've found yet really defines how to turn on individual outputs of a shift register. lol

thenewnewguy44:
Any idea why every example of how to use a shift register ONLY shows how you do what the example you gave me shows? lol I can loop all day long through the 8 pins or 16 pins (2 x registers) but no example I've found yet really defines how to turn on individual outputs of a shift register. lol

I'm not sure what you mean, the example I linked to does enable and disable individual outputs, it just does it in a for loop.
If you want an example that just uses a single pin: SPI-Blink.ino

I just keep a byte variable for each shift register, and use AND (&) and OR (|) to clear bits or to make them high.

dataByte = 0b00001111;
dataByte = dataByte | 0b01000000; result is 0b01001111
dataByte = datbyte & 0b11111101; result is 0b01001101

AND in 0 clears a bit, OR in 1 sets a bit. AND in 1 keeps bits whatever they were. OR in 0 keeps bits whatever they were.
See the BitWise Operators here Arduino Reference - Arduino Reference
Then SPI.transfer() to send it out quick.

PieterP:
I'm not sure what you mean, the example I linked to does enable and disable individual outputs, it just does it in a for loop.
If you want an example that just uses a single pin: SPI-Blink.ino

You're right Pieter. The example you showed does activate a single LED at a time inside the for loop. It doesn't explain, or show, how to activate single pins outside of the for loop. That's what I meant.

The SPI-Blink.ino sketch you showed me looks really easy and I'd like to see if I can get it working. I have 2 questions though:

  1. With the Library you mentioned, how to do you set the Latch, Clock, and Data pins for the Register? Is it the same way as normal or a different way? (int latchPin = 12; for example)
  2. if I have 2 registers daisy chained, how do I address the second register and it's pins? I tried looking at the Arduino Helpers documentation but it doesn't really say. At least what I read didn't.

The latch pin is the first argument to the SPIShiftRegister constructor. By default it uses the Slave Select pin of the Arduino.

If you use SPI, the clock and data pins are fixed in hardware. The wiring diagram is shown in the example.

If you really want to, you could bit-bang it in software instead of using hardware SPI, then you can specify all pins in your code, but it's significantly slower. (BitBang-Blink.ino).

To address the second register, you use pin numbers 8-15. There's nothing special about multiples of eight when it comes to shift registers, you can have any number of bits, the 74HC595 happens to have 8 bits, but if you chain two together, you effectively have a single 16-bit shift register.

PieterP:
The latch pin is the first argument to the SPIShiftRegister constructor. By default it uses the Slave Select pin of the Arduino.

If you use SPI, the clock and data pins are fixed in hardware. The wiring diagram is shown in the example.

EDIT: I got the bit bang version of your code working and it works great Pieter. One issue that I'm not sure how to fix. You mentioned that using the second register should just be setting the ledPin to any number between 8 and 15. That does work. Setting ledPin to 0, 1, 2, or 3 blinks the same LED on both registers (Setting to ledPin 0 blinks the first LED on Register 1 and also blinks the first LED on register 2).

EDIT 2: GOT IT! I had to change ShiftRegisterOut<8> to ShiftRegisterOut<16>. You're the man Pieter! Have a great weekend!

Awesome. I can bitbang the pins without issue. Not too worried about speed for that since the lights aren't going to be updated often enough to really matter.

I am still confused on Slave Select Pin and if I can use the hardware clock pin. The pin out for my board was attached to my first post. The light blue pins are SPI but some of them are also used by the LoRa radio. It's an Arduino compatible board but I am unsure how to ID the Slave Select pin. I can tell that pins 18 and 23 are the clock and data respectively.

If I use the hardware SPI pins, can I also use the other functions assigned to those pins in the pin out? Example, Pin 18 is the SPI Clock AND used for the LoRa radio transceiver which I also need to use. Also, this is my first foray into SPI.

I really, really appreciate the help. I'm going to see if I can get things working with bit banging.

thenewnewguy44:
I am still confused on Slave Select Pin and if I can use the hardware clock pin. The pin out for my board was attached to my first post. The light blue pins are SPI but some of them are also used by the LoRa radio. It's an Arduino compatible board but I am unsure how to ID the Slave Select pin. I can tell that pins 18 and 23 are the clock and data respectively.

The Slave Select is really only useful when either using the Arduino as an SPI slave (or when using a hardware DMA controller to handle the SPI transfer).
When you're simply using the SPI peripheral in master mode (that's what you're doing here when using the SPIShiftRegister class), you could use any pin as the latch pin. Often the hardware Slave Select pin is used, because this pin cannot be used as an input when the SPI peripheral is in master mode. When changing it to input, the SPI would switch to slave mode (on some AVR boards at least), which is not what you want.

In your case, the LoRa is probably already using the hardware Slave Select pin, so just use any available pin. In the code, you can replace SS by your pin number of choice.

When bit-banging using the ShiftRegister class, there are no restrictions on the pins at all, just use any available pin.

thenewnewguy44:
If I use the hardware SPI pins, can I also use the other functions assigned to those pins in the pin out? Example, Pin 18 is the SPI Clock AND used for the LoRa radio transceiver which I also need to use. Also, this is my first foray into SPI.

The SPI can share the data (MISO, MOSI) and clock lines with many different devices, as long as each device has its own Slave Select pin. (Note: Chip Select (CS) and Slave Select (SS) are often used as synonyms.)

That being said, the pinout you posted shows that the LoRa module doesn't use the standard SPI pins. It might be bit-banging in software as well, or it might have re-wired the hardware SPI pins in the IO mux.

You could investigate further how the LoRa module uses SPI, but if bit-banging the shift registers works, it's probably easiest to go with that option.

Awesome! Thank you Pieter! Once I get the receive end set up I'll test out the LoRa transceiver and change the SS pin if needed. So far so good though.