Sunday, December 8, 2013

Under Pressure

Wow.  A follower.  Now I know exactly how Jesus feels, soooo much pressure.

I did a little more soldering in the past 3 months, but not much.  I am a little down on my soldering skills and intimidated by the reality of soldering it all together.

Hopefully The Follower will encourage me to overcome my fears and inhibitions and soldier/solder on.

My solution to the lack of headroom for the duino in the dartboard case was to order a brand spankin' new boarduino and assemble it without the socket, so the chip sits lower and it all fits in the case.  Not only does  this solve this stupid problem, it also means I have another arduino to play with while this one is busy playing darts.

I soldered the new duino to the perfboard along with all the wiring for the LEDs and the ribbon connector, and most of the grounds.

Next would be the 5v wiring from the duino.  I was thinking - soldering would be so much easier with 3 arms, so anyone who hasn't gotten me a xmas present yet... hint, hint.

I am not certain that all of the connections are wire-to-wire and might be relying on the solder too much in some cases.  Maybe I'll try to head down to the neighborhood hackerspace or makerspace or whatever we have here and get some advice and some help fixing some of the joints that might need fixing.  I have the feeling my current board would be on the cover of "How Not to Solder Your Crappy Project."

I thought about the game engine a little but haven't made much progress there.

I also picked up another cheap-ass electronic dartboard from the local sporting goods store in case I totally ruin this one, or in case I get this working and want to mass produce them (does 2 constitute a mass?).  My local Target just started stocking one for $15 in case things get nutty one way or the other.

This thing has been sitting right next to me on my desk all this time, I just need to do it.

It's been so long since my last post and I didn't go back and read any of them, so I might be repeating some things here.

Hopefully my next post will be soon and hopefully it will report some real progress.




Wednesday, September 18, 2013

Slow Going Slow

Here is a much anticipated update for my 0 followers and 0 page hits per day.

I laid out the perf board and decided to commit... so I soldered the LEDs, resistors and sockets to the board.

Here is a photo with my rough draft, rats nest wiring diagram. The LEDs are on the other side so they poke out through the 6 holes in the front of the dartboard where the buttons used to be.



 I need to go back to my nice Fritzing diagram to make sure I have everything going to the right place.  I kinda reversed the sides of the duino, so I'll have to update the sketch code to use some different pins, but shouldn't be a big deal... as long as I get the dartboard ribbon connectors in the right order, everything else should be easy enough to adjust.

3 challenges:
1) wiring this up without screwing up
2) the USB mini connector was too large to fit inside the dartboard case when plugged into the duino the way i have it set up
3) since i used a socket for the microprocessor on the duino, this board is a little too tall, so the back cover of the dartboard won't go on

My plans:
1) don't screw it up
2) I bought a left-angle mini USB cable from Star Tech that fits perfectly
3) ugh. I guess I'll cut a window out of the cover and use spacers or something.  Maybe I'll think of something else.  I'll have to consider that it has to hang back up flush against a wall and get hit by darts.

Still need to work on the pygame.

Thursday, September 12, 2013

LED LED LED LED LED LED

I dug up 2 red, 2 yellow and 2 green LEDs, 6 220 Ohm resistors and added them to the dartboard interface.  They are wired to the remaining 6 output pins on the second of the daisy chained 74HC595s.

Then I updated the duino sketch to light them up as status indicators: one set to indicate that the board is connected to the game server and the other to indicate that the game is being played.

I loosely tied these to the existing gamestate and command processing functionality, so both are red by default.  The connected indicator goes to yellow for 1 second when a connection command is received from the game server, then to green when the gamestate goes to stopped.

The playing indicator goes to yellow for a second when a play command is received and then to green when the gamestate is playing.... when playing, these are set along with the matrix row being pinged in the game loop.

So I added these variables:

// status light shift register values (logical and with shiftRows1)
byte connectedRed = 1;
byte connectedYellow = 2;
byte connectedGreen = 4;


byte playingRed = 8;
byte playingYellow = 16;
byte playingGreen = 32;

which work together with these:

// data to send to shift register for each board row/pin
byte shiftRows1[10] = {64,128,0,0,0,0,0,0,0,0};
byte shiftRows2[10] = {0,0,1,2,4,8,16,32,64,128};

I added a new method to set these LEDs:

void setStatusLEDs(byte state) {
  boolean setLEDs = false;
  byte connectedStatus = 0;
  byte playingStatus = 0;
  
  switch (state) {
    case IFACE_HIT:
      connectedStatus = connectedGreen;
      playingStatus = playingYellow;
      setLEDs = true;
      break;
    case IFACE_CONNECT:
      connectedStatus = connectedYellow;
      playingStatus = playingRed;
      setLEDs = true;
      break;
    case IFACE_DISCONNECT:
      connectedStatus = connectedRed;
      playingStatus = playingRed;
      setLEDs = true;
      break;
    case IFACE_PLAY:
      setLEDs = false;
      break;
    case IFACE_STOP:
      connectedStatus = connectedGreen;
      playingStatus = playingRed;
      setLEDs = true;
      break;
    default:
      setLEDs = false;
  }
  
  if (setLEDs) {
    // take the shift out latchPin low to shift it out
    digitalWrite(LATCH_SIPO, LOW);
    
    // shift out the bits (assume we're connected and playing if we're doing this at all):
    shiftOut(DATA_SIPO, CLOCK_SIPO, MSBFIRST, connectedStatus + playingStatus);
    shiftOut(DATA_SIPO, CLOCK_SIPO, MSBFIRST, 0);
    
    //take the shift out latch pin high so the voltage is sent
    // to the next row (or none if looking at the first 2 rows):
    digitalWrite(LATCH_SIPO, HIGH);
  }
}

Which I call in the main loop if the gamestate isn't play:

// the loop routine runs over and over again forever and ever and ever:
void loop() {
  if (gameState == IFACE_PLAY) {
    // check for a hit
    for (int row=0; row < 10; row++) {
       setSipoRow(row);
       processPisoColumns(row);
    }
  }
  else {
    setStatusLEDs(gameState);
    delay(1000);
  }
}

If the gamestate is playing, I added the green lights to the shiftout that iterates over the matrix rows:

// sets the SIPO shift register to power the correct row
void setSipoRow(int rowNumber) {
  // take the shift out latchPin low to shift it out
  digitalWrite(LATCH_SIPO, LOW);
  
  // shift out the bits (assume we're connected and playing if we're doing this at all):
  shiftOut(DATA_SIPO, CLOCK_SIPO, MSBFIRST, shiftRows1[rowNumber] + connectedGreen + playingGreen);
  shiftOut(DATA_SIPO, CLOCK_SIPO, MSBFIRST, shiftRows2[rowNumber]);
  
  //take the shift out latch pin high so the voltage is sent
  // to the next row (or none if looking at the first 2 rows):
  digitalWrite(LATCH_SIPO, HIGH);
}

And when a command is processed which changes the gamestate, i set the lights to yellow for a second when transitioning between red and green:

// automatically called between loops when serial data is available
void serialEvent() {
    switch (Serial.read()) {
      case IFACE_QUERY_STATE:
        Serial.print(gameState);
        break;
      case IFACE_CONNECT:
        if (gameState == IFACE_DISCONNECT) {
          setStatusLEDs(IFACE_CONNECT);  // sets connected LED to yellow for a sec
          delay(1000);
          gameState = IFACE_STOP;
          Serial.write(IFACE_CONNECT);
        }
        break;
      case IFACE_DISCONNECT:
        if (gameState != IFACE_DISCONNECT) {
          setStatusLEDs(IFACE_CONNECT);  // sets connected LED to yellow for a sec
          delay(1000);
          gameState = IFACE_DISCONNECT;
          Serial.write(IFACE_DISCONNECT);
        }
        break;
      case IFACE_PLAY:
        if (gameState == IFACE_STOP) {
          setStatusLEDs(IFACE_HIT);  // sets play LED to yellow for a sec
          delay(1000);
          gameState = IFACE_PLAY;
          Serial.write(IFACE_PLAY);
          playCharge();
        }
        break;
      case IFACE_STOP:
        if (gameState == IFACE_PLAY) {
          setStatusLEDs(IFACE_HIT);  // sets play LED to yellow for a sec
          delay(1000);
          gameState = IFACE_STOP;
          Serial.write(IFACE_STOP);
        }
        break;
      default:
        break;  
    }
}

The updated sketch is in git.

I also downloaded Fritzing to try to make some nicer circuit diagrams and came up with this one for the dartboard interface:


They didn't have a part for the boarduino, so I used the Arduino Micro.  They didn't have a part for the 74HC589, so I created my own, based on the 74HC595 included in the core parts list.  I used Inkscape to work on the SVG files required for the Fritzing parts.  The Fritzing diagram and the custom part are both in git.  I started to work on a custom USB Boarduino part but don't know if I will have the time and patience to finish it.

I think Fritzing is beyond cool.

I also cut down my perfboard/pcb to the same size as the original in the dartboard, marked off the mounting screws and posts from the original and used an x-acto to make 4 holes for the posts and screws on either end.  It fits rather nicely, so now I just need to figure out how to fit all my components on there and wire it up.



