3

I have a project which requires me to read if the input is "HIGH". I have 15 inputs (switches), and each input has its own output (LED). I am using a Shift Register to control its inputs and outputs.

My current code looks like this (4 inputs and 4 outputs, it works though...):

#include "SPI.h"
#include "MFRC522.h"
#include "rgb_lcd.h"
#include <Wire.h>

#define SS_PIN 17
#define RST_PIN 7

int counter = 0;
int lock = 100;

MFRC522 rfid(SS_PIN, RST_PIN);
rgb_lcd lcd;
MFRC522::MIFARE_Key key;

// Define Pins
int SHIFTIN_LATCH = 22;
int SHIFTIN_DATA = 23;
int SHIFTIN_CLOCK = 21;
int numberToDisplay = 0;

#define SHIFTOUT_DATA  18
#define SHIFTOUT_LATCH  19
#define SHIFTOUT_CLOCK  20

//Define variables to hold the data
//for each shift register.
//starting with non-zero numbers can help
//troubleshoot
byte keySlotID[15] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte keyInsert[15] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte keyReg[10] = {
  0,0,0,0,0,0,0,0,0,0}; // amt of reg.

void setup() {
  //start serial
  Serial.begin(9600);

  //define pin modes
  pinMode(SHIFTIN_LATCH, OUTPUT);
  pinMode(SHIFTIN_CLOCK, OUTPUT);
  pinMode(SHIFTIN_DATA, INPUT);

  pinMode(SHIFTOUT_DATA, OUTPUT);
  pinMode(SHIFTOUT_LATCH, OUTPUT);
  pinMode(SHIFTOUT_CLOCK, OUTPUT);
  Serial.begin(9600);
  SPI.begin();
  rfid.PCD_Init();
  lcd.begin(16, 2);
}

void KeyID(){
  // Key slot indicator.
  keySlotID[0] = (keyReg[0] & 0x1E) >> 1;
  keySlotID[1] = (((keyReg[1] & 0x03) << 3) | ((keyReg[0] & 0xE0) >> 5)) >> 1;
  keySlotID[2] = (keyReg[1] & 0x78) >> 3;
  keySlotID[3] = (keyReg[2] & 0x0F);
  // Key inserted indicator.
  keyInsert[0] = (keyReg[0] & 0x01);
  keyInsert[1] = (keyReg[0] & 0x20) >> 5;
  keyInsert[2] = (keyReg[1] & 0x04) >> 2; // X
  keyInsert[3] = (keyReg[1] & 0x80) >> 7; // X
}

void registerWrite(byte data1, byte data2) {
  digitalWrite(SHIFTOUT_LATCH, LOW);
  delay(10);
  shiftOut(SHIFTOUT_DATA, SHIFTOUT_CLOCK, MSBFIRST, data2);  
  shiftOut(SHIFTOUT_DATA, SHIFTOUT_CLOCK, MSBFIRST, data1);
  digitalWrite(SHIFTOUT_LATCH, HIGH);
  delay(10);
}



void LedIFs() {

  if (keyInsert[0] == 0 && keyInsert[1] == 0 && keyInsert[2] == 0 && keyInsert[3] == 0) {
    registerWrite(0xFF,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 0 && keyInsert[2] == 0 && keyInsert[3] == 1) {
    registerWrite(0x40,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 0 && keyInsert[2] == 1 && keyInsert[3] == 0) {
    registerWrite(0x10,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 0 && keyInsert[2] == 1 && keyInsert[3] == 1) {
    registerWrite(0x50,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 1 && keyInsert[2] == 0 && keyInsert[3] == 0) {
    registerWrite(0x04,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 1 && keyInsert[2] == 0 && keyInsert[3] == 1) {
    registerWrite(0x44,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 1 && keyInsert[2] == 1 && keyInsert[3] == 0) {
    registerWrite(0x14,0);
  }
  else if (keyInsert[0] == 0 && keyInsert[1] == 1 && keyInsert[2] == 1 && keyInsert[3] == 1) {
    registerWrite(0x54,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 0 && keyInsert[2] == 0 && keyInsert[3] == 0) {
    registerWrite(0x01,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 0 && keyInsert[2] == 0 && keyInsert[3] == 1) {
    registerWrite(0x41,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 0 && keyInsert[2] == 1 && keyInsert[3] == 0) {
    registerWrite(0x11,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 0 && keyInsert[2] == 1 && keyInsert[3] == 1) {
    registerWrite(0x51,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 1 && keyInsert[2] == 0 && keyInsert[3] == 0) {
    registerWrite(0x05,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 1 && keyInsert[2] == 0 && keyInsert[3] == 1) {
    registerWrite(0x45,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 1 && keyInsert[2] == 1 && keyInsert[3] == 0) {
    registerWrite(0x15,0);
  }
  else if (keyInsert[0] == 1 && keyInsert[1] == 1 && keyInsert[2] == 1 && keyInsert[3] == 1) {
    registerWrite(0x55,0);
  }
}

void loop() {

  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(SHIFTIN_LATCH,1);
  //set it to 1 to collect parallel data, wait
  delay(1);
  //set it to 0 to transmit data serially  
  digitalWrite(SHIFTIN_LATCH,0);

  //while the shift register is in serial mode
  //collect each shift register into a byte
  //the register attached to the chip comes in first
  keyReg[0] = ~shiftIn(SHIFTIN_DATA, SHIFTIN_CLOCK);
  keyReg[1] = ~shiftIn(SHIFTIN_DATA, SHIFTIN_CLOCK);
  keyReg[2] = ~shiftIn(SHIFTIN_DATA, SHIFTIN_CLOCK);

  LedIFs();
  KeyID();
}

The problem I'm facing is that it would be too long for me to write down 15 KeyInserts. That would mean I have to write about or close to 200,000 lines of code...

  • some code wasn't added as it is of no relations to this part of the code. – Dante Takeshii Nov 9 '16 at 2:18
  • What are you trying to do EXACTLY? – Dat Ha Nov 9 '16 at 2:18
  • Just Read the Inputs and if the input is high, output is high. It would've been easier if i don't need to use a shift register but i have to , to save pins. Im currently doing a project, a 15 lock project. – Dante Takeshii Nov 9 '16 at 2:19
  • Can you please add your circuit diagram. – sa_leinad Nov 9 '16 at 2:45
  • 2
    May I respectfully suggest you read up on how to write loops? This should be achievable in a dozen lines of code. – Nick Gammon Nov 9 '16 at 8:52
1

Let's assume value that will be stored into "keyInsert" are either "1" or "0". Therefore, its a waste to declare them as an array byte

byte keyInsert[15] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};    

It means that you will have 15 * 8 bytes variable, and its overkill. it will be much simpler if you declare it as

uint16_t keyInsert;    

Which have 16 bits data (2 bytes).
in your code, you can implement it by doing

void LedIFs() {
if (keyInsert == 0x0001) registerWrite(0xFF,0); else 
if (keyInsert == 0x0002) registerWrite(......)......
......
}
1

I can't quite get the logic of your keyInsert[] array. Why don't you use a binary number (e.g. uint16_t, which is 16 bits) instead of an array of zeros and ones? Also, half of the lines of the output shift register seem essentially unused.

If I understand correctly, you want to simplify LedIFs() in order to handle many bits with few lines of code. Examining your current implementation, it appears that you are writing to the output register the very same bits you have in keyInsert[], only in different positions. Instead of testing every possible combination, it would be much simpler to just move the bits into their appropriate positions:

  • keyInsert[0] becomes bit 0 (i.e. least significant) of the first argument of registerWrite()
  • keyInsert[1] becomes bit 2 (it's weight is 22 = 0x04)
  • keyInsert[2] is bit 4 (weight: 24 = 0x10)
  • keyInsert[3] is bit 6 (weight: 26 = 0x40)

This is done using bit shifts, and joining the bits with the | bitwise-or operator:

void LedIFs() {
    byte val = keyInsert[0] << 0
             | keyInsert[1] << 2
             | keyInsert[2] << 4
             | keyInsert[3] << 6;
    if (val == 0) val = 0xff;
    registerWrite(val, 0);
}

Notice that << 0 has no effect: it is here only because it looks nicer (more symmetric, easier to read) this way. The compiler will optimize out this operation anyway. Also, the case when all the bits are zero is special, since you are writing 0xff instead of zero.

If I were you, what I would do is store the information in keyInsert[] as a single number with the bits already at their correct position. Then I would write

uint16_t keyInsert;

//...

static inline void LedIFs() {
    registerWrite(keyInsert ? keyInsert : 0xff, 0);
}
0

I will be using digitalReads and digitalWrites but just follow this logic:

int state[num_of_switch_that_you_have];

for(int i=0; i<num_of_switch_that_you_have; i++)
{
  //buttonPins is the pin to which all your buttons are connected to in an array
  state[i] = digitalRead(buttonPins[i]);

  //leds is the pin to which all your leds are connected to in an array
  digitalWrite(leds[i], state[i]);
}

Try to follow this logic while using your shift registers. Sorry if I don't have a full code with shift registers for you, I'm not really good with them!

If you need any more details, please comment, I'll be happy to help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.