Monday, December 19, 2011

Building your own Arduino board with the "Sparkfun Arduino Compatible PTH Kit"

Some of you, like our students, are going to want to really "get under the hood" with microcontrollers and learn how to "build your own".  We've noticed that when you use microcontrollers "out of the box" it is hard to appreciate their components. We tend to use them as discrete objects and never really gain an appreciation for what makes one microcontroller different from another. We will say things like, "The Arduino Romeo is better for running a Sea Perch because it has 2 built-in motor controllers" but we don't really come to appreciate which components vary and which don't and what makes one Arduino board more suitable for a task than another.

By building your own basic Arduino board using the Sparkfun kit, you get to touch and mount and solder each component individually and this gives a real appreciation for what the components are and do and ultimately will enable you to build new custom boards and expand the capabilities of what these boards can do (to do all those cool robotic things that only your imagination can conceive of!).

If you are highly ambitious, you can make your own Printed Circuit Board (a.k.a. "PCB" or PC Board) from scratch, doing the design, etching and drilling yourself.  But for starters we will work with boards that are pre-wired and drilled and simply needs its components soldered on.  The Arduino Compatible PTH Kit is one such introductory kit.  It "gives you all the components you need to build your very own development platform. When you're done with this kit, " they say, "you'll not only have a fully-functioning microcontroller that can be used with Arduino code and software, but you'll also have a greater understanding of how your development platform works. This kit is built with the beginner in mind and features only through-hole soldering."

The kit includes:

  • 1x ATmega328
  • 1x28-pin socket
  • 2x6-pin female headers
  • 2x8-pin female headers
  • 1x6-pin right-angle male header
  • 1x momentary push button
  • 1x 5mm green LED
  • 2x 330 Ohm resistors
  • 1x 10k Ohm resistor
  • 1x 16MHz crystal
  • 2x 22pF ceramic capacitors
  • 5x 0.1uF ceramic capacitors
  • 2x 100uF electrolytic capacitors
  • 1x 1N4001 diode
  • 1x MCP1700 3.3V regulator
  • 1x PTC
  • 1x barrel jack connector
  • 1x Arduino Compatible PTH Kit PCB
(Note that here PTH stands for "Pin Through Hole")


To solder a PC Board that is a pre-drilled "PTH", like the one that Sparkfun supplies, we want to be careful not to overheat the back of the board.  If you are using an inexpensive soldering iron, the recommendation is to stay within 10 Watts to 30 Watts so as not to damage the board or components.  For a more expensive soldering iron with adjustable temperature, like the Weller WES51 that we are using, we dial the Fx10 (degrees Fahrenheit x 10) control to between 60 and 65.  This is because "The melting point of most solder is in the region of 188°C (370°F) and the iron tip temperature is typically 330°C to 350°C (626°F to 662°F)."

The tecknick.net site tells us,
"...ensure that the temperature of all the parts is raised to roughly the same level before applying solder. Imagine, for instance, trying to solder a resistor into place on a printed circuit board: it's far better to heat both the copper PCB and the resistor lead at the same time before applying solder, so that the solder will flow much more readily over the joint. Heating one part but not the other is far less satisfactory joint, so strive to ensure that the iron is in contact with all the components first, before touching the solder to it...  the joint should be heated with the bit for just the right amount of time -- during which a short length of solder is applied to the joint. Do not use the iron to carry molten solder over to the joint! Excessive time will damage the component and perhaps the circuit board copper foil too! Heat the joint with the tip of the iron, then continue heating whilst applying solder, then remove the iron and allow the joint to cool. This should take only a few seconds, with experience. The heating period depends on the temperature of your iron and size of the joint -- and larger parts need more heat than smaller ones -- but some parts (semiconductor diodes, transistors and integrated circuits), are sensitive to heat and should not be heated for more than a few seconds. Novices sometimes buy a small clip-on heat-shunt, which resembles a pair of aluminium tweezers. In the case of, say, a transistor, the shunt is attached to one of the leads near to the transistor's body. Any excess heat then diverts up the heat shunt instead of into the transistor junction, thereby saving the device from over-heating. Beginners find them reassuring until they've gained more experience."

 Our electronics wizard at Motion Picture Marine, Mark Volivar, keeps his Weller WES51 at 75 (750 degrees F) because "if you keep it at a lower temperature you will be tempted to keep the iron on the component lead longer and then you risk damaging the component or board.  If you keep it hotter you heat the component to the desired temperature quicker and can get in and out fast".

A good illustrated tutorial for soldering PCB boards is found here: http://www.aaroncake.net/electronics/solder.htm
This site has a nice short video showing the proper technique.
They say,
"If you see the area under the pad starting to bubble, stop heating and remove the soldering iron because you are overheating the pad and it is in danger of lifting. Let it cool, then carefully heat it again for much less time. "


As I solder the components on the board I lay my blue Arduino Uno, purchased from Sparkfun, next to the characteristic red  Sparkfun "Adunio Uno Compatible PTH Kit" board, to see what the differences are.  The most obvious, of course, is the color, but beyond that there are big differences. What is similar about them is what strikes the eye:  the size and shape of the board and the number and location of input and output pins along hte sides of the boards.  It is these that allow one to use shields made for the one on the other.

Let's see, as I solder each component on the Arduino clone (the PTH kit board), how it compares with the original.

The first thing I solder on are the Right Angle to 6 pin male Header pins.  These seem to go where the USB jack is located on the Arduino Uno. The pin assignments on the clone board are "DTR, TX-0, RX-I, 5V, GND and GND".  We will work on understanding the relation of these pins to the USB mounted jack later on; what is nice is that this project of building an arduino may help demystify the function and pin assignments of USB jacks.

The second and third part of the assembly are the two 330 ohm resistors and the single 10 kilo-ohm resistor.  These are hard to distinguish in the Arduino Uno board, but there seem to be tiny microresistors in the correct locations near the micro-LED lights for L and ON.

Step 4 is the 22pF Capacitor, which are not to be confused by the 0.1 microFaraday capacitors (they look alike, so read the printed label on the mustard colored body).  There are two to be installed.  If your eyes are as bad as mine you will need a magnifying glass to see the labels (I use one for all my soldering too, one on a stand with clips sold in many electronics stores).  Note that the capacitors (sometimes called simply "caps") are labeled on both sides, so don't get confused. The one's we want here say "220" on one side and "K2J" on the other.

 On the Arduino Uno I can't seem to find an easy visual equivalent for these two caps, which surround a spot meant for a 16MHz Crystal component located above the primary IC. There is a tiny soldered component above what looks like a silver metal slug (and to the left of the reset push button) so maybe that is the equivalent.

In Step 5 you install the five 0.1 microFarad caps.  They have "104" on one side and "K5M" on the other.
If what I think are the micro-capacitors on the Uno are indeed that, then one can sort of see the correspondence between the two boards...

In Step 6 you install a 1N4001 Diode and this you have to pay careful attention to because it is polarized, meaning the plus side and minus sides have to be installed facing the right direction.  The silver band on the diode can fortunately be lined up with the white line on the PCB.  I'm believing that the black rectangle with the letters M7 etched on it is the Uno equivalent.

Step 7 is the installation of the LM7805 5V Regulator.  The tutorial that comes with the kit tells us to "bend all three legs at a 90 degree angle so they point toward the back of the chip. Insert the regulator matching it up with the white outline on the PCB; the metal side of the regulator should be touching the board."  I couldn't get the hole in the regulator to line up exactly with the hole in the board, but it seems okay.
The equivalent on the Uno board is fairly obvious because of the three legs.

Step 8 is the MCP1700 3.3V Regulator.  Hard to tell what on the Uno board is the equivalent. It might be the yellowish larger rectangle at the edge of the baord next to the 5V regulator that says 2005 on it, or it could be the tiny rectangular black box under it.

Step 9 involves inserting the 16MHz Crystal in the center of the board. This looks identical to the silver metal cased oval on the Uno board, only it is in a different location.

It is nice that the instruction manual makes clear which components have polarity (indicated in yellow on the schematic) and which don't (indicated in green on the schematic) so that we don't have to worry when installing something like the 16MHz crystal (which can be installed in either direction). This attention to detail and fool-proof assembly through color and clear descriptions will be critical to any kit we develop too so that students are not only free from intimidation but so that a project doesn't get derailed because of a simple error in assembly destroying a board which would be expensive in time and money for an at risk school to replace.

Step 10 is the Reset Button.  It doesn't seem to matter which way you insert it as long as you do it gently (it is indicated in green!).  The reset button has a direct visual equivalent on the same location of the Uno board (the only difference is that the Uno reset seems to have 5 pins and the one on the clone only 4).

Step 11 is a resettable fuse (called a PTC which stands for "positive temperature coefficient").
Sparkfun says these components can protect your board from disaster:

"This is a handy little device that can save your system from smoking. A resettable fuse (also known as a PTC) is a resistor that has very unique properties ... For this model, if your circuit tries to draw more than 250mA of current (if you have a bad short for instance) the PTC would 'trip' (by heating up). The increased resistance (trip state) would break the circuit and allow only a small leakage current."

The general class of components of this type is a "thermistor" (a combination of "thermal" and "resistor"). Wikipedia tells us, "Thermistors can be classified into two types, depending on the sign of k. If k is positive, the resistance increases with increasing temperature, and the device is called a positive temperature coefficient (PTC) thermistor, or posistor. If k is negative, the resistance decreases with increasing temperature, and the device is called a negative temperature coefficient (NTC) thermistor."

The instruction manual says to "push it down as far as it will go" but the PTC has kinky looking spider legs with bends in them and these seem to inhibit pushing down very far unless you are willing to straighten the kink out.  My thought is that the bends in the legs must be there for a reason, so for now I am only pushing the thermistor down to the kink in the leg.

There doesn't seem to be an obvious equivalent on the Uno unless it is the black rectangle that I took to be the diode. 

In step 12 we mount the 8-pin and 6-pin female headers on the top and bottom sides of the board. These are identical to what we find on the Uno, being the input and output headers for both digital and analog pins and power pins; this is what you also mount arduino shields onto.

In step 13 we insert the red and green LED's.  These are polarized so we must carefully observe where we place the positive lead (the long lead) and the negative lead (the short one which is on the flat side of the plastic bulb casing -- you can find it by rolling the LED until it stands still on the flat side).  Because the PTH kit board doesn't indicate positive or negative, you use the white markings on the PCB to align the flat side (so that the shorter negative lead is facing the reset button and the 6-pin female headers side of the board.)

On the Uno board the LEDs for ON and STATUS (L) are in identical places on the board; they are just much much smaller, appearing as tiny rectangles.  The Uno also has two more LED indicators underneath the L LED; these are labelled TX, for transmit, and RX, for receive, respectively. They tell us when the board is communicating with the computer when uploading information or downloading sketches.


Step 14 involves putting the barrel jack on the board. The pins go through three fairly large holes and the instructions say "you may have to use a little extra solder on this part.  From looking at the comparable part on the Uno it seems you should fill in the entire hole. That really does take a lot of solder!

Step 15, soldering the 28 pin socket, involved putting a ballpoint pen under the socket to keep it in place while soldering and being careful while doing all 28 pins not to let the solder bleed from one pin to another.  It is good that they have you attempt this part at the end so that you have built up a lot of experience soldering PC boards before attempting this.  The temptation of somebody not involved in education would be to have people solder the socket on at the beginning because it would be easier to hold it in place without the female pin headers and other components sticking out.  By the way, this component is polarized -- make sure the notch on the socket lines up with the white line notch marked on the board.
The Uno board has an IC in the same place but it is a tiny square rather than the large 28 pin arthropod looking thing supplied for the clone.

Step 16 involves putting the polarized 100 uF capacitors in place; they must be placed with the gold stripe (the shorter lead) facing the barrel jack -- this is easily done because the board is marked with a minus sign on the left side of the markings (left if the barrel jack is to the left).  On the Uno the caps are much shorter but are in the same location.