Wednesday, September 11, 2013

Mmmmmmm, Pi - Another Milestone

Got the Raspberry Pi yesterday.  I had already downloaded an installation disk image (NOOBS) and saved it to an 8GB sans disk (following the quick start guide).  It was easy as.... well, something very easy.

When I got the Pi, I plugged in keyboard and mouse to 2 USBs, HDMI from Pi to TV, and network cable... then the mini USB power adapter.  It started right up and went through configuration screens.  I enabled SSH and changed everything from the UK to my locale and changed my password, then did the updates.  Everything worked just swell.

It already has Python installed and Pygame and git.  I opened a terminal window and installed the python package manager, pip:

sudo apt-get install python-pip

Then the python web framework, Flask, since I think I might use this to interface with smartphones/pads as controllers at some point:

sudo pip install flask

Then I added my git credentials to my .netrc file.  I used the same ones that I put in my windows _netrc file in an older post.  Something like:

cd ~
echo "machine code.google.com login me@gmail.com password [GeneratedPassword]" > .netrc
chmod 600 .netrc

Then added a folder to store my code and cloned my git repo there:

mkdir Code
cd Code
git clone https://TimKracht4@code.google.com/p/no-arms-darts/ 

So then I wanted to try to see if I could just plug in the dartboard via the arduino and run it on the PI.  I needed another USB port for that, so I got out a powerd USB hub, plugged it into the Pi and plugged the keyboard, mouse and arduino into the hub.  I loaded up the python IDE, IDLE,  and opened the serial test script and ran it.  It complained because it couldn't find the Serial module... so I opened the lightweight web browser, Midori, and tried to download the PySerial tarball, but I kept getting empty files.... so I tried pip, something like:

sudo pip install pyserial

Which did the trick.  so I went back to IDLE and tried running the code again.  This time it complained about not being able to find the "COM5" serial port.  Makes sense since COM5 is on my windows laptop.  To find out what pi port the duino was connected to, I first unplugged the duino from the USB hub, then checked out what all was in the /dev folder for tty connections:

ls -alt /dev/tty*

Then I plugged in the duino, waited a few seconds and ran the command again.  The second time around there was a new entry, /dev/ttyusb0, so I figured this was the guy.  I modified the script like so:

ser = serial.Serial("COM5", 9600) # windows
ser = serial.Serial("/dev/ttyusb0", 9600) # *nix

Saved and ran it again and then saw the output scroll as the Pi connected to the duino, then the dartboard speaker beeped "Charge!" when it entered play mode, then correctly reported what segments I pressed on the dartboard contact film matrix thingy.

So another milestone, I successfully (and quite easily) ported the python code from my windows laptop to my Raspberry Pi and have both talking with the duino/dartboard circuit.

Just for kicks, I loaded my Jumpman intro into IDLE and it ran flawlessly.

Next steps: hardware=cut perfboard/pcb down to size and move breadboard prototype over to it.  considering adding LED indicators where the 6 game buttons are --- maybe a couple RGB leds, one for connection to the game server (red not connected, yellow/orange connecting, green connected) and one for play mode (red stopped, orange paused, green playing) and then 4 more LEDs to do whatever with.  Or maybe instead of 2 RGB, just 2 red, 2 orange, 2 green and use 3 separate indicators for each state... that will tie up all 6 button holes with something that is reasonably useful and I won't have to think of something else to use LEDs for, like wasting time with blinking patterns or something... although I know where you can find some sweet LED blinking code. So if I get the pcb built, then screw it into the dartboard case and close it up and hope it doesn't fall apart when I start throwing darts at it.

Next steps: software=still need to jump in and code the game engine in pygame.  Have been jotting down ideas here and there, but now is the time to act, now is the time to code. Need to try to convince myself to use a simple, working design and refactor bells and whistles later. I think I want to try to auto-detect the serial port that the duino is on as a first step, then do a simple game menu maybe, and then the game play for a simple game, like around the clock.

l8r

Saturday, September 7, 2013

Python Serial Talkies, Interface Milestone 2

I tweaked the arduino dartboard interface sketch a little bit and wrote a test python script to talk to the dartboard.  I used PySerial to handle the USB port.  It was easy to implement and is working well so far.

I put a little handshake business in there, but otherwise really trust that everything will work just swell all the time.  It worked almost immediately, so I got to spend a long time fiddling with minutia.  

I let it sit for a couple days and then kept noticing the snipped wires from the dartboard's speaker dangling near the small breadboard that attaches to the dartboards ribbon connector.  So I found the Arduino tones example, wired the speaker to the breadboard, grounding one and sending the other to arduino digital pin 12, through a 100 Ohm resistor and added a generic playMelody procedure in the interface sketch.

// based on the arduino tones example, plays the given melody
void playMelody(int melody[], int noteDurations[], int notecount) {
  // don't even try to play nothin' if we don't got no speaker
  if (HAS_SPEAKER) {
    noTone(SPEAKER_PORT);
    
    // iterate over the notes of the melody:
    for (int thisNote = 0; thisNote < notecount; thisNote++) {
  
      // to calculate the note duration, take one second 
      // divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      int noteDuration = 1000/noteDurations[thisNote];
      tone(SPEAKER_PORT, melody[thisNote], noteDuration);
  
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      
      // stop the tone playing:
      noTone(SPEAKER_PORT);
    }
  }
}

Then a playCharge procedure which is called when the interface changes to the play state.

void playCharge() {
  int notes[] = {NOTE_G3, NOTE_C4, NOTE_E4, NOTE_G4, NOTE_E4, NOTE_G4};
  int durations[] = {8, 8, 8, 4, 8, 2};
  int noteCount = 6;
  
  playMelody(notes, durations, noteCount);
}


...
      case IFACE_PLAY:
        if (gameState == IFACE_STOP) {
          gameState = IFACE_PLAY;
          Serial.write(IFACE_PLAY);
          playCharge();
        }
        break;
...

It's totally awesome.

I ordered me a raspberry pi and will be working on the pygame dartboard game engine.

Monday, September 2, 2013

Inside the Board, Interface Milestone 1




Finally got around to opening up the dartboard.



It was pretty much what I expected based on the other projects I have seen... 2 clear plastic sheets with conductive patterns printed on them.  An insulator sandwiched between them with holes allowing the plastic sheets to make contact when pressed together.


The dartboard wedges are really big plastic buttons that press these sheets together to make contact, registering a hit.

 The sheets terminate in a pair of short ribbon cables crimped to a ribbon connector which is soldered to the dartboard's small pcb brain. The pcb has a small lcd display, 2 sets of rubber buttons and wires running to a small speaker, an ac power adapter jack, and a battery compartment.



What I didn't expect was the configuration and layout of the 2 contact sheets.  I was hoping for something like a 10x10 matrix, but instead it is a 7x10 matrix.  This means that the inner and outer single-score wedges are wired together and pretty much eliminates some of the games I wanted include.  Oh well.  Maybe I'll hack the sheets to split them into separate connections for v2.

The way these are wired... the board is split into 2 halves: from the 9 wedge clockwise around to 10 and then from 15 around to 14.  The sheet with 7 wires has 3 connections on each half - 1 each for the single, double and triple segments.  The 7th connection on this sheet is for the bulls-eye.  The other sheet has 10 wires... each wire goes to 2 wedges, one on each half of the board, and with 2 wires also connecting to the bulls-eye - one to the single bull and the other to the double.




So when you hit a triple 20, you hit a wire connected to both the 20 and 16 wedges on one sheet and you hit a wire connected to the triple ring on the 9 through 10 half of the other sheet; or row 6, column 0; or boardMatrix[6][0].  Should be easy enough to hook this thing up to the duino, huh?




First thing i did was cut the wires to the batteries, ac jack and speaker and unscrew the pcb from case.  Next, I grabbed a soldering iron and solder sucker and desoldered the 20-pin ribbon connector.  This connector also happened to be glued to the pcb, so a combination of rubbing alcohol, screwdriver and needle-nose pliers finished the job.


 There were some solder lumps on the pins still, so I used the iron to pull some of this off and smooth out all the pins so they could fit into a breadboard.


I started out using just one 595 shift register and 2 duino data pins to send a signal to the board's 10 wired sheet, but for some reason i wasn't making any connections from the duino data pins.  The multimeter showed 5v coming from the pins, going into the ribbon connector and even from the conductive sheet, yet when the connection was made from these data pins directly to the dartboard, hardly any voltage was coming out the other side.  I don't know why.  I am curious, but would rather get this working than figure that out... so I just daisy chained another 595 for the other 2 lines and this worked very well. Possibly unnecessary given the available duino data ports,  but so it goes and so it goes and so it goes.

The final circuit has the duino activating "rows" one at a time in sequence on the 10 side, using the daisy chained 595 serial-to-parallel shift registers.  Then the duino checks all 7 "columns" in sequence on the 7 side, through a single 589 parallel-to-serial shift register, looking for a hot wire.  If it finds such a wire, then it stores the row and column that made the connection, and looks up the wedge value and multiplier segment for that row,column.  This row, column is considered to be in a "pressed" state.  The duino continues to loop through the rows and columns and once this hot row,column is no longer hot, it is considered "unpressed" and a message with some details is sent out the Serial.

When the dart hits the board, the button is pressed for a whole bunch of cycles and we only want to treat it as a single hit.  That's why I just keep track of what was hit and only consider it to be really hit when the button is no longer pressed.  Other projects I have seen just run a delay command when a button press is detected, but I like this unpressed approach better.  I might try a 2d array to hold the state of all buttons, which could be another improvement, but I think this should work for now.

 When I first wired it up, I had a few wires out of place and some of the wedge/multiplier mappings backwards, but these were easy to track down and fix and the whole thing was pretty simple to implement on both the hardware and software sides.  I tested all buttons manually and everything is in working order.


I think this can be considered a milestone.  Cool beans.

So the first version of the sketch is out on git.



Next hardware step is to move my circuit from the breadboards to a pcb about the same size as the board's original pcb, so I can just screw it into place.  Then I'll want to find an extry long mini usb cable.  I'm going to try to find a grommet to fit where the ac power jack sits in the dartboard case and have the usb go through there.  I might eventually try to find another small LCD to use to display my own nonsense.... but that's probably not necessary.

Next software step is to conjure some python code to receive these Serial messages and do something useful.  And order a raspberry pi.  My dog has no nose. "How does he smell?"  Awful.

I have some pics I took along the way which I may or may not add later.  This is the worst blog ever, but I'm happy about the progress I made with the dartboard and Arduino interface, so whatevs, b's.

Monday, August 26, 2013

Software Bug

I thought I ruined some of my IC shift registers due to my inexperience with hardware.  Turns out it was a bug I introduced in the duino sketch when i was cleaning up the comments and debugging output.  I cleaned up a little bit that pushes the shift register's serial shift-parallel load from low to high.  This was the "serial shift" part of the deal and a good reason for the shift register to stop shifting.

I suppose I should have more confidence in my hardware abilities... and less in my coding :)

Of course I spent way too much time troubleshooting and building and rebuilidng circuits than I should have before I looked at the code, but I gained some experience in the process... and tested my duino assembly a little more completely... although I still haven't messed with the analog ports.

I see how cluttered these relatively simple circuits can get on a breadboard, so I'm going to start looking for some options... maybe more breadboards.  I also have a nice tangled mess of resistors in my little plastic craft box.  Somewheres I saw someone mentioned getting a 3 ring binder with plastic inserts for collecting baseball cards.  I'm going to look into that and see if someone has a sticker template to print out resistor values along with the color codes, since I'm slow at learning my colors.

With my troubleshooting disaster behind me, I am ready to move on... maybe daisy chaining the shift registers and then reading an 8x8 "button" matrix with one of each shift register.  Then I'll open up the dartboard and see what's inside.

*EDIT*
Decided to add my troubleshooting sketch to my git, ShiftInBasic.  This is what I was messing with to find the problem with my circuit when I ended up finding the problem with my code.

And here's a pic of the circuit... you can see I got me an 8 bit dip switch which made things a little easier to test. And look at those professional solders on the Boarduino's breakout pins :)  I'm really glad I finally put the little bastard together, I am thoroughly enjoying his company.



Starting at the bottom right corner, the 7 yellow wires extend the 10K pull down resistors to the far-right ground rail.  Above them is the dip switch with 8 blue wires touching the middle 5v rail.  There are 7 yellow wires running from the dip switch to the 7 parallel input ports on the right of the shift register (which is "upside down" at the bottom of the small breadboard.  By upside down, I mean pin one is on the lower right instead of on the upper left).  The green wire coming from the dip switch runs to the first parallel input pin on the left of the shift register.  It's hard to see the other pull down resistor, but it is plugged in beside the green wire running up the left to the leftmost ground rail.  Finally, 2 yellow and 2 orange wires run up the left of the shift register to the duino's data ports on the upper left of the small breadboard.  From bottom to top, these are the Serial Shift-Parallel Load (yellow, to digital 8), the latch clock (yellow, to digital 9), the shift clock (orange, to digital 10) and the Serial Data Output (orange, to digital 11). The rest of the wires extend the 5v and ground rails and attach these to the duino and shift register.  

I'm messy.

Maybe I'll look into getting some software to make nice circuit diagrams.  I wasn't going to do all that here since all the examples that I link to tend to have really nice diagrams and better writing... but maybe I'll start putting some on here in case those links get broken in the future.  Maybe I will, I should write down a reminder. Someday, I suppose. 

Sunday, August 25, 2013

Still Shifting LEDs

