Lab 4: Sensors!


  1. First Build
    1. The Circuit
    2. The Code
  2. Hardware Theory
    1. Potentiometers
    2. Photoresistors
    3. Temperature Sensor
    4. Touch Sensor
    5. Arduino Shields
  3. Software Theory
    1. The Tone Function
    2. Printing to the Serial Monitor
    3. Using Analog Input
      1. Range Mapping
      2. Thresholding
    4. Libraries
      1. CapSense Quick Start
  4.  Exercises
    1. Night Light
    2. Danger Shield Setup
    3. Danger Night Light
  5. References

1. First Build

Take a few moments to build this circuit and install the sketch code. You will know you got things right if you hear weird noise coming from the piezo that changes and sounds "video-gamey" as you twist the potentiometer. The LED will be off most of the time but may flicker occasionally. If you have an Arduino Mega the tone will be pure and the LED will change brightness as you turn the potentiometer.

1.1 The Circuit

This circuit isn't too complicated. Pin A0 should be connected to the middle pin of the potentiometer. For everything else come up with your own interpretation of the schematic below.


1.2 The Code

Playing with pots.
Written 23 Aug 2011 by Alex Clarke

//constants for this sketch
const int ledPin = 11;
const int piezoPin = 6;
const int potPin = A0;

// variables for this sketch
int pot_value;
int frequency;

void setup()
pinMode(ledPin, OUTPUT);
pinMode(piezoPin, OUTPUT);

void loop()
//read voltage from the potentiometer
pot_value = analogRead(potPin);

//Set the LED to brightness pot_value
analogWrite(ledPin, pot_value);

//Play the sound represented by frequency pot_value
tone(piezoPin, pot_value);


2. Hardware Theory

This week you will be learning to use different types of analog input device. The Arduino's six analog inputs are able to sense different voltage levels and convert them to numbers you can use in your sketch. Some input devices provide voltages you can use directly. Others require creative use of Ohm's law and the concept of voltage division to use with your Arduino. This lab we will use the devices. Next lab you will explore the concept of voltage division in more detail.

2.1 Potentiometers

Potentiometers are the component behind most knobs that you see on electronic devices. They work by the principle of voltage division to adjust output voltage between two reference levels.

pot dissection

Inside they have a length of resistive material, often graphite or a carbon/plastic mixture, that is connected to terminal wires at either end.  A sliding contact connected to a third terminal is moved back and forth across the resistive material, usually with some kind of knob or slider. The the resistance between the contact and the two end terminals is related to the distance to the terminals — longer is more resistive and shorter is less.

The resistive material in most potentiometers stays the same along its length. Its resistance is directly, or linearly, related to length. In other potentiometers, the resistive material is tapered or changes properties across its length. This type is used in audio applications and is usually more expensive. The amount of resistance in this type is usually logarithmic - it increases with a curve that matches human sound perception.

Some potentiometers are meant to be used often. They are rugged and can be fitted with large knobs. Others are small and are meant to be hidden away. These are called trimpots, and are used by experts to tune a complex circuit. They are not meant to be used often and will wear out if twisted frequently.

The small blue potentiometer in your ARDX kit is a linear trimpot.

The pins labeled 1 and 3 are should be connected to two different voltage levels. Pin 2, the middle pin, will have a voltage between the levels on pins 1 and 3. Turning the knob counterclockwise will adjust pin 2's voltage toward that of pin 1, and clockwise adjusts it toward that of pin 3. If that seems confusing, then try rotating your trimpot so that the pins are away from you. Then it should make more sense.

If you use your potentiometer to measure the Ohms between pins 1 and 3 the value should remain constant. If you measure from pin 1 or pin 3 to pin 2 the value will change as you rotate the knob. In an ideal potentiometer the total of the two should add up to the number from pin 1 to pin 3. In the real world, the total is always a little smaller because the contact is a conductor with a measurable width.

To use a potentiometer with your Arduino you usually connect:

