Semi-Trailer light and brake test unit - Shift register for indicator lights?

Hi,

I’ve been working on building a machine that will be used to test semi-trailer lights and air brake systems for use in the repair shop. I’ve written the code that will select and activate a bank of 8 relays to perform various functions via rotary encoder with pushbutton integrated. This allows 1 knob to perform all functions and will simplify the control panel.

My next task is to display the status of each relay on a bank of LED’s on the control panel. I want the “active” relays indicated with a solid lit LED, and the “cursor” position to be indicated by a flashing LED.

I understand that to output to all of these LED’s I’m going to need to use a shift register, which I have purchased. The trouble is, I don’t even know where to begin with coding this thing. If I used an arduino mega board, it would be easy, I would just give each lamp it’s own pin and call it a day. Anyone able to walk me through this, or offer some advice on how to set it up?

I’m also working on adding a full-function remote control, but more on that later…

I’ve attached the code for the relay switching, as it’s too long to embed on the forum.

Trailer_Tester.ino (7.96 KB)

Which shift register? For a 74HC595 you will need 3 or 4 pins. Shift clock, latch, data and optionally chip enable. You can use the shiftOut() function to shift the data into the register and then pulse latch high then low to transfer the data in the shift register to the output latches. 595 tutorial

74HC164 tutorial

And a tutorial for the 164 non latching shift register.

I read through the shift out tutorial, and I'll likely use the array example, as I have 8 outputs that can occur either on or off in any combination. 7CH595 register. What I'm trying to wrap my head around now is how to set up the array without having 8*2 if statements. I'm already holding the "output state" and "previous output state" in booleans for each output. How to use an array with variable values?

Ok. I’ve got the array up and running for my indicator lights. I can print a byte of data showing the current status of outputs in binary to the serial monitor. How does one go about sending this to the shift register?

Does it make sense to store this “code” for the shift register data in a single byte variable each time around the loop, and send it from there? Or is it possible to send it to the data pin directly from the array?

here’s the array setup:

  SRdataArray[0] = relayState0;
  SRdataArray[1] = relayState1;
  SRdataArray[2] = relayState2;
  SRdataArray[3] = relayState3;
  SRdataArray[4] = relayState4;
  SRdataArray[5] = relayState5;
  SRdataArray[6] = relayState6;
  SRdataArray[7] = relayState7;
  

  if (buttonPos == 1)
    {
       int x;
 for (x=0; x < 8; x++) 
{
  Serial.print(SRdataArray[x]);
 }
 Serial.println(" ");
    }

Anyone can help?

Ok. I’ll explain my question:

do I need to store the output from my array as a single int?

For example:

if (buttonPos == 1)
    {
       int x;
 for (x=0; x < 8; x++) 
{
  Serial.print(SRdataArray[x]);
 }
}

This gives me a byte of data printed to the serial monitor, which changes based on other variables. Let’s say the output is 10110001. I want to send that number to the shift register which will fire the LED’s to indicate what’s on, or off. I’m guessing it’s easiest to have the shift register receive a single int.

I’ve tried many ways to store the output of the array as an int, but I can’t get more than 1 digit stored. Is there a special way to do this?

You will send a byte (8 bits) to the shift register. Each bit represents the state of a light. Say 0 for off and 1 for on. Assign each light a bit position in the byte like the binary number in your last post.

byte lightStates = 0;  // all off

byte srLeft = 0;              
byte srStop = 1;
byte srRight = 2;
byte srMark = 3;
byte srClear = 4;
byte srABS = 5;
byte srEmergency = 6;
byte srService = 7;

Now you can use the bitSet and bitClear instructions to control the states of the lights. bitSet

To turn on the Mark light: bitSet(lightStates, srMark); That will set (set to 1) the the forth bit (bit 3) bit of lightStates.

Once you have the lightStates variable set as you like, use shiftOut to send the lightStates byte to the shift register. shifOut

There are other ways to do the same as well as changing several bits at once using and (&) and or (|) with masks and/or using bit shifting , but this is simpler, I think, for someone new.

Is this an array? How do the bytes following byte lightStates get addressed back to lightStates? To me this code just looks like 9 byte setups? How do I get the shift register to call all of those bytes in the correct order to fire the appropriate LEDs?

There is no array involved here. The srxxxxx bytes are bit positions in lightState (0-7) given names. You set or clear bits in lightState using the names to point to the position that you want to change (set or clear). The shift register only gets one byte, the lightStates byte. The lightStates byte is sent to the shift registers. How do you have the LEDs wired to the shift registers? Through a resistor to ground or to Vcc? If they go to ground a high will turn the LED on. So, if lightState starts as 0b00000000 (0x00 hex) and you want the left (bit 0) and ABS (bit 5) LEDs lit:

lightStates = 0;

bitSet(lightStates, srLeft); //   lightStates = 0b00000001 (0x01)
bitSet(lightStates, srABS); //   lightStates = 0b00100001 (0x21)

shiftOut(dataPin, clockPin, MSBFIRST, lightStates);  // send lightStates byte to shift register
digitalWrite(latch, HIGH);
digitalWrite(latch, LOW);  // pulse latch pin to transfer shift register to output register

// turn off ABS light
bitClear(lightStates, srABS);  // turn off ABS bit lightStates = 0b00000001

shiftOut(dataPin, clockPin, MSBFIRST, lightStates);  // send lightStates byte to shift register
digitalWrite(latch, HIGH);
digitalWrite(latch, LOW);  // pulse latch pin to transfer shift register to output register