I think I ruined something, maybe my 74HC589.  I left  it running and had 2 LEDs turned on and at some point the LEDs went out.  I tested the circuit with the shiftOutBlinkPlus sketches which showed that the HC595 and 4 LEDs were all working.  Maybe I shorted the circuit some how, I dunno.

So I dismantled the circuit and bought some more LEDs and resistors, and redid the basic ShiftOutBlinkPlus circuit, but with 8 LEDs, called it ShiftOutBlinkPlus8.

This is pretty much the same as the code for the 4 bit version, except I changed the way I created the last few patterns.

Instead of this:

// shifts every other LED on and off
void eitherOr() {
  // getting lazy about generating patterns algorithmically
  // so just setting the nybbles by hand
  bitWrite(pattern, 0, pos);
  bitWrite(pattern, 1, neg);
  bitWrite(pattern, 2, pos);
  bitWrite(pattern, 3, neg);
  displayPattern();
  delay(delayCount);
  
  bitWrite(pattern, 0, neg);
  bitWrite(pattern, 1, pos);
  bitWrite(pattern, 2, neg);
  bitWrite(pattern, 3, pos);
  displayPattern();
  delay(delayCount); 
}

I added a new helper method:

// return positive or negative pattern according to
// negation settings
byte posNegPattern(byte pattern) { 
  if (neg)
  {
    pattern = ~pattern;
  }
  return pattern;
}

And the pattern for 8 LEDs became this (the "0b" prefix indicates a binary number and, as you know, there are 10 types of people, those who know binary and those who do not):

void eitherOr() {
  // getting lazy about generating patterns algorithmically
  // so just setting the nybbles by hand
  pattern = posNegPattern(0b10101010);
  displayPattern();
  delay(delayCount);
  
  pattern = posNegPattern(0b01010101);
  displayPattern();
  delay(delayCount); 
}

Next time I'll try building a circuit with only the HC589 and see if it still works.


Saturday, August 24, 2013

More Shift RegisterTests

So I updated the ShiftOutBlinkPlus code with all the patterns from the BlinkPlus code and everything was working just swell.

I decided to kick it up a notch and introduce the parallel in-serial out 74HC589 shift register to my test circuit.  I wired 4 digital i/o pins from the arduino to the 589's shift clock, latch clock, serial shift-parallel load and serial out pins.

I give some more details on this Arduino Forum post, which also explains the trouble I had.  I was always missing the first bit, and the 8th parallel input pin seemed pretty useless.

As the post explains, this is because the shiftIn() function sets the clock to HIGH first, then reads the data.  It was not obvious to me at first, but looking at the datasheet for the 74HC589, this approach will lose the first bit placed on the output pin (which is actually the bit coming from the 8th parallel input pin).

So how the 74HC589 basically works is, there are 8 input pins, one output pin and 3 control pins.  Inside, it has a data latch and the shift register.  You toggle the latch control to send data from the 8 inputs into the data latch.  You toggle the parallel-load control to send the data from the data latch to the shift register prepare for shifting.  Then you toggle the shift clock control to shift the data out through the serial output pin.

Again, the Arduino's shiftIn() code first toggles the shift clock, then reads the data.  The problem is that when you finish toggling the parallel load control for the "prepare for shifting" part, the first shift occurs and the first bit (from the 8th input pin) is available on the data pin.  When shiftIn() is called, the clock is toggled and the next bit (form the 7th input pin) is shifted to the data pin and is the first bit actually read by the code.

Anyway, the Arduino code is freely available on github, so I just copied the code into my project and changed it so it reads the data pin before toggling the shift clock, like so:

// replaces built-in shiftIn to read the first bit before pulsing the clock
uint8_t naShiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;

for (i = 0; i < 8; ++i) {
// digitalWrite(clockPin, HIGH); // this was here
if (bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);

digitalWrite(clockPin, HIGH); // this is now here
digitalWrite(clockPin, LOW);
}
return value;
}

So my new test sketch is ShiftInAndOutBurger which reads a byte from the 74HC589 shift register every 5 seconds and passes the byte to the 74HC595 which is still connected to my 4 red LEDs.  So, connecting a wire from the vcc to any of the 1st four parallel input pins of the HC589 will light up the matching LED.

Another note about this circuit is the use of pull-down resistors.  When any of the 8 input pins is NOT connected to vcc, they are essentially open switches and they are "floating."  When floating, the input can be influenced by white noise and start lighting things up that you don't want lit up.   To prevent this white noise, you connect the floating pit to ground through a resistor, typically 10k ohms, which will sufficiently suppress the noise.

My next test will be to daisy chain 2 74HC595s and 2 74HC589s to control 16 LEDs, but I'm gonna need more LEDs and more resistors.

Once I get that working, then I think I will have learned enough to build a circuit to read the dartboard.

Friday, August 23, 2013

Shift RegisterTests

Finished testing all of the digital outs, looking good.

Decided to test the 74HC595 shift register in the circuit instead of testing the analog ports.. I'll get to that later, maybe.

The 74HC595 is an 8-bit serial to parallel shift register.  What that means is you send it 8-bits in a row, one at a time on its input pin, flip a switch and it throws all 8 bits to 8 output pins at the same time, in parallel. This shift out example was very helpful in explaining how the 74HC595 works and how to wire it up to the duino.

This is overkill for my test, but useful.  It basically allows you to turn 3 ports into 8 ports - you use 3 ports from the duino to control the shift register: 1 to send the data, 1 to tell the 74HC595 to "shift in" the bit you are sending it, and 1 to flip the "latch" when you're done to send out the data to the parallel pins.

I used the shift out example's hello world example, modified it slightly for my test (i used different duino ports and only 4 LEDs) and felt pretty confident about using this little guy in my circuits.

So I had all these grand ideas of how I could use classes and dynamic arrays to build bytes to send to the shift register and turn my BlinkPlus sketch into an awesomely elegant piece of code.  This is where I learned some lessons about the limitations of programming a microcontroller like the duino and how the code is built and compiled.  So much for dynamic array type definitions, linked lists, and so on and so forth.

Eventually, I updated BlinkPlus to use the shift register.  Right now I only implemented one of the patterns, but it should be pretty quick and painless to convert the rest.  Here's how it works...

First I set up the 3 digital ports that the duino will use to control the 595:

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 3;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 2;
////Pin connected to Data in (DS) of 74HC595
const int dataPin = 7;

// control variables
int delayCount = 500;
int repeatCount = 4;

byte pos = 1;
byte neg = 0;

byte pattern = 0;

