## Saturday, January 22, 2011

### Physical Computing with Arduino: class 3

Today's class is going to be an exciting one. We have some new concepts to work with that are a little hard at first to understand but are very powerful. Here is a look at what we are going to learn today:

3. mapping: control LED with a Pot(lab)
4. thresholds and calibration: Brightness sensor (lab)
5. arrays and for loops: Multiple LEDs (lab)
6. Button counter w/state change (lab)

Modulo:

Modulo is an mathematical operator that calculates the remainder when one integer is divided by another. It is very useful for keeping a number with in a set of numbers, or counting to a certain number over and over. Lets take a look at how it works:
0 % 4 = 0
1 % 4 = 1
2 % 4 = 2
3 % 4 = 3
4 % 4 = 0
5 % 4 = 1
6 % 4 = 2
7 % 4 = 3
8 % 4 = 0

The first number can keep growing but the result will only be a number between 0-3. If you modulo by 255, instead of 4, you have a great number to throw into the analogWrite() command to PWM a digital pin. Thats just what we are going to do. In fact lets make a simple "clock" and then a metronome.

Using the function millis() returns the number of milliseconds since the Arduino has begun running a program. We can visualize the length of time the Arduino has been running a way that we recognize by chunking it into blocks of seconds, or fractions of seconds. Make the following circuit and then upload the corresponding code to make a simple clock.

/*
Simple Clock

Using % (modulo) and millis() to make a simple clock that
PWMs an LED to fractions of a second

Matt Richard
http://idblab.blogspot.com
*/

int pwmPin = 6;// digital pin to connect to LED
int pwmVal = 0;// variable that represents the PWM value for the LED to be placed in the analogWrite(pin, value) command.
int maxPWM = 256;// used with % to keep pwmVal between 0-255
int divisor = 2;// used to keep the increment of light and time relative
int pwmValIncrement = maxPWM / divisor;// if this # is a factor of 256 then the brightness steps will be even

int second = 1000;// number of milliseconds in one second
int time = second / divisor;// the increment in time that will trigger a change in the pwmVal

void setup() {
Serial.begin(115200);// begin a serial communication so we can see the millis count up.
}

void loop() {
// if the amount of time has passed then...
if(millis() % time == 0){
pwmVal = pwmVal + pwmValIncrement;// the value of the LED equals itself plus the LED light increment
pwmVal = pwmVal % maxPWM;// make sure the value of the LED is not greater than 255, if it is loop it back to 0
analogWrite(pwmPin, pwmVal);// PWM the led

Serial.println("time");// displays the change in light along side the change in millis
}
Serial.println(millis() % 1000);// displays the change in millis
}

The Arduino has 6 pins that allow you to receive analog values from sensors attached to those pins. The Arduino determines the value by reading the voltage coming into those pins and comparing it to the Arduino standard voltage of 5volts dc. We are going to discover how this works by using a potentiometer. Create the circuit below and then upload the following code onto the Arduino.

/*
Matt Richard
http://idblabs.blogspot.com
*/

int potPin = A0; // the pin which the middle pin of the potentiometer is attached
int potValue = 0; // the value that is sent from the potentimeter to the analog input pin

void setup() {
// create a serial connection so we can view the potentiometer readings in the serial monitor
Serial.begin(9600);
}

void loop() {
// read the value from the potentiometer

// display the value of the potentiometer in the serial monitor
Serial.println(potValue);
}

Now that we have used a potentiometer lets use the value to vary the delay between turning an LED on and off. Create the circuit below and then upload the following code onto the Arduino. The code is an example available with the Arduino ide found under 3.Analog/AnalogInput.

/*
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 circuit:
* 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 4 Sep 2010
By Tom Igoe
This example code is in the public domain.
*/

int sensorPin = A0; // 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:
// 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);
}

Thresholds and Calibration:

The potentiometer generated a value from 0-1024 a even range to use as an input. Most sensors do not generate such a nice range of values under normal working conditions. To accurately map a sensor you need to now what the thresholds of the sensor. Each sensor will have a minimum and maximum threshold. Lets use a photocell to change the brightness of an LED. To do this first we will need to determine the minimum and maximum threshold of the photocell. Create the circuit below and then upload the following code onto the Arduino.

/*
Matt Richard
http://idblab.blogspot.com
*/

int sensorPin = A0; // select the input pin for the potentiometer
int ledPin = 6; // select the pin for the LED
int sensorValue = 0; // variable to store the value coming from the sensor
int minThresh = 0;// replace this number with a lowest number from the serial monitor
int maxThresh = 1000;// replace this number with a highest number from the serial monitor

void setup() {
Serial.begin(9600);
}

void loop() {
// read the value from the sensor:
Serial.println(sensorValue);
analogWrite(ledPin, map(sensorValue, minThresh, maxThresh, 0, 255));
}

Once the program has been uploaded, open the serial monitor to view the incoming values from the photocell. Make note of the value of the photocell in ambient light, this is your maximum threshold. Now cover the photocell with your hand or an object to make it as dark as you can. This value is your minimum threshold. I like to add a small buffer of +-20 to insure that the photocell values do not go out of range under normal conditions, but make sure not to have a number less than 0. This is a simple way to calibrate your sensor. By replacing the values for minThresh and maxThresh with values from the serial monitor the effect of dimming the LED by placing your hand over the photocell has a greater effect on the brightness of the LED.

Arrays and For Loops:

Arrays are a way of declaring multiple of the same type of variable in a row in memory. Usually they are used with the idea that the values are multiples of the same type of object. What I mean is while the value of the photocell is an integer it doesn't make sense to include it in an array of integers that represent the digital pins used to power LEDs. Arrays are declared a little differently then other variables. Here are a few ways to declare an array:

int myInts;// this creates an array that has 6 places but does not define what the values are
int myPins[] = {2, 4, 8, 3, 6};// this creates an array of 5 places and defines the values
int mySensVals = {2, 4, -8, 3, 2};// this creates an array of 6 places but only defines the first 5 values

This is how you access the values that are store in the arrays above:

myPins + 1 = 3

The number inside of the square brackets [ ] indicates which value to access. Arrays are 0 based, meaning the first value is considered the 0 place not the 1st place.

Here is how you change the value of an element of an array:
myPins = 9;// now the values for myPins look like this: {2, 9, 8, 3, 6}

The real power of arrays is unleashed when combined with for loops. The structure of a for loop is a little confusing at first, but once you understand how to use them they are essential. Basically a for loop is a way of repeating a command a determined number of times. You can use an array to count from any number by any number to any number. This makes it perfect for working with arrays because instead of manually putting 0-4 inside of the [ ] to access the values of myPins array, you can use a variable.

Here is a for loop that prints the values of myPins array to the serial monitor:

for(int i = 0; i <>
Serial.print(myPins[i]);
Serial.print(", ");
}
Serial.println();

This snippet of code will display the values with a comma and space between each value and then a line break after the last element has been printed. I recommend that you take a look at the for loop link above. The guys at Arduino have a wonderful description of how the mechanics work.

Lets put it into action so you can see how easy they are to use. Create the circuit below and then upload the following code onto the Arduino.

contains code to allow me to not mess styles
/*
Using an array of digital pins and a for loop to easily contol LEDs
with a mapped value from a photocell
As you can see, using arrays and for loops makes your code a lot smaller
and easy to change.
Matt Richard
http://idblab.blogspot.com
*/