The last step is aligning and pushing in the ATmega328 chip.  You want the notch marked  at the end with the A6/A5 marked on it (it says "UNO" under it) to line up with the notch at the end of the board (the side farthest from the barrel jack).  Conveniently the chip has a white label strip on it with indicators for what each pin is (A6, D0, D1, D2, D3, D4, VCC, GND, X1, X2, D5, D6, D7, D8 on the top side (the side facing the reset button and LED's) and A5, A4, A3, A2, A1, A0, GND, AREF, AVCC, D13, D12, D11, D10 and D9 on the bottom side (facing the 6 pin female headers).

You have to be careful as you "bend the legs slightly inward" to plug it in. As they say, "be gentle, don't force it" and rock it in place.

Voila. Done.

Interestingly, the board does have 6 holes labeled ISP on the side with the reset button, but nothing to populate them with (and the schematic in the instructions doesn't show them at all).  Meanwhile, the Arduino Uno itself has these holes populated by six male pin headers and labels them ICSP.  Also, on the Uno board the same six pin male headers can be found on the side where the USB connector is, next the the 8 pin female header labeled AREF.  So the Uno has extra functionality that our clone does not have (including what look like to microchips the clone lacks, one a square one above the crystal and next to the Tx and Rx LEDs and aother below the crystal.  As we say in Egypt, "Ma'alaysh".  No problem. We've built our first Arduino clone board and learned to compare it with the Uno.   Fun times. Now all we have to do is test it out to make sure there are no short circuits before trying to run some sketches on it.

Thanks for joining us!


Update:

Testing the Arduino clone:  I used a voltmeter with continuity alarm to see if any of the solder joints I made are touching by mistake.  Everything looks good. Two of the barrel jack leads (the ones at the edges of the board) are connected but this is true of the pro-Uno board too so it seems I'm okay.  Now I just have to figure out how to connect the board to the computer since it doesn't have USB. 

The instructions say that "to power the Arduino a DC power source between 6V and 15V should be plugged into the barrel jack. A standard 9V Wall Adapter power supply would be perfect".  I'm used to getting power from the USB on the Uno so I'll have to look around for an adaptor. But this still won't solve the computer connection.

The instructions have the answer, telling me "To load a new program onto the Arduino, you'll need one more piece of hardware -- a 5V FTDI Basic Breakout board.  One side of the FTDI Breakout connects via USB to your computer, while the other side connects to the right angle 6-pn male header on your kit (which was the first component we soldered on).  When you connect the FTDI Breakout to your arduino, make sure to line up the 'blk' and 'grn' labels. The FTDI Breakout can also be used to power your Arduino. If you haven't already, you'll need to install drivers for the FTDI Basic Breakout board." Then it tells us that we need to select the correct port under "Tools>Serial Port" and under "Tools>Board" (we select 'Arduino Uno' since this is a clone). Then we can load new sketches.

Fortunately the ATmega328 apparently comes preloaded with the classic "Blink" sketch so to see if my board is correctly assembled, all I need to do is power it up via the barrel jack.










To program your Arduino visually, look at
http://blog.ardublock.com/
http://www.modk.it/alpha (based on the Scratch environment).
http://blog.minibloq.org/
See this article http://www.funnyrobotics.com/2011/04/minibloq-arduino-gets-another-graphical.html
http://xinchejian.com/2011/02/05/visual-programming-language-for-arduino-1/
http://makezine.com/25/modkit/

(To enable your Android phone to talk to Arduino:
On Android, go to google search, type in Amarino, when the google search comes up click on download. 
Download the apk file to your android phone.  It will appear in the downloads folder. Click on it to install it to your phone (you may have to enable your device to install applications that aren't from the Android market). )

Project Lead the Way STEM program:
http://www.pltw.org/
http://www.pltw.org/getting-started/school_locator

Friday, November 18, 2011

Sparkfun Inventor's Kit Circ-14

/*     ---------------------------------------------------------

 *     |  Experimentation Kit for Arduino Example Code         |

 *     |  CIRC-14 .: Fancy Sensing :. (Soft Potentiometer)     |

 *     ---------------------------------------------------------

 *

 *    Will fade an RGB LED from Red-Green-Blue in relation to the

 *    soft pot value

 *

 */


// LED leads connected to PWM pins

const int RED_LED_PIN = 9;    //Red LED Pin

const int GREEN_LED_PIN = 10; //Green LED Pin

const int BLUE_LED_PIN = 11;  //Blue LED Pin





void setup() {

  //no need for any code here

}

   

void loop() {

  int sensorValue = analogRead(0);   //read the Soft Pot


  int redValue = constrain(map(sensorValue, 0, 512, 255, 0),0,255); //calculate the red Value (255-0 over the range 0-512)

  int greenValue = constrain(map(sensorValue, 0, 512, 0, 255),0,255)-constrain(map(sensorValue, 512, 1023, 0, 255),0,255);  //calculate the green value (0-255 over 0-512 & 255-0 over 512-1023)

  int blueValue = constrain(map(sensorValue, 512, 1023, 0, 255),0,255); //calculate the blue value 0-255 over 512-1023


  // Display the requested color

  analogWrite(RED_LED_PIN, redValue);

  analogWrite(GREEN_LED_PIN, greenValue);

  analogWrite(BLUE_LED_PIN, blueValue);

}
"http://ardx.org/HSB
To convert from RGB to HSB all that is required is some slightly complicated math. Visit http://ardx.org/CODE14MB based on www.kasperkamperman.com's original code: http://ardx.org/KASP

Faux buttons:
 Define a range of values corresponding to a discrete button.
if(analogRead(0) > minValue && 
analogRead(0) < maxValue) {
buttonAction()
}

Then cover the soft pot with a drawn/printed button pattern."

Sparkfun Inventor's Kit Circuit-13

// Based on File > Examples > Servo > Knob
// Controlling a servo position using a potentiometer (variable resistor)
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup()
{
  Serial.begin(9600);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop()

{
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  Serial.println(val); 
  val = map(val, 50, 300, 0, 179);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}


map(value, fromLow, fromHigh, toLow, toHigh)
For full details on how it works: http://ardx.org/MAP
To calibrate the sensor we use the debug window (like in CIRC-11). Open the debug window then replace the fromLow value (default 50) with the value displayed when the sensor is unbent. Then replace the fromHigh (default 300) value with the fully bent value.
                  
void loop()

{
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  Serial.println(val); 
  val = map(val, 269, 140, 0, 179);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there


One player rock paper scissors glove:  http://ardx.org/RPS
Electronic plant brace: monitor if your plant is bending towards light and fix it: http://ardg.org/BRACE


Sparkfun Inventor's Kit Circuit-12

/*

  RGB_LED_Color_Fade_Cycle.pde
 
  Cycles through the colors of a RGB LED

  Written for SparkFun Arduino Inventor's Kit CIRC-RGB

*/

// LED leads connected to PWM pins
const int RED_LED_PIN = 9;
const int GREEN_LED_PIN = 10;
const int BLUE_LED_PIN = 11;

// Used to store the current intensity level of the individual LEDs
int redIntensity = 0;
int greenIntensity = 0;
int blueIntensity = 0;

// Length of time we spend showing each color
const int DISPLAY_TIME = 100; // In milliseconds


void setup() {
  // No setup required.
}

void loop() {
  // Cycle color from red through to green
  // (In this loop we move from 100% red, 0% green to 0% red, 100% green)
  for (greenIntensity = 0; greenIntensity <= 255; greenIntensity+=5) {
        redIntensity = 255-greenIntensity;
        analogWrite(GREEN_LED_PIN, greenIntensity);
        analogWrite(RED_LED_PIN, redIntensity);
        delay(DISPLAY_TIME);
  }

  // Cycle color from green through to blue
  // (In this loop we move from 100% green, 0% blue to 0% green, 100% blue) 
  for (blueIntensity = 0; blueIntensity <= 255; blueIntensity+=5) {
        greenIntensity = 255-blueIntensity;
        analogWrite(BLUE_LED_PIN, blueIntensity);
        analogWrite(GREEN_LED_PIN, greenIntensity);
        delay(DISPLAY_TIME);
  }

  // Cycle cycle from blue through to red
  // (In this loop we move from 100% blue, 0% red to 0% blue, 100% red)   
  for (redIntensity = 0; redIntensity <= 255; redIntensity+=5) {
        blueIntensity = 255-redIntensity;
        analogWrite(RED_LED_PIN, redIntensity);
        analogWrite(BLUE_LED_PIN, blueIntensity);
        delay(DISPLAY_TIME);
  }
}


http://ardx.org/HEXCOL

for hexadecimal colors
http://ardx.org/RGBMB

analogWrite(RED_LED_PIN, redIntensity); to analogWrite(RED_LED_PIN, redIntensity/3);

Sparkfun Inventor's Kit CIRCUIT-11

Ever sat in your car with the blinkers on, listening to that metronome like clicking sound as the lights flash on an off and wondered about the programming and mechanics of that simple behavior? Or watched traffic lights flash from color to color and thought about what goes into that?
This is the world of relays, a land of electrically controlled mechanical switches.  The clicking sound is caused by an electromagnet inside the a little plastic box. When it is energized the coil of wire that makes up the electromagnet becomes magnetic and is attracted to the other side of the switch, pulling it towards the magnet and closing a circuit path, kind of like a train track switching device.  When the current stops the switch goes back to its original position, sending the current down a different track.

When you power this circuit up before loading the code, the yellow LED is lit.  Once you load the circuit it starts switching between the yellow and the red LED with that satisfying blinker click (makes me want to compose a song to its measured tick tock beat...!).

The set up involved 1 10k Ohm Resistor, 1 330 Ohm resistor, 1 P2N2222AG (T092) transistor, one 1N4001 Diode (acting as a "flyback diode -- se http://ardx.org/4001), a yellow LED, a red LED and a Relay (Single Pole, Double Throw or "SPDT").  The wiring looks a bit bird's nest intimidating and the pattern didn't quite line up on the breadboard so I had to be careful to hook up all the wires in the right position, but I got it to work.
This is a case where it helps to look at the schematic at http://ardx.org/CIRC11 , where you will also find the code, to see that the 10K resistor (shown as a 2.2kohm resistor on the website and a 10K in the booklet) connects to Arduino pin 2 and to the base of the transistor, with the emitter going to ground and the collector going to the flyback diode and to the relay pin whose other side is connected to the 5V source which picks up the other side (the negative side) of the diode. The middle pin on the part of the relay facing ground in the schematic, which is actually the pin on the LED side of the physical relay,  is connected to +5 volts while the two pins that are parts of the "different train tracks" (and which the middle 5 volt pin switches between) are each connected to the LEDs through their positive sides, with the negative sides going to ground.








/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
  The circuit:
* LED connected from digital pin 13 to ground.
  * Note: On most Arduino boards, there is already an LED on the board
connected to pin 13, so you don’t need any extra components for this example.
 
Created 1 June 2005
By David Cuartielles

http://arduino.cc/en/Tutorial/Blink

based on an orginal by H. Barragan for the Wiring i/o board
*/

int ledPin =  2;    // Relay connected to digital pin 2 <-----Change this to pin 2

// The setup() method runs once, when the sketch starts

void setup()   {               
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);   
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()                   
{
  digitalWrite(ledPin, HIGH);   // set the LED on
  delay(1000);                  // wait for a second
  digitalWrite(ledPin, LOW);    // set the LED off
  delay(1000);                  // wait for a second
}



The code here is desperately simple; it is simply the "blink" code used through a relay.  Digital pin 2 is used instead of pin 13 and the rest is exactly what one would use for blinking one LED. The difference is that when pin 2  is powered on (ledPin, HIGH) it makes the relay flip to the "train track" that gives the current to the red LED and when off it reverts to a state where the yellow LED is given current.

The use of a flyback diode is interesting. The wikipedia links tells us, "A flyback diode (sometimes called a snubber diode, freewheeling diode, suppressor diode, or catch diode[1]) is a diode used to eliminate flyback, the sudden voltage spike seen across an inductive load when its supply voltage is suddenly reduced or removed.".

Ever since I started working with Joule Thief circuits I've become fascinated with inductors, wherein a magnetic field is created which, when power is shut off, collapses and creates a voltage.  In the case of a relay this can cause arc-ing so the diode here protects from that.
The book suggests replacing the fly-back diode with a light emitting diode.

Thursday, November 17, 2011

Sparkfun Inventor's Kit Circuit-10: Measuring Temperature

The MIT Sea Perch Sensor Suite that we will be using with the students of Venice High School and the Washington Math Science Technology Public Charter School as we "pimp our Perches" to give them autonomy, will use an Arduino board to measure water temperature, depth, light and conductivity.  In the previous Sparkfun Inventor's Kit Circuit Tutorial they showed us how to measure light and use its intensity to control an LED and a servo using a Photo Resistor.  In Circuit-10 we get to play around with a Precision Temperature Sensor.

The temperature sensor looks identical to a transistor.  It fact it looks so much like the two transistors supplied in the Inventor's Kit that you have to be really careful not to confuse them.  Use a magnifying glass and you can see that the temperature sensor has the tiny letters TMP inscribed on the flat side. The other two say P2N2 222A.  So use the one that doesn't say P2N2 222A. Use the one that says TMP (if you can see it, it is so tiny).

This is "a rather complicated IC (integrated circuit) hidden in a package identical to our P2N2222AG transistors. It has three pins, ground signal and +5 volts and it is easy to use. It outputs 10 millvolts per degree centigrade on the signal pin (to allow measuring temps below freezing there is a 500 mV offet, e.g. 25 C = 750 mV so 0 C = 500 mV)." So sayeth the manual.

This tutorial uses the Arduino IDE's serial monitor so that we can see how it converts the millivolts to degrees.
The TMP36 Datasheet can be found at http://ardx.org/TMP36. The code can be downloaded from http://ardx.org/CODE10

The build on this one is really simple; you just plug in the temp IC and connect the right lead to ground, the middle lead to Arduino's Analog 0 pin and the left lead to 5 Volts. Then you paste the code in the sketch and upload it and open the serial monitor (the icon is a square with an antenna).

Mine starts spitting out data saying it is between 21.78  and 22.27 degrees C in the room.
When I hold the black casing of the IC between my fingers it quickly starts to rise in temperature; after a couple of seconds it is over 26 degrees.

The manual says if you want to see the voltage instead of the temperature, delete the line (or comment it out) that says temperature = (temperature - .5) * 100;

Now when I run it the serial monitor shows the room temperature as .73 which must be 730 mV.  When I touch the sensor with my fingers it goes up to .8 within a few seconds.
We can make the serial monitor display the temperature in Fahrenheit by recalling the formula
F = (C * 1.8) +32).  We add a line that says "temperature = (((temperature - .5) * 100) * 1.8) + 32;" and stick it before Serial.println(temperature);

Instead of doing that, because I'm getting more and more confident hacking the code myself, I wrote
void loop()                     // run over and over again
{
 float temperature = getVoltage(temperaturePin);
 //getting the voltage reading from the temperature sensor

  float temperatureC = (temperature - .5) * 100;          //converting from 10 mv per degree wit 500 mV offset
  float temperatureF = (((temperature - .5) * 100) * 1.8) + 32;                                                //to degrees ((voltage - 500mV) times 100)
 Serial.println(temperatureC);
  Serial.println(temperatureF);
 //printing the result
 delay(1000);                                     //waiting a second
}


That way I got a display that showed me both Celsius and Fahrenheit (and note, I had to declare new floats for my new variables temperatureC and temperatureF which I defined with the math.)

The manual says we can create more informative output by changing Serial.println(temperature); to read  Serial.print(temperature);Serial.println(" degrees centigrade"); and it says "the change to the first line means when we next output it will appear on the same line, then we add the informative text and a new line."

I made my code read the following:

void loop()                     // run over and over again
{
 float temperature = getVoltage(temperaturePin);
 //getting the voltage reading from the temperature sensor

  float temperatureC = (temperature - .5) * 100;          //converting from 10 mv per degree wit 500 mV offset
  float temperatureF = (((temperature - .5) * 100) * 1.8) + 32;                                                //to degrees ((volatge - 500mV) times 100)
 Serial.print(temperatureC);
 Serial.println(" degrees Centigrade");
  Serial.print(temperatureF); Serial.println(" degrees Fahrenheit");
 //printing the result
 delay(1000);                                     //waiting a second
}


Now my serial monitor tells me the room is at "22.7 degrees Centigrade" and "72.08 degrees Fahrenheit." Cool... er...warm!

Finally the manual shows us how to make the data transmission to the serial monitor 12 times faster by changing the baud rate from 9600 to 115200.  Change Serial.begin(9600) to Serial.begin(115200) or any value you want and watch the serial monitor fly!
Oops, when I run it I get garbage output, but that is because I haven't changed the speed in the pull down menu at the bottom of the serial montor to 115200.  So I do that and... voila!






Sparkfun Inventor's Kit Circuit-09: Photo Resistors

Most of the robotics that goes on in the military involves what is called "man in the loop", that is, the presence of a human being controlling the ultimate decisions the robot makes.  And that makes sense, particularly when lethality is involved.  Still, there is an important place for fully autonomous robots, robots that can make critical decisions on their own, and the challenge of creating such "artificial intelligence" is seen by many as the apogee of robotics education.

The Sea Perch program, sponsored by the Office of Naval Research, started out with an underwater rover that was "tethered" through a CAT 5 Ethernet cable and the students, usually middle school age kids, learned to build and solder together the controller, small box like unit that had toggle switches to control the three propeller motors on the submersible.   Going to RC (Radio control) was not considered a viable option because of the difficulty of transmitting radio waves under water, so the next step in "hacking your Sea Perch" (what Daryl Davidson, the hip robotics education specialist and executive director  of the AUVSI (Association for Unmanned Vehicle Systems International) appropriately calls "pimping your Perch") is to "take the man out of the loop" and, through the application of sensors and a micro-controller, give some autonomy to the submersible robot craft.

MIT has been working on exactly that with their Sea Perch Sensor Suite, a kit based on an Arduino board.  It is described as, "a microcontroller-based platform that can be fabricated with minimal tools in a few hours, for under $200. When first fabricated, the sensor monitors:
- Water Temperature
- Depth
- Light
- Conductivity
And can be expanded with basic electronic and computing skills to monitor an assortment of other variables."

If you are working with the Sparkfun Inventor's Kit, Circuit-09 gives you an introduction to the world of autonomy with the introduction of a photo-resistor.  The manual says, "Whilst getting input from a potentiometer can be useful for human controlled experiments, what do we use when we want an environmentally controlled experiment? We use exactly the same principles but instead of a potentiometer (twist based resistance) we us a photo resistor (light based resistance)."

This is the first step in creating a robot that can sense its environment and respond to it.  From the perspective of a marine robotics program, the use of a photoresistor is appropriate since light sensitive organs evolved in the ocean very early on, giving organisms the capability for "phototaxis" or "movement toward or away from light".  This simple behavior can be rather easily done with the arduino, and might be one of the first one should attempt when "pimping the perch" -- i.e. use a photoresistor to make the Sea Perch move up or down,  toward or away from the surface,  based on the amount of light shining down on it (something many squid and plankton do in the ocean!).

The Sparkfun manual tells us that Arduinos cannot directly sense resistance.  They sense voltage, so what is needed is a voltage divider (http://ardx.org/VODI). We don't need to calculate the exact voltage at the sensing pin at this point so this experiment is about sensing relative light values and see what works.  We won't be driving a Sea Perch with this, but using an LED instead of a motor, we will see how the variable amount of light falling on the photoresistor affects the brightness of the LED.  Low voltages (high resistance to the current)  will be produced when the light is shining strongly, and high voltages (less resistance to the current) when it is dark; for a Sea Perch this could be useful so that the robot dives in the day and returns to the surface at night.  For this example daylight will shut off the LED and darkness turn it on, and this is exactly what people use for security lights.

The wiring isn't complex -- just one 330 Ohm resistor and one 10 K resistor, the LED and the Photoresistor, and the code is here:
http://ardx.org/CIRC09:

 /*
* A simple programme that will change the intensity of
* an LED based  * on the amount of light incident on
* the photo resistor.
*
*/

//PhotoResistor Pin
int lightPin = 0; //the analog pin the photoresistor is
                  //connected to
                  //the photoresistor is not calibrated to any units so
                  //this is simply a raw sensor value (relative light)
//LED Pin
int ledPin = 9;   //the pin the LED is connected to
                  //we are controlling brightness so
                  //we use one of the PWM (pulse width
                  // modulation pins)
void setup()
{
  pinMode(ledPin, OUTPUT); //sets the led pin to output
}
/*
* loop() – this function will start after setup
* finishes and then repeat
*/
void loop()
{
int lightLevel = analogRead(lightPin); //Read the
                                        // lightlevel
lightLevel = map(lightLevel, 0, 900, 0, 255);
         //adjust the value 0 to 900 to
         //span 0 to 255

lightLevel = constrain(lightLevel, 0, 255);//make sure the
                                           //value is betwween
                                           //0 and 255
analogWrite(ledPin, lightLevel);  //write the value
}


The code  uses digital pin 9 so that we can use PWM (pulse width modulation) to simulate analog light levels.

When you upload the circuit and put your hand around the photoresistor the LED goes on. If you want the opposite effect, the manual tells us to change the code from analogWrite(ledPin, lightLevel); to analogWrite(ledPin, 255 - lightLevel);
When I try it the light now stays on, even when I put my hand around it or dim the room.  I changed it then to  analogWrite(ledPin, 100 - lightLevel); and I get a dimmer LED but it still won't go out when I cup my hand around it to darken the photoresistor.  Changing the span to span 0 to 100 and constraining the light level to 0,100 and then writing 100 - lightLevel doesn't do much except make the constant LED dimmer. But it works the other way around, with your hand causing the light to go on by blocking light from the Photoresistor.

The next suggestion the manual has is creating a "night light" that turns on based on a threshold value using this code:

void loop() {
int threshold = 300;
if(analogRead(lightPin) > threshold) {
digitalWrite(ledPin, HIGH);
}else {
digitalWrite(ledPin, LOW);
}
}

This unfortunately doesn't work for me; I had to set the int threshold to around 10 to get the light to turn on when I cupped my hand around it.  Nonetheless, it does work with a low enough threshold. Your task is to find out what that threshold is for your environment.

And now we can begin to think about running a Sea Perch motor or a servo based on this principle.
I wire up the servo the way I did in Circuit-08, connecting the white servo wire to the positive lead of the LED which is connected to digital pin 9 on the Arduino, and the red and black servo wires to 5V and ground respectively. Now when I put my thumb over the photoresistor the servo spins and the light goes on, but of course then the servo gets stuck in one position.  I reverse the HIGH and LOW commands and the servo spins in the other direction.  But I can't quite control it yet.

The manual says to load up File>Examples>Servo>Knob from the Arduino sketch library like we did in the last circuit.  When I upload that it makes the light go on and the servo spin to the end of its range and then it just sits and vibrates.  The manual says,
"You'll notice that the servo will only operate over a limited portion of its range. This is because with the voltage dividing circuit we use the voltage on analog pin 0 will not range from 0 to 5 volts but instead between two lesser values (these values will change based on your setup). To fix this play with the val = map(val,0,1023,0,179); line. Hints on what to do are found at: http://arduino.cc/en/Reference/Map."
The manual says we are engaging in "a little bit of Arduino code hacking".  I try messing with the values but can't get much to happen.

It doesn't seem intuitive to me, so I decide to give up and move on; one of the nice things about this field is that you can always circle back later when things seem clearer.  If you get stymied, don't stop, just keep working through different examples!









Sparkfun Inventor's Kit Circuit-08: Potentiometer








Today we look at the use of Potentiometers, a.k.a "variable resistors".  Whats fun about these is that they are provide a window into more natural robotics, in other words, a way to start thinking of sensors that mimic the way we sense the world -- not in binary black and white on off terms, but on a continuum. To mimic analog behavior (where "shades of grey" or "values between 0 and 1" can be interpreted) the Arduino has not just the 14 digital pins (on the left side of the board when the power connector  is facing you) but 6 analog pins (on the right side, top).  They are inputs and they take voltages from 0 to 5V and convert them into digital numbers from 0 to 1024 (the manual says this is 10 bits of resolution). 

When the potentiometer is connected to one of these inputs via its middle lead, and the outer leads are connected to ground and 5 Volts on the board, you can dial it from 0 on one side to 5 Volts on the other, with 2.5 V being the voltage when the arrow is in the center, and use the returned values as variables in the program.

The code from http://ardx.org/CIRC08 is here:

/*
  Analog Input
Demonstrates analog input by reading an analog sensor on analog pin 0 and
turning on and off a light emitting diode(LED)  connected to digital pin 13.
The amount of time the LED will be on and off depends on
the value obtained by analogRead().

The circuit:
* Potentiometer attached to analog input 0
* center pin of the potentiometer to the analog pin
* one side pin (either one) to ground
* the other side pin to +5V
* LED anode (long leg) attached to digital output 13
* LED cathode (short leg) attached to ground

* Note: because most Arduinos have a built-in LED attached
to pin 13 on the board, the LED is optional.

Created by David Cuartielles
Modified 16 Jun 2009
By Tom Igoe

http://arduino.cc/en/Tutorial/AnalogInput

*/

int sensorPin = 0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() {
  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT); 
}

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);   
  // turn the ledPin on
  digitalWrite(ledPin, HIGH); 
  // stop the program for milliseconds:
  delay(sensorValue);         
  // turn the ledPin off:       
  digitalWrite(ledPin, LOW); 
  // stop the program for for milliseconds:
  delay(sensorValue);                 
}


What this program does is simply set the delay between turning the LED on and off to whatever the potentiometer is putting out. When you turn it hard left the delay is zero, when you the delay appears to be 1024 or about 1 second (since 1000 milliseconds  is 1 second).


The manual provides a way to make the LED start flashing only when the voltage reaches a certain threshold.  They provide this code to start the flashing when it reaches 512 ms (i.e. half way):

void loop() {
int threshold = 512;
if(analogRead(sensorPin) > threshold) {
digitalWrite(ledPin, HIGH); }
else{digitalWrite(ledPin, LOW);}
}

(I highlight the old void loop() code and comment it out, then paste the above code underneath it).
When you upload this the LED will remain off when the potentiometer arrow angle is anywhere between 0 and the middle and then it turns on when it is in the middle or below.  As they say, "you can adjust the sensitivity by changing the threshold value."

You can also make it fade, controlling the brightness of the LED directly from the potentiometer (you are familiar with this effect from volume knobs on guitars and stereos and amplifiers -- these are examples of potentiometers used to fade sound). To make the LED fade we change the Digital pin connecting the LED to the board from 13 to 9, i.e. int ledPin = 9;      // select the pin for the LED

The manual says to use the following for your void loop():

void loop() {
int value = analogRead(potPin) / 4;
analogWrite(ledPin, value);
}

When you try to compile this, of course, you'll get the error "potPin was not declared in this scope" This is obviously a typo (or a way to test how well we are now understanding programming at this point!).

Change it to sensorPin and you are golden! (int value = analogRead(sensorPin) / 4;)

void loop() {
int value = analogRead(sensorPin) / 4;
analogWrite(ledPin, value);
}
Why divide by 4? The manual says, "the analogRead() function returns a value from 0 to 1024 (10 bits) while the analogWrite() takes a value from 0 to 255 (8 bits)." So a lot of what one does to get one thing talking to another is to do conversion math so the scales match up.  As Einstein pointed out, everything is relative!

Now that we can control the brightness of an LED, the implication is that we can control a lot of variable elements. The book suggests combining lessons and control a servo with a potentiometer.

What I did, for fun, was to add the servo to CIRC-08 by putting my three-pin header down on the breadboard at holes 22, 23 and 24. Then I connected my servo and used a white wire to connect the Servo's white signal wire  to the hole  next to the positive pin of the LED on the board. Then I connected a red wire next to the Servo's red wire to the positive +5 V rail of my breadboard, and a black wire next to the Servo's black wire and then to the negative (gnd) rail of the breadboard. Then, without uploading any additional code, keeping the void loop() above,  I was able to use the potentiometer to control both the brightness of the LED and the position of the Servo.

The manual says to wire up the servo as we did in CIRC-04, and use the code from the example program in Arduino called "Knob" (File>Examples>Servo>Knob) and change one line of code:
int potpin = 0; ---> int potpin = 2; (be careful, potpin has all small p's, while  the usual convention is that the second work gets a cap! Misspelling can cause an error!)
Now your Servo should turn as you turn the potentiometer!

So I went ahead and uploaded the Example Knob file:

// Controlling a servo position using a potentiometer (variable resistor)
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop()
{
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}


and then changed int potpin  = 0;  to int potpin =2; .

But nothing happened.  So I looked at the code and looked at my board and realized there was no need to change int potpin = 0; to intpotpin = 2; because the center lead of my potentiometer was already connected to analog input 0, not 2.  So there are some discrepancies in the manual. The schematic for CIRC-08 shows the potentiometer connecting to Arduino analog pin 0 and the code says int sensorPin = 0;  but then in the "Not Working" section they say "make sure you haven't accidentally connected the potentiometer's wiper to digital pin 2 rather than analog pin 2 (the row of pins beneath the power pins).  So from then they seem to be assuming you are hooked up to pin 2. Just be consistent and everything should work out fine!

The thing is, you don't really need this example sketch, which calls a library called "Servo.h" since you can use the potentiometer sketch above as well. But it is great to play with all this.









Monday, November 14, 2011

Sparkfun Inventor's Kit Circuit-07: A Push-Button World

With what they describe as an "underwhelming" example the Inventor's Kit manual brings us into what may be the most important part of creating an autonomous vehicle: sensing.  In the first 6 tutorials everything was about output -- getting the robot to "do something".  Trouble is that this tethers the human to the mechanical being, and why people with control fantasies may be satisfied with robots that do exactly and only what they tell them to when they tell them to, the rest of us are fascinated by the idea of giving our co-creations some semblance of "free will".

To be autonomous, a robot needs to be "aware" of its environment.  It needs to be able to hear and to see, to touch and taste and even smell. Watching and listening will come later, but this tutorial prepares the robot to "feel" via one of the simplest of "touch sensors" - the push button.

The set up is fairly simple (2 pushbuttons, a red LED, a 330 Ohm resistor and a 10 KOhm resistor), and for the first sketch only one of the pushbuttons is used.  As the book states, "Underwhelmed? No worries, these circuits are all super stripped down to make playing with the component easy, but once you throw them together the sky is the limit."

Here is the first code:


/*
  Button

 Turns on and off a light emitting diode(LED) connected to digital 
 pin 13, when pressing a pushbutton attached to pin 7.


 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached to pin 2 from +5V
 * 10K resistor attached to pin 2 from ground

 * Note: on most Arduinos there is already an LED on the board
 attached to pin 13.


 created 2005
 by DojoDave <http://www.0j0.org>
 modified 17 Jun 2009
 by Tom Igoe

  http://www.arduino.cc/en/Tutorial/Button
 */

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);     
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {    
    // turn LED on:   
    digitalWrite(ledPin, HIGH); 
  }
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
}


You download it. You press the push button. The LED goes off. You release the button. It goes back on.  Bravo. So what?
But then you start modding.

Here is the modded code to use both pushbuttons, one to turn the LED on, one to turn it off (I commented out the original code, but it is still there:)

/*
  Button

 Turns on and off a light emitting diode(LED) connected to digital 
 pin 13, when pressing a pushbutton attached to pin 7.


 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached to pin 2 from +5V
 * 10K resistor attached to pin 2 from ground

 * Note: on most Arduinos there is already an LED on the board
 attached to pin 13.


 created 2005
 by DojoDave <http://www.0j0.org>
 modified 17 Jun 2009
 by Tom Igoe

  http://www.arduino.cc/en/Tutorial/Button
 */

// constants won't change. They're used here to
// set pin numbers:
//const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
int inputPin1 = 3;  //button 1
int inputPin2 = 2;   //button 2

// variables will change:
//int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);     
  // initialize the pushbutton pin as an input:
 // pinMode(buttonPin, INPUT);    
 pinMode(inputPin1,INPUT); //make button 1 an input
 pinMode(inputPin2,INPUT); //make button 2 an input
}

void loop(){
  // read the state of the pushbutton value:
 // buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
 // if (buttonState == HIGH) {    
    // turn LED on:   
  //  digitalWrite(ledPin, HIGH); 
 // }
  //else {
    // turn LED off:
   // digitalWrite(ledPin, LOW);
 // }
//}

if(digitalRead(inputPin1)==LOW) {
  digitalWrite(ledPin, LOW); //turn LED OFF
} else if (digitalRead(inputPin2)==LOW) {
  digitalWrite(ledPin, HIGH); //turn LED ON
}
 }


The next hack is "fading up and down". This means using the push buttons to control an analog signal.  We start by changing the wire connecting the LED to pin 9 from pin 13 and change it in the code to, so it reads int ledPin = 9;
Then the loop() code is changed to:
int value = 0;
void loop() {
if (digitalRead(inputPin1) == LOW) { value--; }
else if (digitalRead(inputPin2) == LOW) { value++;}
value = constrain(value, 0, 255);
analogWrite(ledPin, value);
delay(10);
}


For doing the fade up and fade down, this is the code (I had to type it in, but it's done, so why should you?!):


// constants won't change. They're used here to
// set pin numbers:
//const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  9;      // the number of the LED pin
int inputPin1 = 3;  //button 1
int inputPin2 = 2;   //button 2

// variables will change:
//int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);     
  // initialize the pushbutton pin as an input:
 // pinMode(buttonPin, INPUT);    
 pinMode(inputPin1,INPUT); //make button 1 an input
 pinMode(inputPin2,INPUT); //make button 2 an input
}
int value = 0;
void loop() {
if (digitalRead(inputPin1) == LOW) { value--; }
else if (digitalRead(inputPin2) == LOW) { value++;}
value = constrain(value, 0, 255);
analogWrite(ledPin, value);
delay(10);
}


And they say "if you would like the LED to fade faster or slower, there is only one line of code that needs changing:
delay(10); can be made into delay(5); to go twice as fast, and delay(20); to go twice as slow, and everything inbetween.

Enjoy;  now that we are into sensing I can sense things are going to get a lot more fun!

Sparkfun Inventor's Kit Circuit-06: Music with a Piezo Element

Much like the Servo Tutorial (number 4) the components here are amazingly simple -- just a single Piezo element and 4 wires.  Everything else is in the code.

When you load this one up, the Piezo element cranks out a melody that you could sing the following lyrics to "Twinkle Twinkle Little Tots, how we love Arduino Bots".  

Then it loops and gets annoying.
Okay, where is the off switch?
There, I unplugged it. Phew.
I could have also just unplugged the Piezo element instead of the usb cable and kept the thing powered up. Or disconnected the Ground  wire (disconnecting the 5V wire does nothing).  Lots of ways to turn off that annoying melody!

First the theory. Controlling sound is different than lights, motion and electrons because sound is an analog phenomenon. We are using a digital microcontroller to create it. How?  The book says that we mimic analog behavior by pulsing current through the piezo at an "incredible speed".  Since a piezo element clicks every time a pulse goes through it, if we pulse at 440 Hz (cycles or times per second) then we get the note A440 (the tuning fork pitch, like the middle A on a really icky keyboard).
If you double the number of clicks over the same period of time (880 clicks per second) you get a note an Octave above (also A, but higher in pitch). Halve it and you get a lower A (A220).  In between are all the other notes. The code explains them:

/* Melody
 * (cleft) 2005 D. Cuartielles for K3
 *
 * This example uses a piezo speaker to play melodies.  It sends
 * a square wave of the appropriate frequency to the piezo, generating
 * the corresponding tone.
 *
 * The calculation of the tones is made following the mathematical
 * operation:
 *
 *       timeHigh = period / 2 = 1 / (2 * toneFrequency)
 *
 * where the different tones are described as in the table:
 *
 * note     frequency     period     timeHigh
 * c             261 Hz             3830     1915    
 * d             294 Hz             3400     1700    
 * e             329 Hz             3038     1519    
 * f             349 Hz             2864     1432    
 * g             392 Hz             2550     1275    
 * a             440 Hz             2272     1136    
 * b             493 Hz             2028    1014   
 * C            523 Hz            1912     956
 *
 * http://www.arduino.cc/en/Tutorial/Melody
 */
 
int speakerPin = 9;

int length = 15; // the number of notes
char notes[] = "ccggaagffeeddc "; // a space represents a rest
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
 
  // play the tone corresponding to the note name
  for (int i = 0; i < 8; i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}

void setup() {
  pinMode(speakerPin, OUTPUT);
}

void loop() {
  for (int i = 0; i < length; i++) {
    if (notes[i] == ' ') {
      delay(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
    }
   
    // pause between notes
    delay(tempo / 2);
  }
}


 So when you string together notes of the right frequency you play a melody.

To change the speed of the melody the tutorial informs us that we need only change one line, making int tempo = 300 into int tempo = some new number.  I tried int tempo = 3000 just for kicks. It really slowed things down.  Then I sped it up by making int tempo = 30.  Hardly recognizable.

You can tweak the tuning of the notes by changing the values in the tones[] array which I have marked in red above.

To make your own melody they say that it is easy.  "Each song is defined in one int and two arrays. The int length deines the number of notes, the first array called notes[] defines what the notes are and the second, beats[], defines how long each note is played.

To play the first line of that horrible birthday favorite, "Hippo Birdy" (and risk copyright infringement again,  just like every year) you would use
int length = 13;
char notes[] = {"ccdcfeccdcgf "};
int beats[] = {1,1,1,1,2,1, 1, 1, 1, 2,4};

Note that a space after a note equals a rest and that needs timing too. So you see 12 notes but an int length of 13 because the rest, which lasts for 4 beats, must be included.

And here is my attempt to play the first 10 notes of the awesome Blue Oyster Cult song "Godzilla"

int length = 10; // the number of notes
char notes[] = "cfgdeabfc "; // a space represents a rest
int beats[] = {3,1,1,1,3,1,1,1,3,3};
int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  int tones[] = { 1915, 1700, 1600, 1432, 1275, 1150, 1100, 956 };
 
Note that I had to change the value of e to something like an Eb (1600) and the values of A and B to 1150 and 1100 respectively. Tweaking it will make it better.

Try it out and have fun!.



Sparkfun Inventor's Kit Circuit 05: More LEDs

 

Since I'm impatient to get my marine robot working and know this means mastering code for motors and servos, I was at first less than enthusiastic about going back to working with LEDs. But then I remembered that the clever structuring of the Sparkfun Inventor's Kit tutorials demonstrates that what you can do with LEDs you can then do with motors and servos, i.e., the code principles are remarkably similar, as is the code itself. And that insight alone is worth a lot.

So today we are looking at the use of an Integrated Circuit.  On first read the tutorial seems alien and intimidating "To use it you "clock in" the data and then lock it in (latch it). To do this you set the data pin to either HIGH or LOW, pulse the clock, then set the data pin again and pulse the clock repeating until you have shifted out 8 bits of data. then you pulse the latch and the 8 bits are transferred to the shift register pins."
Huh?  Say what?
Thank God they then say "It sounds complicated but is really simple once you get the hang of it." Newbies like me (and the target student group I represent) need reassurances like this to keep our confidence up as we plunge into these new and for us uncharted waters.

It is a cliche, of course, but it turns out that everything sounds complicated at first to those who didn't grow up swimming in those waters, and everything appears simple once you really get the hang of it.  In fact I would go so far as to say that one of the reasons STEM subjects (science, technology, engineering, and mathematics) seem so hard is because once people who have struggled through the learning curve do get the hang of it, the subjects seems so simple that we rarely back up and try to simplify the path it took us to get there so that others can make it through without stumbling or bumping into unnecessary roadblocks.

There is also a tendency I've observed in human nature to resist making our hard-won insights freely available to others.  As one teacher I knew put it, "I struggled  hard to make it, it was tough for me to make C's let alone A's in science.  If you think I'm going to suddenly make it easy on these kids, you're nuts. They gotta suffer and earn it like I did."

I liken this to the a treasure hunter who spends years without a map searching for a mysterious hidden treasure island.  When he finally gets there he discovers that the island's treasures are actually so abundant that they could be shared with everybody and that the island is also actually rather easy to get to, once you know where it is.  But he keeps the location a secret, refuses to share the map he made, and suggests that only those who spend the same number of years searching should get the rewards available in this "promised land".

Our intent in this program is to be mindful of the idea that "once you get the hang of robotics it is really rather simple" and make sure that we work on  providing a good, clear roadmap so that others don't have to struggle to get where we got.  This is the role of the explorer and the pathfinder in our opinion.

So this odyssey is about making things simple for those who come after. It is about translating the arcane into common language.

During the years I was with our Harvard Acapella group "The Harvard Squares"  and our West Coast musical group "The Quintessentials", my Wall Street financial investment specialist friend and fellow songster Paul Sagawa  used to jokingly  say to the crowds, "Ladies and Gentlemen, we are the group that sings so that YOU DON'T HAVE TO!".

We will apply the same logic to our PORPOISE program: We are the group that struggles through the arcane and obscure and difficult parts of the technical  manuals so that YOU DON'T have to!"   We will dedicate ourselves to figuring out where things seem complicated and do our best to making it user friendly and fun.

This personal blog is a mere log of the journey we are taking to get there!

So what about the IC chip journey?

Well, before we can decipher what it means to "clock in" data and "lock it in (latch it") we have to get our "feet wet" and our "hands dirty" and actually build the circuit and play around with it -- that is the best strategy in any event for anything!

The key here seems to be an understanding that the function of adding the 74HC595 Shift Register IC to the Arduino is that it "will give you an additional 8 outputs (to control LEDs and motors and Servos) using only three Arduino pins".  So it gives expanded capabilities.  And "They can also be linked together to give you a nearly unlimited number of outputs using the same four pins".

The 74HC595 Shift Register IC is also known as a "serial to parallel converter" which gives a good indication of its function, getting through the serial bottleneck and enabling us to control a much larger array of actuators and servos and motors without having to use additional microcontrollers.

That is great news, particularly considering that this chip costs a couple dozen cents, while the chip on the Arduino costs a few dollars.

The manual says, encouragingly, "once you're comfortable playing around with it and its datasheet (available online http://ardx.org/datasheet/IC-74HC595.pdf  )the world of chips will be your oyster."  An additional resource is the "in depth look at how a shift register works found at http://ardx.org/SHIF; this just takes you to a wikipedia entry which I didn't find that useful at this stage of knowledge. 

The datasheet may not be immediately helpful to the novice but one thing that can be appreciated is how the IC resembles the Arduino board itself in that some of the leads are datapins, and there is one labeled grnd for Ground (pin 8) and one labeled Vcc ( pin 16) for supply voltage.  This can also be seen on the supplied pattern for Circuit 05. Pin 14 is for Data, pin 13 for output, pin 12 for this mysterious thing called "Latch", pin 11 for Clk, which must be "Clock" and pin 10 for Reset. Pins 1 through 7 and Pin 9 and pin 15 are for Q parameters, whatever they are (Q1 is usually a designator for a transistor, so maybe that is what they refer to here?). 

 


In terms of building, this one should be simple but what is tricky is that the pattern layout doesn't fit all that well on the breadboard, making you have to guess a bit to make the squares on the layout sheet line up with the breadboard beneath.  It helps in any case to learn to read and understand the Schematics provided, even though they sometimes don't see to correspond well to the real world wiring. The Schematic tells you how things really need to connect and helps you understand why the breadboard is wired the way it is. Ultimately we will have to work off of schematics completely with no helpful pattern layouts as our crutches or training wheels and this is the time to start understanding how breadboard wiring and schematics correspond.

Note that Pin 4 on the Arduino goes to Latch on the IC, Pin 3 to Clock and Pin 2 to Data, and that the 0 - 7 leads go to the LED's and resistors, going through the positive side of the LED whose negative side goes through the resistor to ground. The trickiest part is noting that IC lead 15, which is Q0, just underneath lead 16 which is the Vcc lead going to the positive rail, goes to the top LED on the left and then you start using the leads from 1 through 7 which correspond to the rest of the LEDs, so you have some crossed wires. IT gets a bit messy in real life, despite how nice and neat it looks on the Schematic.

Reset goes to the positive rail and ground, of course, goes to ground.

Hooking this messy circuit up makes one appreciative of the clean-ness of a well made PCB board.



The code is downloaded from http://ardx.org/CODE05 but is reproduced here to save you a step:



/*     ---------------------------------------------------------
 *     |  Arduino Experimentation Kit Example Code             |
 *     |  CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register)   |
 *     ---------------------------------------------------------
 *
 * We have already controlled 8 LEDs however this does it in a slightly
 * different manner. Rather than using 8 pins we will use just three
 * and an additional chip.
 *
 *
 */


//Pin Definitions
//Pin Definitions
//The 74HC595 uses a serial communication
//link which has three pins
int data = 2;
int clock = 3;
int latch = 4;

//Used for single LED manipulation
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;
                       

/*
 * setup() - this function runs once when you turn your Arduino on
 * We set the three control pins to outputs
 */
void setup()
{
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT); 
  pinMode(latch, OUTPUT); 
}

/*
 * loop() - this function will start after setup finishes and then repeat
 * we set which LEDs we want on then call a routine which sends the states to the 74HC595
 */
void loop()                     // run over and over again
{
  int delayTime = 100; //the number of milliseconds to delay between LED updates
  for(int i = 0; i < 256; i++){
   updateLEDs(i);
   delay(delayTime);
  }
}



/*
 * updateLEDs() - sends the LED states set in ledStates to the 74HC595
 * sequence
 */
void updateLEDs(int value){
  digitalWrite(latch, LOW);     //Pulls the chips latch low
  shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
  digitalWrite(latch, HIGH);   //Pulls the latch high displaying the data
}

/*
 * updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
 * sequence. Same as updateLEDs except the shifting out is done in software
 * so you can see what is happening.
 */
void updateLEDsLong(int value){
  digitalWrite(latch, LOW);    //Pulls the chips latch low
  for(int i = 0; i < 8; i++){  //Will repeat 8 times (once for each bit)
  int bit = value & B10000000; //We use a "bitmask" to select only the eighth
                               //bit in our number (the one we are addressing this time through
  value = value << 1;          //we move our number up one bit value so next time bit 7 will be
                               //bit 8 and we will do our math on it
  if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data pin high
  else{digitalWrite(data, LOW);}            //if bit 8 is unset then set the data pin low
  digitalWrite(clock, HIGH);                //the next three lines pulse the clock pin
  delay(1);
  digitalWrite(clock, LOW);
  }
  digitalWrite(latch, HIGH);  //pulls the latch high shifting our data into being displayed
}


//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};
/*
 * changeLED(int led, int state) - changes an individual LED
 * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
 */
 void changeLED(int led, int state){
   ledState = ledState & masks[led];  //clears ledState of the bit we are addressing
   if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to ledState
   updateLEDs(ledState);              //send the new LED state to the shift register
 }


When I upload the code... Al Hamdu'Lillah! It works, lighting up all the red LEDs in various sequences!
What we are told is that it is counting up in binary.  



 If you had trouble figuring this one out, because of the crossed wires and stuff, they have kindly posted a video at http://ardx.org/VIDE05



 Now to look at the code and figure out what it does!

The manual suggests we experiment with controlling individual LEDs saying that the eight LED states "are stored in on byte (an 8 bit value) and giving details on how this works (i.e. the history of bit-math)  at http://ardx.org/BINA and pointing us to http://ardx.org/BITW for more details on bitwise maths and the set of operators that help an Arduino manipulate bits (the key lesson here is the sites statement  "On the simple low cost digital processors used in many embedded systems, bitwise operations are typically several times as fast as multiplication, sometimes also significantly faster than addition, at least in certain technical circumstances. On the other hand, modern processors in high performance segments usually perform addition and multiplication as fast as bitwise operations[1] but the latter typically occupy less machine resources and may therefore be more optimal for overall performance and/or power consumption. Division is normally very slow compared to bitwise operations."    Since we are dealing with low cost boards without much memory, bitwise math helps us to do more with less.

The tutorial instructs us to change this:

void loop()                     // run over and over again
{
  int delayTime = 100; //the number of milliseconds to delay between LED updates
  for(int i = 0; i < 256; i++){
   updateLEDs(i);
   delay(delayTime);
  }
}

To this:

void loop()                     // run over and over again
{
  int delayTime = 100; //the number of milliseconds to delay between LED updates
  for(int i = 0; i < 8; i++){
   changeLED(i, ON);
   delay(delayTime);
  }
  for(int i = 0; i < 8; i++){
   changeLED(i, OFF);
   delay(delayTime);
}
}
(To do this, my technique, rather than writing over the original code, is to highlight the original and then comment it out using Edit>Comment and then paste the revision underneath. Then I can get back to the original by highlighting and going to Edit>Uncomment).

When this modification is uploaded the LEDs light up and go off in sequence.

The final thing the manual suggests we try is to go back to the code from CIRC02 where we changed the LEDs using digitalWrite(led,state) (meaning something like digitalWrite(1edPins[7], HIGH); ).  They suggest we can use the animations from CIRC02 by copying the code into this sketch and changing all the digitalWrite()'s to changeLED()'s.    This will become the essence of the way we use Arduino's as beginners. No students are expected to be able to write their own code before they can get into programming their robots.  Instead we copy code from other powerful applications and mod it to do what we want.  The trick is in knowing what and how to modify, not being a great code writer. Not at this stage of the game! And you can go far with this copy-paste-modify routine if you learn how to spot what to change.

In this case, the pieces I will copy in to this IC chip sketch are

/*
 * loop() - this function will start after setup finishes and then repeat
 * we call a function called oneAfterAnother(). if you would like a different behaviour
 * uncomment (delete the two slashes) one of the other lines
 */
void loop()                     // run over and over again
{
  oneAfterAnotherNoLoop();   //this will turn on each LED one by one then turn each off
  //oneAfterAnotherLoop();   //does the same as oneAfterAnotherNoLoop but with 
                             //much less typing
  //oneOnAtATime();          //this will turn one LED on then turn the next one
                             //on turning the 
                             //former off (one LED will look like it is scrolling 
                             //along the line
  //inAndOut();              //lights the two middle LEDs then moves them out then back 
                             //in again
}
 
And 
 
/*
 * oneAfterAnotherLoop() - Will light one LED then delay for delayTime then light
 * the next LED until all LEDs are on it will then turn them off one after another
 *
 * this does it using a loop which makes for a lot less typing. 
 * than oneOnAtATimeNoLoop() does exactly the same thing with less typing
 */
void oneAfterAnotherLoop(){
  int delayTime = 100; //the time (in milliseconds) to pause between LEDs
                       //make smaller for quicker switching and larger for slower
 
//Turn Each LED on one after another
  for(int i = 0; i <= 7; i++){
    digitalWrite(ledPins[i], HIGH);  //Turns on LED #i each time this runs i
    delay(delayTime);                //gets one added to it so this will repeat 
  }                                  //8 times the first time i will = 0 the final
                                     //time i will equal 7;
 
//Turn Each LED off one after another
  for(int i = 7; i >= 0; i--){  //same as above but rather than starting at 0 and counting up
                                //we start at seven and count down
    digitalWrite(ledPins[i], LOW);  //Turns off LED #i each time this runs i
    delay(delayTime);                //gets one subtracted from it so this will repeat 
  }                                  //8 times the first time i will = 7 the final
                                     //time it will equal 0
                                     
                                     
}
 
/*
 * oneOnAtATime() - Will light one LED then the next turning off all the others
 */
void oneOnAtATime(){
  int delayTime = 100; //the time (in milliseconds) to pause between LEDs
                       //make smaller for quicker switching and larger for slower
  
  for(int i = 0; i <= 7; i++){
    int offLED = i - 1;  //Calculate which LED was turned on last time through
    if(i == 0) {         //for i = 1 to 7 this is i minus 1 (i.e. if i = 2 we will
      offLED = 7;        //turn on LED 2 and off LED 1)
    }                    //however if i = 0 we don't want to turn of led -1 (doesn't exist)
                         //instead we turn off LED 7, (looping around)
    digitalWrite(ledPins[i], HIGH);     //turn on LED #i
    digitalWrite(ledPins[offLED], LOW); //turn off the LED we turned on last time
    delay(delayTime);
  }
}


/*
 * inAndOut() - This will turn on the two middle LEDs then the next two out
 * making an in and out look
 */
void inAndOut(){
  int delayTime = 100; //the time (in milliseconds) to pause between LEDs
                       //make smaller for quicker switching and larger for slower
  
  //runs the LEDs out from the middle
  for(int i = 0; i <= 3; i++){
    int offLED = i - 1;  //Calculate which LED was turned on last time through
    if(i == 0) {         //for i = 1 to 7 this is i minus 1 (i.e. if i = 2 we will
      offLED = 3;        //turn on LED 2 and off LED 1)
    }                    //however if i = 0 we don't want to turn of led -1 (doesn't exist)
                         //instead we turn off LED 7, (looping around)
    int onLED1 = 3 - i;       //this is the first LED to go on ie. LED #3 when i = 0 and LED 
                             //#0 when i = 3 
    int onLED2 = 4 + i;       //this is the first LED to go on ie. LED #4 when i = 0 and LED 
                             //#7 when i = 3 
    int offLED1 = 3 - offLED; //turns off the LED we turned on last time
    int offLED2 = 4 + offLED; //turns off the LED we turned on last time
    
    digitalWrite(ledPins[onLED1], HIGH);
    digitalWrite(ledPins[onLED2], HIGH);    
    digitalWrite(ledPins[offLED1], LOW);    
    digitalWrite(ledPins[offLED2], LOW);        
    delay(delayTime);
  }
 
  //runs the LEDs into the middle
  for(int i = 3; i >= 0; i--){
    int offLED = i + 1;  //Calculate which LED was turned on last time through
    if(i == 3) {         //for i = 1 to 7 this is i minus 1 (i.e. if i = 2 we will
      offLED = 0;        //turn on LED 2 and off LED 1)
    }                    //however if i = 0 we don't want to turn of led -1 (doesn't exist)
                         //instead we turn off LED 7, (looping around)
    int onLED1 = 3 - i;       //this is the first LED to go on ie. LED #3 when i = 0 and LED 
                             //#0 when i = 3 
    int onLED2 = 4 + i;       //this is the first LED to go on ie. LED #4 when i = 0 and LED 
                             //#7 when i = 3 
    int offLED1 = 3 - offLED; //turns off the LED we turned on last time
    int offLED2 = 4 + offLED; //turns off the LED we turned on last time
    
    digitalWrite(ledPins[onLED1], HIGH);
    digitalWrite(ledPins[onLED2], HIGH);    
    digitalWrite(ledPins[offLED1], LOW);    
    digitalWrite(ledPins[offLED2], LOW);        
    delay(delayTime);
  }
}


But where to place them? 


My instinct is to copy all of the above and place it where the void loop() code was.  When I do that however, I get an error message. 
The book predicted this would happen. It says that this is a powerful technique but that "you'll also need to change a few other things but follow the compile errors and it works itself out.". 
So I look at my compile errors one by one. 

The first error is "CODE05:71 error oneAfterAnotherNoLoop' was not declared in this scope".
The Arduino sketch highlights line 71 in yellow to draw my eye immediately to the line where the error occured (That is what CODE05:71 error meant; there is an error in line 71 of the sketch named CODE05.)

What does it mean, "not declared in this scope"?  According to one arduino tutorial on variables
"Now what, you might be wondering, did the word "scope" in that error message above mean? It refers to the part of your program in which the variable can be used. This is determined by where you declare it. For example, if you want to be able to use a variable anywhere in your program, you can declare at the top of your code. This is called a global variable"


As I hunt through the original code I realize that I didn't bother to copy the section for oneAfterAnotherNoLoop because in Sketch 2 of the tutorial we learned that that was an inefficient way of using the LEDs.  So I left it out.  All I have to do, then, to resolve this error, is to comment out the line
// oneAfterAnotherNoLoop(); 
Now I uncomment  the next line:
oneAfterAnotherLoop();   //does the same as oneAfterAnotherNoLoop but with
                             //much less typing

And I compile to see what happens.
It says now CODE05:96 error  "ledPins was not declared in this Scope"
But before I drive myself crazy trying to figure all this out I need to follow the advice of the tutorial and "change all the digitalWrite()'s to changeLED()'s and see what happens.


I use Arduino's Find and Replace function and change all of them with "Replace All"
When I try to compile I still get the "ledPins was not declared in this Scope" message, but at least I've followed the directions!

Now, taking my cue from the original sketch for CODE05, where the  loop() function contained code saying "changeLED(i, ON);" I reason that perhaps I should simply replace all of the "ledPins" declarations to simply "i". When I do that all of the "ledPins was not declared in this Scope" error disappear but I get a new error in the "inAndOut" section of the code wherever the replacement caused the code to look like this:

 changeLED(i[onLED1], HIGH);
    changeLED(i[onLED2], HIGH);   
    changeLED(i[offLED1], LOW);   
    changeLED(i[offLED2], LOW);

Instead of

 changeLED(ledPins[onLED1], HIGH);  

It says "invalid types 'int[int]' for array subscript at line  152.

My instinct now is simply to comment that whole section out and see what happens before trying to figure out how to fix this (remember, like most of you, I have no background in computer coding whatsoever!).

When I do that the error now appears in line 97 'changeLED' was not declared in this scope.

So it is back to the drawing board, looking for where changeLED was declared in the original sketch for this tutorial.

As I examine the code I realize now that when I commented out the inAndOut section I accidentally commented out the part of the code that defines "changeLED", so I have to go and uncomment that.


That code is the following:


/*
 * updateLEDs() - sends the LED states set in ledStates to the 74HC595
 * sequence
 */
void updateLEDs(int value){
  changeLED(latch, LOW);     //Pulls the chips latch low
  shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
  changeLED(latch, HIGH);   //Pulls the latch high displaying the data
}

/*
 * updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
 * sequence. Same as updateLEDs except the shifting out is done in software
 * so you can see what is happening.
 */
void updateLEDsLong(int value){
  changeLED(latch, LOW);    //Pulls the chips latch low
  for(int i = 0; i < 8; i++){  //Will repeat 8 times (once for each bit)
  int bit = value & B10000000; //We use a "bitmask" to select only the eighth
                               //bit in our number (the one we are addressing this time through
  value = value << 1;          //we move our number up one bit value so next time bit 7 will be
                               //bit 8 and we will do our math on it
  if(bit == 128){changeLED(data, HIGH);} //if bit 8 is set then set our data pin high
  else{changeLED(data, LOW);}            //if bit 8 is unset then set the data pin low
  changeLED(clock, HIGH);                //the next three lines pulse the clock pin
  delay(1);
  changeLED(clock, LOW);
  }
  changeLED(latch, HIGH);  //pulls the latch high shifting our data into being displayed
}


//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};
/*
 * changeLED(int led, int state) - changes an individual LED
 * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
 */
 void changeLED(int led, int state){
   ledState = ledState & masks[led];  //clears ledState of the bit we are addressing
   if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to ledState
   updateLEDs(ledState);              //send the new LED state to the shift register
 }



I run it now and it compiles fine, but the lights do nothing.  So now I have to figure out how to talk to the lights...


Finally I get it working. I realize that I should NEVER have done a "replace all" changing all the "digitalWrite"s to "changeLED"s because there are digitalWrites at the end of the original CODE05 sketch that are essential.  Also, I realize that the error when I replace ledPins with "i" comes from when the modified code says "i[offLED] because one can not concatenate these since i is not an array.  So all I have to do is elminate the i and the brackets and just use "offLED" or whatever because that is defined in terms of i.


Here then is the modified code that combines the animations from CODE02 into the sketch of CODE05:


/*     ---------------------------------------------------------
 *     |  Arduino Experimentation Kit Example Code             |
 *     |  CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register)   |
 *     ---------------------------------------------------------
 *
 * We have already controlled 8 LEDs however this does it in a slightly
 * different manner. Rather than using 8 pins we will use just three
 * and an additional chip.
 *
 *
 */


//Pin Definitions
//Pin Definitions
//The 74HC595 uses a serial communication
//link which has three pins
int data = 2;
int clock = 3;
int latch = 4;

//Used for single LED manipulation
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;
                       

/*
 * setup() - this function runs once when you turn your Arduino on
 * We set the three control pins to outputs
 */
void setup()
{
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT); 
  pinMode(latch, OUTPUT); 
}

/*
 * loop() - this function will start after setup finishes and then repeat
 * we set which LEDs we want on then call a routine which sends the states to the 74HC595
 */
//void loop()                     // run over and over again
//{
//  int delayTime = 100; //the number of milliseconds to delay between LED updates
//  for(int i = 0; i < 8; i++){
//   changeLED(i,ON);
//   delay(delayTime);
//  }
//  for(int i = 0; i < 8; i++){
//   changeLED(i,OFF);
//   delay(delayTime);
//}
//}

void loop()                     // run over and over again
{
  //oneAfterAnotherNoLoop();   //this will turn on each LED one by one then turn each off
oneAfterAnotherLoop();   //does the same as oneAfterAnotherNoLoop but with
                             //much less typing
  oneOnAtATime();          //this will turn one LED on then turn the next one
                             //on turning the
                             //former off (one LED will look like it is scrolling
                             //along the line
  inAndOut();              //lights the two middle LEDs then moves them out then back
                             //in again
}

/*
 * oneAfterAnotherLoop() - Will light one LED then delay for delayTime then light
 * the next LED until all LEDs are on it will then turn them off one after another
 *
 * this does it using a loop which makes for a lot less typing.
 * than oneOnAtATimeNoLoop() does exactly the same thing with less typing
 */
void oneAfterAnotherLoop(){
  int delayTime = 100; //the time (in milliseconds) to pause between LEDs
                       //make smaller for quicker switching and larger for slower

//Turn Each LED on one after another
  for(int i = 0; i <= 7; i++){
    changeLED(i, HIGH);  //Turns on LED #i each time this runs i
    delay(delayTime);                //gets one added to it so this will repeat
  }                                  //8 times the first time i will = 0 the final
                                     //time i will equal 7;

//Turn Each LED off one after another
  for(int i = 7; i >= 0; i--){  //same as above but rather than starting at 0 and counting up
                                //we start at seven and count down
    changeLED(i, LOW);  //Turns off LED #i each time this runs i
    delay(delayTime);                //gets one subtracted from it so this will repeat
  }                                  //8 times the first time i will = 7 the final                                    //time it will equal                                                                     
}

/*
 * oneOnAtATime() - Will light one LED then the next turning off all the others
 */
void oneOnAtATime(){
  int delayTime = 100; //the time (in milliseconds) to pause between LEDs
                       //make smaller for quicker switching and larger for slower
 
  for(int i = 0; i <= 7; i++){
    int offLED = i - 1;  //Calculate which LED was turned on last time through
    if(i == 0) {         //for i = 1 to 7 this is i minus 1 (i.e. if i = 2 we will
      offLED = 7;        //turn on LED 2 and off LED 1)
    }                    //however if i = 0 we don't want to turn of led -1 (doesn't exist)
                         //instead we turn off LED 7, (looping around)
    changeLED(i, HIGH);     //turn on LED #i
    changeLED(offLED, LOW); //turn off the LED we turned on last time
    delay(delayTime);
  }
}

/*
 * inAndOut() - This will turn on the two middle LEDs then the next two out
 * making an in and out look
 */
void inAndOut(){
  int delayTime = 100; //the time (in milliseconds) to pause between LEDs
                       //make smaller for quicker switching and larger for slower
 
  //runs the LEDs out from the middle
  for(int i = 0; i <= 3; i++){
    int offLED = i - 1;  //Calculate which LED was turned on last time through
    if(i == 0) {         //for i = 1 to 7 this is i minus 1 (i.e. if i = 2 we will
      offLED = 3;        //turn on LED 2 and off LED 1)
    }                    //however if i = 0 we don't want to turn of led -1 (doesn't exist)
                         //instead we turn off LED 7, (looping around)
    int onLED1 = 3 - i;       //this is the first LED to go on ie. LED #3 when i = 0 and LED
                             //#0 when i = 3
    int onLED2 = 4 + i;       //this is the first LED to go on ie. LED #4 when i = 0 and LED
                             //#7 when i = 3
    int offLED1 = 3 - offLED; //turns off the LED we turned on last time
    int offLED2 = 4 + offLED; //turns off the LED we turned on last time
   
    changeLED(onLED1, HIGH);
    changeLED(onLED2, HIGH);   
    changeLED(offLED1, LOW);   
    changeLED(offLED2, LOW);       
    delay(delayTime);
  }

  //runs the LEDs into the middle
  for(int i = 3; i >= 0; i--){
    int offLED = i + 1;  //Calculate which LED was turned on last time through
    if(i == 3) {         //for i = 1 to 7 this is i minus 1 (i.e. if i = 2 we will
      offLED = 0;        //turn on LED 2 and off LED 1)
    }                    //however if i = 0 we don't want to turn of led -1 (doesn't exist)
                         //instead we turn off LED 7, (looping around)
    int onLED1 = 3 - i;       //this is the first LED to go on ie. LED #3 when i = 0 and LED
                             //#0 when i = 3
    int onLED2 = 4 + i;       //this is the first LED to go on ie. LED #4 when i = 0 and LED
                             //#7 when i = 3
    int offLED1 = 3 - offLED; //turns off the LED we turned on last time
    int offLED2 = 4 + offLED; //turns off the LED we turned on last time
   
    changeLED(onLED1, HIGH);
    changeLED(onLED2, HIGH);   
    changeLED(offLED1, LOW);   
    changeLED(offLED2, LOW);       
    delay(delayTime);
  }
}



/*
 * updateLEDs() - sends the LED states set in ledStates to the 74HC595
 * sequence
 */
void updateLEDs(int value){
  digitalWrite(latch, LOW);     //Pulls the chips latch low
  shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
  digitalWrite(latch, HIGH);   //Pulls the latch high displaying the data
}

/*
 * updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
 * sequence. Same as updateLEDs except the shifting out is done in software
 * so you can see what is happening.
 */
void updateLEDsLong(int value){
  digitalWrite(latch, LOW);    //Pulls the chips latch low
  for(int i = 0; i < 8; i++){  //Will repeat 8 times (once for each bit)
  int bit = value & B10000000; //We use a "bitmask" to select only the eighth
                               //bit in our number (the one we are addressing this time through
  value = value << 1;          //we move our number up one bit value so next time bit 7 will be
                               //bit 8 and we will do our math on it
  if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data pin high
  else{digitalWrite(data, LOW);}            //if bit 8 is unset then set the data pin low
  digitalWrite(clock, HIGH);                //the next three lines pulse the clock pin
  delay(1);
  digitalWrite(clock, LOW);
  }
  digitalWrite(latch, HIGH);  //pulls the latch high shifting our data into being displayed
}


//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};
/*
 * changeLED(int led, int state) - changes an individual LED
 * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
 */
 void changeLED(int led, int state){
   ledState = ledState & masks[led];  //clears ledState of the bit we are addressing
   if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to ledState
   updateLEDs(ledState);              //send the new LED state to the shift register
 }



It works great, playing out each of the three animations in sequence and repeating. 


Try it out for yourself!