// the setup routine runs once when you press reset:
void setup() {     
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

The main loop iterates through each of the 4 LEDs and blinks them on and off a set number of times:

// the loop routine runs over and over again forever:
void loop() {
  
  reset();
  delay(delayCount*2);
  
  for (int i=0; i < 4; i++)
  {
    for (int j=0; j < repeatCount; j++)
    {
      blinkoUno(i);
    }
  }
  
  // toggle negative
  setPos(neg);
}

blinkoUno was rewritten to modify the bits of the global byte variable named "pattern" instead of sending HIGHs and LOWs directly to the LEDs.

// blink the given bit on then off
void blinkoUno(int ledNum) {
  bitWrite(pattern, ledNum, pos);
  displayPattern();
  delay(delayCount);
  
  bitWrite(pattern, ledNum, neg);
  displayPattern();
  delay(delayCount);
}

It calls the displayPattern function which jumps through all the necessary hoops to send the byte to the 595 serially (one bit at a time) and then flip the latch switch to send all 8 bits to the 595's 8 output pins:

// sends the given byte to the shift register
void displayPattern() {

  // take the latchPin low so 
  // the LEDs don't change while you're sending in bits:
  digitalWrite(latchPin, LOW);
  
  // shift out the bits:
  shiftOut(dataPin, clockPin, MSBFIRST, pattern);
  
  //take the latch pin high so the LEDs will light up:
  digitalWrite(latchPin, HIGH);
}

Just in case... a byte consists of 8 bits.  A bit is a value that can either be 1 or 0, bits are like switches, they are on (1) or off (0).  Each bit corresponds to one of the shift register's ouput pins... the first bit in the byte controls the first ouput pin, the second bit controls the 2nd ouput pin, etc.  So if I want to turn on both the first and third LEDs, i would send the byte 00000101 (assuming the first LED is wired to the first output pin, and so on).

One thing that can be confusing is that most people look at a row of LEDs and think the leftmost LED is the first LED.  In the byte, the rightmost bit is the first bit: 00000001.

I used the bitWrite command to turn the bits on and off.  To turn on bits 1 and 3 in the byte variable "pattern", you would do this;
 bitWrite(pattern, 1, 1); // set bit 1 of the byte "pattern" to 1 (on)
bitWrite(pattern, 3, 1); // set bit 3 of the byte "pattern" to 1 (on)

Another way to do this would be using the bitSet command:
bitSet(pattern, 1);  // set bit 1 of the byte "pattern" to 1 (on)
bitSet(pattern, 3);  // set bit 3 of the byte "pattern" to 1 (on)

To turn bits off, you can either use the bitWrite or bitClear commands:

bitWrite(pattern, 2, 0); // set bitv2 of the byte "pattern" to 0 (off)
bitWrite(pattern, 4, 0); // set bit 4 of the byte "pattern" to 0 (off)

bitClear(pattern, 2);  // set bit 2 of the byte "pattern" to 0 (off)
bitClear(pattern, 4);  // set bit 4 of the byte "pattern" to 0 (off)


Anyway... a couple more procedures from the code that I haven't mentioned yet are reset and setPos.

SetPos lets you switch the values of the pos and neg variable to on or off to easily display the patterns as negative images.

void setPos(byte posVal)
{
  pos = posVal;
  neg = !pos;
}

This is why I used the bitWrite command instead of bitSet and bitClear.  I just send bitWrite either "pos" or "neg" to generally define the pattern and calling setPos defines whether pos is on and neg is off, or the other way around.

Reset switches all bits off:

// sets all bits to off
void reset() {
  if (pos == 1)
  {
    pattern = 0;
  }
  else
  {
    pattern = ~0;
  }
  
  displayPattern();
}

If pos is set to display positive images, then I set the byte to 0 (which is really 00000000).  If it is set to display negative images, then I set it to ~0, which uses the bitwise NOT operator - which flips every bit in the byte to the opposite setting.  So if 0 = 00000000, then ~0 = 11111111.  I could have also just set it to 255, which is the decimal equivalent of 11111111, but I wanted to have an example of ~ in my toolbox.

So the complete code is all checked into git, and what it does is:

  • reset, turn all 4 LEDs off
  • blink the first LED on and off 4 times
  • blink the second LED on and off 4 times
  • blink the third LED on and off 4 times
  • blink the fourth LED on and off 4 times
  • set pos to 0 (OFF, or negative mode)
  • reset, turn all 4 LEDs ON
  • blink the first LED off and on 4 times
  • blink the second LED off and on 4 times
  • blink the third LED off and on 4 times
  • blink the fourth LED off and on 4 times
  • repeat until you unplug it or something breaks
I'm going to update it to display more patterns and do the whole random thingy stuff.

Thursday, August 22, 2013

BlinkPlus

As I mentioned in my previous post, I dug into the Blink example and played around.  This got me comfy with the Arduino IDE, working with the digital out pins, breadboarding simple boarduino circuits and it allowed me to test the boarduino (at least with the digital outs) to make sure my soldering was adequate.

So, in my first test with the Blink example, I didn't use an LED, i  just let it flash the on-board LED which is connected to the duino's digital port 13.  So this time, I grabbed a generic red LED, a 330 Ohm resistor and some jumper wires (the examples say 220 Ohm, but I didn't have any and I referred to my Electrodroid app which recommended 330 for a red LED)
I plugged the duino, LED and resistor into the breadboard, wired duino gnd to the negative (short) LED pin, wired duino d13 to the resistor, and wired the resistor to the positive (long) LED pin.

Then I plugged the duino into my laptop with USB and since it was already running the Blink sketch, and since the blink sketch flashes d13, and since the on-board LED and my red LED were both wired to d13, both blinked.

I had exactly 3 more red LEDs in my bag of tricks, and at least as many 330 Ohm resistors, so I added 3 more resistor/LED pairs and wired them up like the other one, except i wired the 4 LEDs to duino ports d8, d9, d10 and d11.

Then I modified the Blink sketch to look like this:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
//int led = 13;

// array, 4 pins for 4 LEDs
int led[4] = {8,9,10,11};

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  //pinMode(led, OUTPUT);

  // loop through array of pins, set each to OUTPUT
  for (int i=0; i<4; i++)
  {
    pinMode(led[i], OUTPUT);
  }

}

// the loop routine runs over and over again forever:
void loop() {
    // loop through pins, turning all LEDs on
    for (int i=0; i<4; i++)
    {
      digitalWrite(led[i], HIGH);   // turn the LED on (HIGH is the voltage level)
    }

    delay(1000);               // wait for a second

    // loop through pins, turning all LEDs off
    for (int i=0; i<4; i++)
    {
      digitalWrite(led[i], LOW);    // turn the LED off by making the voltage LOW
    }

    delay(1000);               // wait for a second
}

Uploaded the sketch to the duino, and all four LEDs blinked.  Magic.

So then I started to add methods to the sketch that turned the LEDs on and off in patterns, like the knightrider pattern.... I added them one at a time and updated the sketch to run the same pattern over and over and finally, wrote a method that randomly sets the delay, repeat and picks a pattern to run.  I checked this code into git, named it BlinkPlus.

I am going to rerun it with ports d2-d7, d12 and then try out an analog example to test out the remaining I/O ports.  So far so good.