2.2 Photoresistors

Photoresistors are resistors that vary their resistance when exposed to light. They are less resistive under bright light than under dim light or in darkness. To use a photoresistor with your Arduino you must put it in series with a resistor to perform voltage division. A typical photoresistor sensor circuit would usually look like this:

Photoresistor Circuit

The range of values you read at the analog input depend on the resistance properties of the photoresistor and the voltage division resistor you select. Once you know these, you should be able to calculate the range using Ohm's law.

2.3 Temperature Sensor

There are two three pin components in your ARDX kit. One is a transistor. The other, pictured below, says TMP 36GZ on the flat side of its case and is actually a complicated integrated circuit (IC) that can sense temperature. If you put it in a 5V circuit it will provide a voltage based reading that is related to its temperature.

Temperature sensor pins

You need to know some properties of the sensor (datasheet here) to convert its output to a temperature in degrees:

This suggests the following equation:
temperature_in_celsius = output_in_volts * conversion_factor  - offset
temperature_in_celsius = output_in_volts * 100 - 50

2.4 Touch Sensor (Capacitive Sensing)

It is possible to use a pair of digital inputs on your Arduino to detect if someone is near to or touching a metal plate. If you use the right combination of resistors, metal and insulators you can make a pressure sensor. This page on capacitive sensing at explains the theory behind the technique and gives a tutorial on how to build and use such a sensor. You will not have to build one in lab. Instead your lab instructor will provide one on an Arduino shield called the Danger Shield.

The ability to read a touch sensor is not built into the Arduino or its IDE. Instead you need to install and include a library - the Capacitive Sense library - to make it work. Please refer to the section on installing libraries to learn how to install the Capacitive Sense library.

2.5 Arduino Shields

You will be given a Danger Shield from SparkFun. It is yours to use for this lab. Once you are done with the shield, please return it to your lab instructor.

Arduino shields work a little bit like game cartridges. They use the (sort of) standard layout of your Arduino's pins to allow you to plug in different circuits. This makes it easy to move your Arduino from project to project. There are many shields available in addition to the Danger Shield, which is mostly just and fun and learning. Most shields make a duplicate set of Arudino headers available to you so you can add your own circuits to unused pins. Some are even designed to be stacked one on top of the other so you can mix and match features that meet your project's needs.

Here's a list of links to some more useful shields:

You can see many more from various companies the shields sections at Solarbotics.

Because the Arduino world is a bit of a DIY (Do It Yourself) kind of place, many shields are shipped as a printed circuit board and loose parts. You get to solder them together yourself. The Danger Shield came that way. It can be great fun to learn to solder, and it is very rewarding when the finished product works.

Plug In the Shield

Once your shield is unpacked and assembled (this should have been done for you by the mentors), you plug it into the top of your Arduino like this:  


Note that you should line up the shield pins with the digital 0 and analog 5 pins on your Arduino because newer Arduinos like the Uno revision 3 have extra pins near the USB jack. Make sure the Danger Shield isn't touching the USB jack or Button A2/D10 will short and fail to work correctly.

3. Software Theory

3.1 The Tone Function

You can easily play notes on the piezo speaker in your kit with the tone() command. In its simplest form, a call to tone looks like this:

tone(pin, frequency);

The tone() command causes a note to begin to play on a pin at the specified frequency. The note will keep on playing while your program runs until another tone command is sent with a different frequency, or a noTone() command is sent.

There is a second form of tone() command that will stop automatically:

tone(pin, frequency, milliseconds);

As with the simple tone() command, your program will keep running while the note plays. If you want to wait for the sound to end before continuing with the program, you must use a delay() command of the same length as the tone. If you want silence between consecutive tones, you will need to use a longer delay.

Note: The tone() command has a nasty gotcha! It uses the PWM timers for pins 3 and 11 to make the note play automatically. Trying to use analogWrite() on those pins while you use the tone() command will cause strange things to happen. The first build sketch uses pin 11 to send analog writes to an LED which is causing interference. Change the sketch so it uses a different PWM pin. Enjoy the purer tones.

3.2 Printing to the Serial Monitor

Sometimes it's nice to be able to see what's going on inside your sketch. You can print values from your Arduino program to the computer and view them with the serial monitor in the Arduino software.

To begin sending messages to your computer you use the Serial.begin() command. You should use it in the setup() procedure. Try adding this to your setup():

Serial.begin(9600); // 9600 baud is the default serial communication speed

To send a message to the computer you use the Serial.print() or Serial.println() commands. They can print one variable or constant. They can also print a text message. Try adding this to your loop() just after the analogRead() command:

Serial.print("I just read: "); //Print some text
Serial.println(pot_value); //Print pot_value and go to next line
//delay(500); //You may want to slow down the messages so you can keep up

To see the resulting messages press the Serial Monitor button — Picture of the Serial Monitor Button — in your Arduino software. A window will pop up, your sketch will restart and text should appear. There's a menu in the lower right corner with a list of alternate speeds you can use with the Serial.begin() command.

3.3 Using Analog Input

Unlike with digital input, no pinMode() function call is needed to use analog input. All you need to do is call the analogRead(analogPin) function where analogPin is one of A0 through A5.

The analogRead() function returns an integer value between 0 and 1023 where 0 represents 0V and 1023 represents +5V. This is nice, but not helpful. You need to do some work to tell your Arduino how you want to respond to these values. Here are two basic strategies you can use to interpret analog input.

3.3.1 Range Mapping

The map() function changes input values from one integer range to another. Here's a sample function call:

result = map( input, fromLow, fromHigh, toLow, toHigh);

For example, if you use raw values from the analog port with the tone() function, the results cover several octaves and includes frequencies lower than you can hear. The tone() function can't even reproduce the lowest tones properly. That's why this sketch sounds weird in some positions even after fixing the PWM pin conflict. The result is hard to control. You might have more control if you map analog values to one octave. The official reference note for modern music is A440 or 440Hz. One octave higher than that is A880 or 880Hz. We can map from (0,1023) to (440,880) to get exactly one octave.  Change your tone playing code from this:

//Play the sound represented by frequency pot_value
tone(piezoPin, pot_value);

to this:

//Map pot_value to a usable frequency
int freq = map(pot_value, 0, 1023, 440, 880);
tone(piezoPin, freq);

Note: the results of the map() function are integers or whole numbers. If you try to use map() to convert analog readings to volts, like this:

float volts = map(pot_value, 0, 1023, 0, 5);

then you will only get the numbers 0, 1, 2, 3 ,4 or 5. If you want more precise results you need to use the float type which allows decimal places. You could then calculate voltage like this:

float volts = 5.0 * pot_value/1023.0;

3.3.2 Thresholding

A threshold is a value that splits a range of values into two parts — everything below and everything else or vice-versa. The following is an example of a threshold that you can try in your First Build sketch. Replace this code in your loop() procedure:
  //Set the LED to brightness pot_value
analogWrite(ledPin, pot_value);

with this code:

  //Set a LED on/off threshold where the potentiometer passes the mid-point
if (pot_value < 512)
digitalWrite(ledPin, LOW);
digitalWrite(ledPin, HIGH);

What this does is check to see if the voltage is less than halfway between 0V and +5V. That is 1023÷2 or 511.5.  When the potentiometer is exactly in the middle it should be near this value. If it is past it, the LED will turn on. If it is below it the LED will turn off.

You can also use a pair of thresholds to check if an input value lies inside a certain range. Change the above code as follows to light the LED when you are close to the midpoint on the pot:

  //Turn the LED on only if it is near the the mid-point
if (pot_value < 500 || pot_value > 524)
digitalWrite(ledPin, LOW);
analogWrite(ledPin, HIGH);

It is better to use a range check like this than to check to see if your potentiometer is at an exact value using the == operator because it is very difficult to accurately position a potentiometer.

3.4 Libraries

In computer programming, a library is a collection of code related to performing some task. In C and C++, the languages the Arduino language is based on, you have to request libraries by writing #include statements. If you downloaded the DangerShield demo code, you will see that it tries to include the CapSense library in the very first line:

#include <CapSense.h>

 * Danger Shield Example Sketch
 * Copyright (c) 2010 SparkFun Electronics.  All right reserved.
 * Written by Chris Taylor
 * This code was written to demonstrate the Danger Shield from SparkFun Electronics
 * This code will test all of the devices on the Danger Shield one at a time. 
 * Press button 1 (D10) to cycle through the different tests. View their output on 
 * a terminal running at 9600 baud. 

The Capacitive Sensing library is just one of many libraries for the Arduino. Some are built in to the language and you never have to worry about them. Some have been contributed to the Arduino project by others and are listed on the Arduino web site, but you have to install and #include them yourself. Others are meant for specific hardware. You'll usually find these or a link to them on the hardware's product page.

In the case of our Danger Shield, the needed library has been bundled with the sample code. You'll find it in the CapSense folder. The instructions for installing the library can be found on the Arduino web site libraries how-to page. It's not actually that hard, and that page does a pretty good job of discussing the details for different types of computers. Your lab instructor will demonstrate how to install the library for the Danger shield.

Lab Library Installation: Copy the CapSense folder from the unzipped Danger Shield demo to your Documents/Arduino/libraries/ folder, then completely restart Arduino IDE.

3.4.1 CapSense Quick Start

The touch sensor does not use analog pins and takes a bit of fiddling to use, but the library is actually making it easier. Let's see what we need to do.

We have already seen that we need to #include <CapSense.h> to use the CapSense library. Next you need to set up a CapSense object like this:

CapSense   cs_9_2 = CapSense(9,2);   //Initializes CapSense pins

This goes in the same place as your sketch constants and variables. Note that we will not need to refer to pins 9 and 2 ever again to use the CapSense object, so it is not necessary to make symbolic names for them.

Next you should turn off autocalibration it like this:

 cs_9_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // Turn off CapSense pin autocalibration.

You can use this function differently to tweak the behaviour of the touch sensor

Last, we need to get a reading from the sensor like this:

 long total =  cs_9_2.capSense(30);

The number 30 is the number of readings that will be added together and presented to you as the sensor's total.

4. Exercises

4.1 Night Light (5 marks)

In the lab demo we had a lot of fun with the potentiometer. You can try a photoresistor sketch yourself.

4.2 Danger Shield Setup (1 mark)

When you have demonstrated the Night Light sketch, your lab instructor will give you a Danger Shield. It is made and sold by SparkFun electronics. You will be using it a various times this semester because it includes ready to use sensors and outputs. SparkFun provides example sketch for Danger Shield. For this exercise, you will get that example to work.

4.3 Danger Night Light (4 marks)

The Danger Shield has a photo resistor based sensor which is set up a lot like the one you used for your night light. Examine the example to see which pins the photo resistor and one LED are on and adapt your Night Light sketch to the Danger Shield.

Note: the Danger Shield may use a different resistor than you, and it may be set up backward to how you set it up. You might want to recalibrate your threshold.

4.4 Challenges (Bonus)

Choose one

Danger Danger Danger (Danger) (In-lab only!)

Try to make it so that either the touch or temperature sensor on the Danger Shield can turn on the light.

12 Tone Arduino Instrument (At Home)

Adapt the First Build sketch so that, as you turn the potentiometer, the piezo speaker only plays notes in the 12 tone (chromatic) equal tempered scale. Because this scale can be easily calculated you may use math to make the code compact, or you may use arrays to make it fast.


During the lab: By online submission before next lab: (Optional) During this lab, in my office hours, or at the beginning of next lab:

5. References