Showing posts with label led. Show all posts
Showing posts with label led. Show all posts

Friday, May 6, 2016

So last week, I got the easy part out of the way: the serial-to-parallel shift out to an array of LEDs. This week, I'm going to be going through how I set-up a 16 bit parallel-to-serial shift in from an array of "buttons" to the Arduino in order to turn those LEDs on at will.

That Shift Register is Talking Some Mad Binary

This is a little less straight-forward than last week's endeavor. I had to take everything into account that was done then and add some practical way to control it.

What helped this time around was looking at the old code I wrote to do this back in 2011. The original code didn't work thanks to Arduino changing things in the compiler and the IDE, but a few hours of beating on it (and my desk) got it to work.

Materials Used:
  • Everything from last week's post
  • More hook-up wire
  • 2 - HCF4021B Shift Registers (Have a datasheet!)
  • 16 - 10kΩ resistors
Why 16 resistors when there will only be 10 buttons in the final product? The 4021 chip I chose freaks out whenever one of the data in pins doesn't have a path to ground. I played around with this in it's 8 bit form and without a single path to ground, it was sending me 11111111 or 255 and nothing else. 

If you're doing this and are getting weird results like the circuit is sending 127 or 255 constantly or whenever a button is pressed, check to see if your resistors are seated securely in the breadboard. The 4021 is a tricky, fickle demon.

Step 1: Put Some Wire on Board

This will at least power the chips

Step 2: The Control Wires


The Clock (yellow) is shared with the 595 circuit. Tie the Clock pins together.  There is no point in having a second clock.
Data (blue) goes to D5. Additionally, a wire needs to go from DS on the top IC to Q7 on the bottom.
The Latch (orange) goes to D4. Tie the Latch pins together. Why the separate Latch? I don't know.

Step 3: The "Button" Debounce Circus

If you have access to 10kΩ DIP resistors, not only will you be better off, but I hate you out of jealousy.

My end-result ended-up being 16 10kΩ resistors straight from the pin line on the breadboard from the chip directly to ground. Since I don't have this many buttons to play with, I just probed the board at certain points with a wire hooked directly to the 5v rail. It does the same thing as a button and is as expensive as a foot of hookup wire.
I used purple in the sketch for lines from pins. RIP Prince

Step 4: The Code

Here's what works:


int latchPin = 4;
int dataPin = 5;
int clockPin = 7;
int led_latchPin = 11;
int led_dataPin = 10;
byte switchVar1 = 72;
byte switchVar2 = 159;

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

  //define pin modes
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, INPUT);
  pinMode(led_latchPin, OUTPUT);
  pinMode(led_dataPin, OUTPUT);
  unsigned int bitsToSend = 0;
  digitalWrite(led_latchPin, 0);
  bitWrite(bitsToSend, 8, HIGH);
  byte registerOne = highByte(bitsToSend);
  byte registerTwo = lowByte(bitsToSend);
  shiftOut(led_dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(led_dataPin, clockPin, MSBFIRST, registerOne);
  digitalWrite(led_latchPin, 1);
}
void loop() {
  int LED;
  digitalWrite(latchPin, 1);
  delayMicroseconds(40);
  digitalWrite(latchPin, 0);
  switchVar1 = shiftIn(dataPin, clockPin);
  switchVar2 = shiftIn(dataPin, clockPin);
  unsigned int allIn = switchVar1 * 256 + switchVar2; //The total value of what is being sent to the Arduino
  if (allIn != 0) {
    switch (allIn) {
      case 1:
        LED = 1;
        break;
      case 2:
        LED = 0;
        break;
      case 4:
        LED = 15;
        break;
      case 8:
        LED = 14;
        break;
      case 16:
        LED = 13;
        break;
      case 32:
        LED = 12;
        break;
      case 64:
        LED = 11;
        break;
      case 128:
        LED = 10;
        break;
      case 256:
        LED = 9;
        break;
      case 512:
        LED = 8;
        break;
      default:
        LED = 8; //Don't know what to do? Go home.
        break;
    }
    Serial.println(switchVar1);
    Serial.println(switchVar2);
    Serial.println(allIn);
    Serial.println("--------------");
    unsigned int bitsToSend = 0;
    digitalWrite(led_latchPin, 0);
    bitWrite(bitsToSend, LED, HIGH);
    byte registerOne = highByte(bitsToSend);
    byte registerTwo = lowByte(bitsToSend);
    shiftOut(led_dataPin, clockPin, MSBFIRST, registerTwo);
    shiftOut(led_dataPin, clockPin, MSBFIRST, registerOne);
    digitalWrite(led_latchPin, 1);
    //changeProgram(LED);
    delay(200);
  }

}


byte shiftIn(int myDataPin, int myClockPin) {
  int i;
  unsigned temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
  for (i = 7; i >= 0; i--)
  {
    digitalWrite(myClockPin, 0);
    delayMicroseconds(2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      myDataIn = myDataIn | (1 << i);
    }
    else {
      pinState = 0;
    }
    digitalWrite(myClockPin, 1);
  }
  return myDataIn;
}

 There are very few things in common with last week's code. For those following along at home: my apologies.

Step 5: The Madness Sets In

From there, I probed around - putting the hot wire between the resistors and the 4021 chips. The lights turned on and off. It was a success.

For further troubleshooting, the Arduino will print out the high bit, the low bit and the combined 16 bit value of what is sent back to the console. Additionally, here's the Fritzing sketch I put together for this post.

If you're seeing a behavior like the following, you too have success. If not, troubleshooting will lead to eventual insanity.



Sunday, May 1, 2016

It's been a long time (5-6 years) since I started this project. Things change. With the struggle of work, life, and family, hobbies and interests sometimes have to take a back seat to things with higher priority.
Pretty much unchanged in 5-6 years

Not too long ago, I looked up on my shelf of stuff (you know you have one) and saw a breadboard with some ICs and an Arduino Uno on it. I don't know if it was a sudden outbreak of nostalgia, or if it was the self-loathing of realizing that I never finished such an ambitious project; but I felt a sudden need to complete what I started.

Over the next few weeks, I will be breaking-down the hardware and code of the individual parts of this build. Going from a Mega 2560 board with about a million I/O pins and handing everything in code to as few I/O pins as possible and handling things in hardware is no small task.

Getting Some LEDs to Turn On

Part of the FCB1010 is the LEDs on the board that indicate what pedal was pressed. I previously handled this in code.

I couldn't find any useful or practical tutorials on how to get a 16 bit shift register setup working. That being said, this is not going to even touch on running a basic 8 bit shift register. The following is cobbled together from various sources around the internets and hours of troubleshooting. I apologize ahead of time as my Fritzing skills have much to be desired.

Materials Used:

Step 1: Wire the Power

I hear electronics like electrons.

I used D2 for the constant 5v

Step 2: Wire the Control Lines

I used blue for Data (D10), Yellow for Clock (D7), and Green for Latch (D11).

The two 74HC595 chips share the same latch and clock lines. The data out from the top chip goes to the data in on the bottom. An extra 5v needs to be supplied to the MR pin of the top chip to enable cascading to the bottom chip.

Step 3: Wire the Data Out Circuits

Purple is a nice color. RIP Prince.

Step 4: Add Some LEDs

Since only one will be on at any one time, I figured one resistor would do.

Step 5: There Is No Step 5

Sit back and admire your work. Here's the Fritzing sketch I used if you need any help. 

Step 6: Test Code

Since there won't really be any practical use of hardware to control which light is on or off, the code doesn't really have to be practical either.

All this code does is throw a rotating sequence of high and low bytes of a 16 bit unsigned integer at the shift registers.

#include <stdio.h>
//Pin connected to ST_CP of 74HC595
int latchPin = 11;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 10;

unsigned  data[] = {
0B0000000000000001,
0B0000000000000010,
0B0000000000000100,
0B0000000000001000,
0B0000000000010000,
0B0000000000100000,
0B0000000001000000,
0B0000000010000000,
0B0000000100000000,
0B0000001000000000,
0B0000010000000000,
0B0000100000000000,
0B0001000000000000,
0B0010000000000000,
0B0100000000000000,
0B1000000000000000
};

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  for (int j = 0; j < 16; j++) {
    digitalWrite(latchPin, 0);
    int data = data[j];
    byte first = lowByte(data);
    byte second = highByte(data);
    shiftOut(dataPin, clockPin, MSBFIRST, first);
    shiftOut(dataPin, clockPin, MSBFIRST, second);
    digitalWrite(latchPin, 1);
    delay(1000);
  }
}

If you end-up with something that looks like the following, you're done! Yay!



Subscribe to RSS Feed Follow me on Twitter!