int sensorPin = A0; // select the input pin for the potentiometer
int ledPins[] = {
2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

/*
//how to write with out an array
int ledPin1 = 2;
int ledPin2 = 3;
int ledPin3 = 4;
int ledPin4 = 5;
int ledPin5 = 6;
int ledPin6 = 7;
int ledPin7 = 8;
int ledPin8 = 9;
int ledPin9 = 10;
int ledPin10 = 11;
*/
int sensorValue = 0; // variable to store the value coming from the sensor
int minThresh = 580;
int maxThresh = 870;

void setup() {
Serial.begin(9600);
for(int i = 0; i <>
pinMode(ledPins[i], OUTPUT);
}
/*
//how to write with out for loop
pinMode(ledPin1,OUTPUT);
pinMode(ledPin2,OUTPUT);
pinMode(ledPin3,OUTPUT);
pinMode(ledPin4,OUTPUT);
pinMode(ledPin5,OUTPUT);
pinMode(ledPin6,OUTPUT);
pinMode(ledPin7,OUTPUT);
pinMode(ledPin8,OUTPUT);
pinMode(ledPin9,OUTPUT);
pinMode(ledPin10,OUTPUT);
*/
}

void loop() {
// read the value from the sensor:
Serial.println(sensorValue);

controlLEDs();
}

void controlLEDs(){
int numLEDsOn = map(sensorValue, minThresh, maxThresh, 0, 10);
for(int i = 0; i <>
digitalWrite(ledPins[i], HIGH);
}
for(int j = numLEDsOn; j <>
digitalWrite(ledPins[j], LOW);
}
/*
// how to write without for loops and arrays
if(numLEDsOn == 0){
digitalWrite(ledPins1, LOW);
digitalWrite(ledPins2, LOW);
digitalWrite(ledPins3, LOW);
digitalWrite(ledPins4, LOW);
digitalWrite(ledPins5, LOW);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 1){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, LOW);
digitalWrite(ledPins3, LOW);
digitalWrite(ledPins4, LOW);
digitalWrite(ledPins5, LOW);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 2){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, LOW);
digitalWrite(ledPins4, LOW);
digitalWrite(ledPins5, LOW);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 0){
digitalWrite(ledPins1, LOW);
digitalWrite(ledPins2, LOW);
digitalWrite(ledPins3, LOW);
digitalWrite(ledPins4, LOW);
digitalWrite(ledPins5, LOW);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 3){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, LOW);
digitalWrite(ledPins5, LOW);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 4){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, LOW);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 5){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, HIGH);
digitalWrite(ledPins6, LOW);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 6){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, HIGH);
digitalWrite(ledPins6, HIGH);
digitalWrite(ledPins7, LOW);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 7){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, HIGH);
digitalWrite(ledPins6, HIGH);
digitalWrite(ledPins7, HIGH);
digitalWrite(ledPins8, LOW);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 8){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, HIGH);
digitalWrite(ledPins6, HIGH);
digitalWrite(ledPins7, HIGH);
digitalWrite(ledPins8, HIGH);
digitalWrite(ledPins9, LOW);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 9){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, HIGH);
digitalWrite(ledPins6, HIGH);
digitalWrite(ledPins7, HIGH);
digitalWrite(ledPins8, HIGH);
digitalWrite(ledPins9, HIGH);
digitalWrite(ledPins10, LOW);
}
if(numLEDsOn == 10){
digitalWrite(ledPins1, HIGH);
digitalWrite(ledPins2, HIGH);
digitalWrite(ledPins3, HIGH);
digitalWrite(ledPins4, HIGH);
digitalWrite(ledPins5, HIGH);
digitalWrite(ledPins6, HIGH);
digitalWrite(ledPins7, HIGH);
digitalWrite(ledPins8, HIGH);
digitalWrite(ledPins9, HIGH);
digitalWrite(ledPins10, HIGH);
}
*/
}
unless the resulting number would be less than 0.

## Saturday, January 15, 2011

Here is the agenda for class 2:
1. Soldering (lab)
2. Comment (code) - review from last week
3. Variables (code) - add to what we learned last week
4. Program structure (code) - add to what we learned last week
5. PWM - introduction to Pulse Width Modulation
7. Where to find components/tools/cool stuff

Soldering:
Soldering is simple in concept but takes some practice to become proficient. Before you begin soldering you will first need the necessary tools: soldering iron, solder and a copper scrubber. Some additional tools to mention are: solder flux, helping hands, and a solder vacuum. Out of all of the tools, having great solder and a nice clean tip on your iron will be the biggest help.
Soldering breaks down to a few simple steps. First, apply a beat of solder to the tip of a hot iron. This is called tinning the tip and will allow for easier transfer of heat between the tip and the metals to be soldered together. Next, apply the tip to the contacts(metal part of the component/wire to be soldered) and allow the metals to heat for a second or three. Now place the solder onto the contacts and wait for the solder to flow onto the metal. If done properly the solder will hug close to the contacts, you will know when it happens and it is spectacular. It took me a few hours of soldering to really get the hang of the it.

By far the most difficult part of soldering is juggling all of the components and tools. Two ways to help with this problem are to use a breadboard to hold the components or use helping hands. Using the breadboard is perfect for soldering breakout boards, boards made to have a component interface with a breadboard, but not as good as helping hands at most other soldering applications. One trick my friend Paul Rothman taught me was to use the helping hands to hold the solder instead of holding the components. This works if you can easily hold both components with one hand and the iron with the other.

There are tons of tutorials online that show you detailed examples of all types of soldering. I have embedded a great beginner video for reference.

Commenting (code):
Commenting code is an important part of making sense of what is going on in the code, especially when you come back to your program at a later date. Using comments, you can leave descriptions of the processes and variables used in your program. There are two kinds of commenting, line commenting(//...) and block comments(/*...*/).
Line commenting occurs each time you place two forward slashes in your code. The rest of the text on the line with the slashes is disregarded by the compiler. This is a great way to turn off one line of code but still have it available for a later time. Block comments use a combination of */ to begin the comment and */ to end the comment. Anything inside of those characters will be disregarded by the compiler. This allows you to turn off big chunks of code and create proper code descriptions.

/*
Turns on an LED on for one second, then off for one second, repeatedly.
This example code is in the public domain.
*/

void setup() {
// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards:
pinMode(13, OUTPUT);
}

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

Variables (code):
Variables are a way of storing and accessing values in programming. There are many different types of variables, each type has a limit to how big of a number or even what type of number can be stored inside. So far we have only used integers(int) in our code. An integer is a whole number with a range from -32,768 to 32,767. Today we will learn about floats, a number with a floating point or decimal. Floats are great for fine detail in rate of change as they allow us to have access to the numbers between whole numbers.

As we progress in class we will learn and use more variable types. If you want to learn more ahead of time you can check out the variables column on the Arduino website.

Program Structure (code):
/*
Smoothing

and printing it to the computer. Keeps ten readings in an array and
continually averages them.
The circuit:

Created 22 April 2007
By David A. Mellis

http://www.arduino.cc/en/Tutorial/Smoothing
This example code is in the public domain.
*/

// Define the number of samples to keep track of. The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input. Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.

int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average

int inputPin = A0;

void setup()
{
// initialize serial communication with computer:
Serial.begin(9600);
// initialize all the readings to 0:
}

void loop() {
// advance to the next position in the array:
index = index + 1;

// if we're at the end of the array...
// ...wrap around to the beginning:
index = 0;

// calculate the average:
// send it to the computer (as ASCII digits)
Serial.println(average, DEC);
}

It is important to have a standard structure when writing a program. A structure will make it easy for you and others to locate all of the components of your program.
The first part of the program should be a description of what the program is using block comments.
The second section is where you place all of your variables. Start with constants first and then group them according to their purpose. Don't forget to leave detailed comments.
The third section is for the setup() function. Void setup() is where you initialize your digital pins and communication lines.
The fourth section is for the loop() function. Void loop() is what gets executed by the microcontroller on every loop or frame. This will get repeated over and over until the microcontroller is turned off.
The fifth section(not depicted) is used for functions you create.

PWM - introduction to Pulse Width Modulation:

Pulse Width Modulation is a process of taking a digital pin(on/off) and creating a gradient value or change. By pulsing the pin on and off in varying square waves you can achieve a range of values which can be used to "dim" an LED. I say "dim" because really the LED is being turned on and off so fast that our eyes perceive it as dim.

/*
PWM LED
dim an led using analogWrite

code by Matt Richard

*/

int pinRed = 11;
int pwmValueRed = 0;
int pwmIncrementRed = 1;

int pinGreen = 3;
int pwmValueGreen = 0;
int pwmIncrementGreen = 2;

int pinBlue = 6;
int pwmValueBlue = 0;
int pwmIncrementBlue = 3;

int pwmMin = 0;// the lowest pwm value - 0 = off
int pwmMax = 255;// the highest pwm value - 255 = full on

void setup(){
Serial.begin(9600);
}

void loop(){
red();
green();
blue();
delay(20);
}

void red(){
pwmValueRed = pwmValueRed + pwmIncrementRed;
Serial.println(pwmValueRed);
// pwmValue += pwmIncrement;
// this takes care of the pwmValue being smaller than pwmMin
if(pwmValueRed <= pwmMin){
Serial.println("we reached red's bottom!");
pwmIncrementRed = pwmIncrementRed * -1;
pwmValueRed = pwmValueRed + pwmIncrementRed;
}
// this takes care of the pwmValue being larger than pwmMax
if(pwmValueRed >= pwmMax){
Serial.println("we reached red's top!");
pwmIncrementRed = pwmIncrementRed * -1;
pwmValueRed = pwmValueRed + pwmIncrementRed;
}
analogWrite(pinRed, pwmValueRed);
}

void green(){
pwmValueGreen = pwmValueGreen + pwmIncrementGreen;
Serial.println(pwmValueGreen);
// pwmValue += pwmIncrement;
// this takes care of the pwmValue being smaller than pwmMin
if(pwmValueGreen <= pwmMin){
Serial.println("we reached Green's bottom!");
pwmIncrementGreen = pwmIncrementGreen * -1;
pwmValueGreen = pwmValueGreen + pwmIncrementGreen;
}
// this takes care of the pwmValue being larger than pwmMax
if(pwmValueGreen >= pwmMax){
Serial.println("we reached Green's top!");
pwmIncrementGreen = pwmIncrementGreen * -1;
pwmValueGreen = pwmValueGreen + pwmIncrementGreen;
}
analogWrite(pinGreen, pwmValueGreen);
}

void blue(){
pwmValueBlue = pwmValueBlue + pwmIncrementBlue;
Serial.println(pwmValueBlue);
// pwmValue += pwmIncrement;
// this takes care of the pwmValue being smaller than pwmMin
if(pwmValueBlue <= pwmMin){
Serial.println("we reached Blue's bottom!");
pwmIncrementBlue = pwmIncrementBlue * -1;
pwmValueBlue = pwmValueBlue + pwmIncrementBlue;
}
// this takes care of the pwmValue being larger than pwmMax
if(pwmValueBlue >= pwmMax){
Serial.println("we reached Blue's top!");
pwmIncrementBlue = pwmIncrementBlue * -1;
pwmValueBlue = pwmValueBlue + pwmIncrementBlue;
}
analogWrite(pinBlue, pwmValueBlue);
}

Where to find components/tools/cool stuff:
Do to the change in culture here in America, hobbyist electronics is not as common as it once was. If you want to walk to a store to purchase electronic components your only option is likely to be Radio Shack. Radio Shack has an assortment of resistors and capacitors as well as a few IC(intergraded circuits). If you want a much better selection and lower cost, you will need to look online. Here is a list of some great electronics suppliers that I like.
Electronics:

Robotics:

Hardware/Materials: