Arduino Kit

From Hitchin Hackspace
Jump to navigation Jump to search

Arduino Kit Beginners Guide

This page is to provide information to go with the Hitchin Hackspace Arduino Starter Kit

Quick Link to the Hackspace Arduino Starter Kit PDF

Want to download the Hitchin Hackspace Arduino Starter Kit PDF and just get started then here is the link to it. Download it from our wiki https://wiki.hackhitchin.org.uk/images/e/ea/Hitchin_Hackspace_Arduino_Kit_Projects.pdf

Quick Link to the Hackspace Arduino Starter Kit Arduino Project code files

A zip file of the example project files used below can be download from this link Hitchin_Hackspace_Arduino_Kit_Projects.zip

Hitchin_Hackspace_Arduino_Kit_Projects.zip

Download the file. Once you have installed the Arduino Integrated Development Environment or "IDE" extract the zip file in to the folder C:\Users\<your user name>\Documents\Arduino\Projects\

Download the Arduino Integrated Development Environment or "Arduino IDE" Software Package

In order to programme an Arduino microcontroller you will probably want to start with an Interactive Development Environment. This is usually shortened to just the initials IDE. There are lots of IDEs about but most beginners probably start with the original Arduino IDE which is what we assume in this guide.

You can download the Arduino Integrated Development Environment Package, the Arduino IDE, from the Arduino Website. Once downloaded and installed you will be able to start programming your Arduino. The package is available from the Arduino download page https://www.arduino.cc/en/software. Versions are available for Windows, Mac and Linux.

Currently we would recommend the 1.8.x version until the 2.0.x version is formally released.

Arduino Programming Language Reference

Useful Programming Language Reference https://www.arduino.cc/reference/en/


Arduino IDE

Electronics

In electronic systems, electrical signals are used to control the flow of other electrical signals. Electronic circuits (systems built of interconnected components) can be connected to inputs to receive information about the outside world, and outputs to influence it. Computers are an example of an advanced electronic system; they take input via a keyboard and mouse, and give output through the screen and speakers. Using this kit, this tutorial will describe simpler electronic circuits that share the same fundamentals. This document only covers basic electronics, which is sufficient for a variety of projects such as the ones in this kit.

What’s in the kit/What’s an Arduino

The heart of this kit is a module called an Arduino Nano. Arduinos, to simplify, are a type of microcontroller - a miniature computer on a single chip (the square black chip at 45 degrees on the top side of the module). Like a full size computer, the chip contains long-term storage, working memory, a processor to perform calculations, and various subsystems - such as timers and ports to communicate with other computers.

Also like a full size computer, the Arduino is programmable - that is, its behaviour can be changed by writing computer code and storing it in the machine’s memory, rather than by directly changing connections within the circuit.

Apart from the Arduino, this kit also contains:

  • LEDs - small, low power lights that can be directly controlled by the Arduino
  • A ‘7-segment’ LED numeric display
  • Some button switches
  • A light sensor
  • A sounder
  • fixed and adjustable resistors
  • Prototyping breadboard to mount the components on
  • ‘jumper’ wires to connect them
  • a USB cable to connect the Arduino to the computer.
  • A power adaptor to provide 3.3V and 5 V from an external power supply* so your projects can be run without needing to be powered by the USB Lead

Note: * The External Power Supply can be between 5 and 12 Volts DC with a

The Arduino IDE

Launching

If you’re using a Hackspace machine to develop on, the Arduino IDE (Integrated Development Environment - an application that contains features to create and test programs) is already installed, and can be launched from the ‘Programming’ menu. If you’re using your own machine, you’ll need to download and install the Arduino IDE from ‘https://www.arduino.cc/en/Main/Software’. The current version of the IDE at time of writing is 1.8.19, and, if your machine is running Windows, it’s likely you’ll want the Windows Installer version.

Saving and loading

Similar to most other software, the Arduino IDE has ‘Save’ and ‘Open’ options in the file menu. Each sketch is stored in a separate directory. The directory must have the same name as the Sketch it contains. e.g. A project called "MySketch" will have a folder called "MySketch". When you save a project or Sketch from inside the Arduino IDE it will automatically create the folder for you and save the sketch code in to the folder with the suffix ".ino".

Compiling

Compiling is the process of translating an Arduino sketch into a form that’s suitable for download to the board. This stage will attempt to detect some types of errors that may exist in the sketch, such as syntax errors, where the structure of the language hasn’t been met, often due to a typo. The compiler will attempt to identify the specific line of the sketch at fault, though the root cause may be some distance from the actual error. To compile a sketch, click the ‘tick’ icon at the left of the Arduino IDE’s toolbar (labelled ‘verify’)

Uploading

The compiled sketch must be transferred to the Arduino board before it can be run. You’ll need to select the port the board is connected to (depending on whether you use Windows or Linux, the port may be called similar to ‘COM3’ or ‘/dev/ttyS0’) You’ll also need to tell the IDE the model of board that’s attached; for the board in this kit, the correct option is ‘Nano’, with a ‘ATmega328’ processor. These options are on the ‘Tools’ menu. To upload a sketch into the Arduino, click the forward-pointing arrow, the second icon on the toolbar.

Breadboard and cables

Breadboards are used to prototype electronic circuits - it’s made of a series of holes in a plastic case, some of which are electrically connected.

The breadboard in this kit has a main section of two banks, each of around 60 rows of 5 columns. Each row of 5 (on one bank labelled ‘A’ through to ‘E’ and on the other ‘F’ through to ‘J’) are internally connected. Rows are not connected to each other. There’s also no connection across the long central gap between the rows of each bank, so components with two rows of connections (like the Arduino) are often placed across the central gap. Outside the main section are the power rails: The red and blue coloured bars along these sections indicate all the holes there are connected together. Note that there’s a break in the coloured bars - and therefore the rails - about halfway along the breadboard. The red rail is traditionally used for the supply voltage, and it’s not connected to the blue rail, traditionally used for ground. The power rails are not connected to anything in the main bank. Additionally, the two sets of power rails on either side of the breadboard are not connected to each other.

To make a connection between two components, connect both of them to the same row of 5. Components themselves - assuming the terminals aren’t supposed to be connected - either go between two rows on the same bank, or across the central gap.

For historical reasons, the pitch of the breadboard holes is 2.54mm (0.1”) - most components will be compatible with this pitch.

Introduction to Electronics

Project: Blinky

This first project is a simple blinking light. This project requires the Arduino, the breadboard, jumper cables, a 180-ohm resistor (the one with brown-grey-brown-gold bands), and a red LED.

An example code file for this project can be download from this link Blinky.ino

Blinky.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder. For example on a windows PC create a folder called "Blinky" under

C:\Users\<your user name>\Documents\Arduino\Projects\

e.g. C:\Users\<your user name>\Documents\Arduino\Projects\Blinky

  1. Blink Stripboard setup Step 1
  2. Take the breadboard and insert the Arduino across the gap at one end. Align the first pins of Arduino (labelled D12 and D13) with the left end of the breadboard. The Arduino should cover rows D through to H; with the rightmost Arduino pins (labelled TX1 and VIN) in breadboard sockets D13 and H13, respectively.
  3. Blink Stripboard setup Step 2
  4. Take a short jumper wire (the colour doesn’t matter, but traditionally power supplies use red) and plug one end into socket J10, and the other end to the socket in the red rail directly beneath it. This will connect the Arduino’s ‘+5V’ pin - the positive power supply - to the red power supply rail. The Arduino will supply power from the computer’s USB port via this pin to the rail.
  5. Blink Stripboard setup Step 3
  6. Take another short jumper wire (ground connections traditionally use black) and connect breadboard socket J12 to the first socket in the third set of pins in the blue rail, opposite socket J14. This will provide a ground connection, via Arduino pin ‘GND’, between the blue ground rail and the connected computer.
  7. Blink Stripboard setup Step 4
  8. Add a red LED. The slightly longer leg of the LED should plug into breadboard socket I27, and the shorter leg into the adjacent socket in the blue ground rail. The LED will only work this way around, but shouldn’t be damaged if it’s plugged in the wrong way.
  9. Blink Stripboard setup Step 5
  10. Connect the 180-ohm resistor between sockets I20 and I24. It doesn’t matter which way around resistors go.
  11. Blink Stripboard setup Step 6
  12. Use two more jumper wires to connect the resistor to the Arduino pin labelled D6, and the LED to the resistor. The colour doesn’t matter, this example shows them in orange. The wires should connect terminals B5 and G20, and G24 and G26.
  13. This construction uses the Arduino to provide power to the supply rails, and connects the LED - via a resistor to limit the power - to one of the Arduino’s digital pins.
  14. Now, open the Arduino IDE.
  15. On the ‘Tools’ menu, set the board to ‘Arduino Nano’ and the processor to ‘ATmega328’.
  16. The sketch used for this project - called ‘blinky’ - is available (where?), and is also reproduced here.

// Instructions in this section ('setup') are run once,
// when power is applied or the Arduino is reset.


void setup() {
  // Set digital pin 6, which the LED is connected to,
  // to be an output.
  pinMode(6, OUTPUT);
}


// Instructions in this section ('loop') run continuously,
// until power is removed.


void loop() {
  // Set the output of digital pin 6 high, turning the LED on.
  digitalWrite(6, HIGH);
  // Delay 1 second (1000 milliseconds)
  delay(1000);
  // Set the output low again, turning the LED off.
  digitalWrite(6, LOW);
  // Delay another second.
  delay(1000);
  // At this point, control will loop back up to the start
  // of this section.
}

  1. Before applying power, check your wiring against the above diagram.
  2. Connect the USB cable to the computer and the Arduino. Make sure the power (‘PWR’) LED on the Arduino is solidly lit.
  3. The Arduino should be recognised by the computer, appearing in the ‘Port’ section of the ‘Tools’ menu of the Arduino IDE. Select it.
  4. Click the ‘Upload’ (forward arrow) button on the IDE’s toolbar. The computer will process the sketch, and, if there are no problems, transfer it to the Arduino.
  5. With luck, the LED is now flashing! If you encounter problems, feel free to ask for help.

The next section will explain how this project works.

Voltage and current

Electricity flows around a circuit. As the name suggests, there needs to be a ‘loop’. It’s usual (but not technically accurate) to consider electricity leaving the positive terminal of the supply - the terminal with the highest voltage - running through the various elements of the circuit, and returning to the supply via the ground (or negative) terminal. If any part of the circuit is broken, so that a loop including the supply no longer exists, no electricity will flow.

The usual analogy for voltage and current is to compare it with water flowing inside pipes. Electrical energy flows from high voltages towards low voltages. Voltage is comparable to the pressure of the water; current to the volume flowing. The higher the voltage being driven across a circuit, and the more current that flows, the more power is spent. Too much power, either because of excessive voltage or excessive current, can cause damage to the component, the Arduino or, potentially, a connected PC.

The Arduino in this kit has a supply voltage of 5 volts. This voltage is accessible from some pins of the Arduino, and can be used to provide power to other components. A rule, Ohm’s Law, connects voltage and current to a third property, resistance: the voltage (in Volts) across a circuit element (such as a connection, light or switch) is equal to that element’s resistance (in Ohms) multiplied by the current flowing through it (in Amps).

When two different points at different voltages are connected via a component, the current is determined by the difference in voltage divided by the resistance of the component. If the resistance is low (as is the case when the component is a wire, for example) the current can be destructively great. For this reason, do not directly connect two points that are fixed at two different voltages - in particular, don’t directly connect the supply voltage and ground.

Where two components are connected, a ‘good’ connection has a low resistance, and doesn’t cause much voltage to be lost, even when a high current flows. A ‘poor’ connection has higher resistance, and the ‘lost’ voltage across that connection can cause problems.

Driving LEDs

LEDs are low-power lights. They’re a type of diode, which are components that allow electricity to flow through them in one direction but not the other (which is why they won’t work if connected the wrong way around). Without something to limit it, they will allow dangerous amounts of current to flow, which may damage the LED or other devices attached to it (like the Arduino, or possibly even the USB port of a connected computer.) LEDs are connected via (‘in series with’) a resistor in order to limit current. A resistor is a component with the primary purpose of providing resistance in a circuit. As mentioned above, voltage and current are connected with resistance: If the voltage is fixed and resistance increases, current must decrease. The power requirements for LEDs vary, so the resistor used with them changes: For the yellow and red LEDs in this kit, use at least a 180 ohm resistor. For the other colours, use at least 100 ohms.

Structure of an Arduino sketch

An Arduino sketch is comprised of at least two sections, ‘setup’ and ‘loop’. The instructions in ‘setup’ run when the sketch starts, as the Arduino is powered up or reset. Afterwards, the instructions in ‘loop’ are run repeatedly, until power is lost or it’s reset. Each instruction (‘statement’) is run in turn, one after the other, from the top of the section towards the bottom. Two instructions can’t run simultaneously, so if one instruction takes a long time to complete (such as a delay instruction), the remainder of the sketch will be held up.

Instructions must be separated by a semicolon (‘;’), and it’s usual to have only one instruction to a line. Blank lines are ignored, as are lines that begin with ‘//’ and any text between the characters ‘/*’ and ‘*/’, even if that spans multiple lines. These are called ‘comments’, and are used to explain or annotate the instructions in the sketch.

pinMode()

It’s now time to introduce some of the instructions the Arduino is capable of understanding. Arduinos generally interact with the outside world by controlling electronic components that are connected to one of their pins. The Arduino is capable of setting most of its pins to either a ‘high’ output, a bit below the supply voltage, or a ‘low’ output, a bit above zero volts. However, when power is applied, the Arduino does not actively output on any of its pins. This is for safety reasons, in case an external connection to that pin is already connecting it to a different voltage. To enable output on a pin, the instruction:

pinMode(pin, OUTPUT)

where pin is replaced by the number of the pin, should be included in the sketch. Once a pin has been set to an output, it doesn’t need to be set again, so it’s sufficient to include it just in the ‘setup’ section.

digitalWrite()

After a pin has been configured as an output, the instruction: digitalWrite(pin, HIGH) or digitalWrite(pin, LOW) can be run to change the voltage on the pin. Voltages output by the Arduino will be close to the appropriate (supply or ground) connection.

delay()

The instruction: delay(ms) causes the Arduino to halt, delaying the execution next instruction by the specified number of milliseconds.

Things to try: Blinky

  • Modify the speed of the flashing.
  • If you know Morse code, get the flashing of the LED to signal a letter in Morse.

Project Idea: Larson Scanner

A Larson Scanner is the ‘scrolling’ LED effect seen on KITT in Knight Rider, or the Cylon faceplate in Battlestar Galactica (both, as it happens, created by Glen A. Larson.)

Connect several LEDs to different pins of the Arduino and write a sketch that turns them on one by one, with a delay. When you’ve turned the last on, go back in the other direction.

  • Remember to add resistors between the Arduino and the LEDs!
  • Set the pins you’re using as outputs using pinMode.
  • The loop() section of your sketch will need to handle one complete cycle of the animation, from the leftmost LED to the rightmost and back again.

Inputs

Project: Toggle Switch

This project introduces inputs to the Arduino. Two switches control an LED.

An example code file for this project can be download from this link Toggle_Switch.ino

Toggle_Switch.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder For example on a windows PC create a folder called "Toggle_Switch" under C:\Users\<your user name>\Documents\Arduino\Projects\ e.g. C:\Users\<your user name>\Documents\Arduino\Projects\Toggle_Switch

It extends the previous project. Start by rebuilding that project if necessary (disconnect the Arduino from the PC before you do!), then you’ll also need two switches, two 10K resistors (banded brown-black-black-red-brown) and additional jumper wires.

Toggle Switch Stripboard setup
  • Place the two switches across the central gap, with the pins of the switches pointing along the short edge of the breadboard. There are four terminals to each switch, but the opposite terminals (not the pairs closest together, but the pairs ‘across’ the switch) are internally connected.
  • Add a resistor between the right-hand terminals of each switch and the blue ground rail. Remember that if you connect to the ground rail ‘after’ the gap in the rail, you’ll need an additional wire to bridge the gap.
  • Add wires between the left-hand terminals of each switch and the red supply rail.
  • Use two longer wires to connect the right-hand terminals of each switch to Arduino pins D7 and D8. You can connect to either bank of the breadboard, thanks to the internal connections of the switches.

This circuit adds two inputs to the Arduino. When the switches are pressed, the inputs will be temporarily connected to the supply voltage; when they’re released, the resistors will pull the inputs to ground.

The sketch used for this project is called ‘toggle’:

void setup() { // Set digital pin 6 (the LED) as an output. pinMode(6, OUTPUT); // Set digital pins 7 and 8 (the buttons) as inputs. pinMode(7, INPUT); pinMode(8, INPUT); } void loop() { // If the input at pin 7 is a high voltage, if (digitalRead(7)) { // Turn the LED on. digitalWrite(6, HIGH); } // If the input at pin 8 is a high voltage, if (digitalRead(8)) { // Turn the LED off. digitalWrite(6, LOW); } }

Connect the Arduino to the computer, and upload the project as before.

Now, press each switch in turn. You should find that one switch will cause the LED to light, and the other switch turns it off.

The following section covers the internals of this project.

if() statements

In all the sketches covered so far, statements are executed one after another, running through each section until complete. To give the sketch more interesting behaviour (and react to the real world) some instructions alter the order other instructions are run in. These instructions are known as control-flow statements.

The simplest control-flow statement is: if (condition) { statement; statement; }

When the if statement is executed, it evaluates the condition. If the condition is true, control passes in turn to the statements within the braces; otherwise, control ‘skips’ those instructions and continues after the closing brace. The condition is an ‘expression’. Some examples of expressions are a ‘literal’ - the keyword ‘true’ or ‘false’ - the result of a function (see below), or a variable or comparison operator (covered later).

There can also be an else section: if (condition) { … } else { … }

The statements in the else block are executed if the condition is false - that is, either the first block or the second block will run, but not both.

digitalRead()

To respond to events in the outside world, the Arduino must be able to take input from sensors connected to its pins. The basic means of doing that is the digitalRead function:

if (digitalRead(pin)) { … }

When used as part of a statement, digitalRead examines the voltage on the specified pin. If the voltage is ‘high’ (close to the supply voltage), digitalRead ‘returns’ (behaves as) true. If the voltage is close to ground, it returns false. Should the voltage be somewhere in the middle, or the pin entirely disconnected, the value of digitalRead can’t be predicted with certainty, so that should be avoided.

Pins must be set as inputs before a value can be read. On startup, all pins are set as inputs, but if you’ve previously (in the same sketch) used a pin as an output, it’s necessary to call pinMode to change it back.

while() statements

Another control-flow statement is while().

while (condition) { statement; statement; }

Similar to the if statement, when control reaches the ‘while’, the condition is evaluated. If the condition is true, the statements inside the braces are executed; otherwise, execution resumes after the closing brace. The difference from ‘if’ is that after the statements in the braces have completed, the condition is again checked. If it’s still true, control ‘loops’ back up to the first statement inside the brace, and the statements are executed again; this continues until the condition is false. The condition is only checked once per loop.

Variables

It’s often necessary to store some information for future use. In an Arduino sketch, variables are used for this. A variable is a portion of the Arduino’s memory that’s reserved, and given a name, so that a sketch can refer to it. To use a variable, it’s first necessary to declare it:

       int some_name;

This can be done either at the top-level (outside of both the setup() and loop() functions), or as a statement nearly anywhere. An important aspect of variables is ‘scope’ - the region of a sketch where the variable is accessible. Generally, a variable can be accessed from the block (section of code between opening and closing braces) it’s declared in, and any block enclosed by it. It can’t be accessed from an unrelated, or higher-level, block.

In this example, ‘some_name’ is the name given to the variable, and ‘int’ is the type. Variables must be given a type to tell the Arduino how to interpret the information stored there. In this case ‘int’ - Integer - means the variable will hold round numbers. Other types you may need are ‘bool’ - the value is either true or false, ‘float’ - numbers including a fractional or decimal component, and ‘long’ - for large, whole numbers.

After a variable has been declared, you can assign values to it:

       some_name = 3;

They can also hold the results of computations:

       some_name = another_variable + 3;

Note that the addition is performed only when the instruction is executed. If the value of ‘another_variable’ later changes, the value of ‘some_name’ won’t automatically be updated.

Variables can then be used in conditionals:

       if (some_name == 42) {
               // This block will be executed if the value of some_name is exactly 42.
               …
       }
       if (some_name > another_variable) {
               // This block will be executed if the value of some_name is strictly greater than
               // that of another_variable.
               … 
       }

Note that checking whether a variable is equal uses two equals symbols ‘==’ to distinguish it from assignment.

millis()

The Arduino contains an internal clock, which counts how long the current sketch has been running. This clock can be accessed by the millis() function; it returns the number of milliseconds since the last power-up or reset. The value returned by the millis() function can be assigned to a variable or compared to other values to create code that does different things at different times.

Relational operators

Variables can be compared using equality ‘==’, not-equals ‘!=’, (strictly) greater-than ‘>’, greater-than-or-equal ‘>=’, (strictly) less than ‘<’, or less-than-or-equal ‘<=’.

Comparisons can themselves be combined with and ‘&&’, or ‘||’ and not ‘!’. For example,

       if ((some_name == 3) && ((another_variable < 14) || digitalRead(7)) {
               …
       }

In this case, the code inside the block will be run if ‘some_name’ is exactly equal to 3, and either ‘another_variable’ is less than 14, or the voltage on pin 7 is high, or both. Parentheses have been used to group the components of this statement together, to ensure it’s evaluated in the right order. By contrast, in:

       if (((some_name == 3) && (another_variable < 14)) || digitalRead(7) {
               …
       }

the contained block will execute if both ‘some_name’ is 3 and ‘another_variable’ is less than 14, or alternatively if the voltage on pin 7 is high.

Pullups

As was mentioned above, if the input pin is entirely disconnected from any voltage, the value digitalRead() returns is unpredictable. For this reason, when a switch is connected to one of the input pins, it’s usual to add a ‘pull-up’ or ‘pull-down’ resistor to the voltage opposite the one the switch is connected to. When the switch is released, this resistor ‘pulls’ the voltage at the pin to the voltage on the other side of the resistor, so the Arduino pin isn’t completely disconnected. When the switch is pressed, the connection through the switch is of a much lower resistance than the connection through the resistor, and ‘swamps’ it, making the voltage at the input pin equal to the voltage on the other side of the switch.

Resistors of around 10K ohms are generally used as pull-up or pull-down resistors. Values much higher than this may not be effective, and values much lower allow too much current to flow, wasting power.

Switch bounce

One problem that occurs when interacting with the outside world is switch bounce. The mechanical components of a switch are affected by physical laws, and don’t therefore behave ‘perfectly’. When a switch is pressed, a contact between the terminals is made and broken repeatedly for a fraction of a second before a good connection is made; a similar thing happens when the switch is released.

If this switch is connected to a digital input pin of an Arduino, as it frequently will be, digitalRead on that pin will return a series of seemingly-random ‘true’ and ‘false’ values as the switch settles down. In this example fragment:

void loop() {
        int counter = 0;
while (digitalRead(pin) == false) {
                // Do nothing. Wait for the switch to be pressed.
        }


        counter = counter + 1;


        while (digitalRead(pin) == true) {
                // Do nothing. Wait for the switch to be released.
}        
}
 

The intent was for the counter to be increased by one each time the switch was pressed. Due to switch bounce, however, a single intentional keypress may cause many (even hundreds) of changes in the pin state to be recorded by the sketch. The usual approach to resolving this is to wait for the pin input to stabilise on a value before using it, by reading it multiple times:

        // Record how long a pin has been high/low.
        // These are declared outside loop(), because we want the values to be remembered
        // between loops.
        int time_high = 0;
        int time_low = 0;
        
        void loop() {
                …
                // Is the pin currently high?
                if (digitalRead(pin) == true) {
                        // It’s high - increment the high counter, and reset the low counter
                        time_high = time_high + 1;
                        time_low = 0;
                } 
                else {
                        // It’s low - increment the low counter, and reset the high counter
                        time_low = time_low + 1;
                        time_high = 0;
                }
                
                if (time_high > 500) {
        // We can now be reasonably certain that the switch is pressed.
}


if (time_low > 500) {
        // We can now be reasonably certain that the switch is not pressed.
}
 

For this to work, the value of the switch must be read very frequently. If your loop function contains delays, and the switch is tested once per loop, it may take a (very) long time for 500 consecutive samples to be the same. If you’re using input like this, it’s best to avoid use of the delay function in your sketch.

Things to Try: Toggle Switch

  • Start with the LED off. Make pressing one button turn the LED on for a short period; the other button a longer period.
  • Modify the sketch so that the first button press turns the LED on, and a second turns it off. You’ll probably have to debounce the switch input.
  • A bit trickier: Rewrite the first - Blinky - sketch to use a continuously running loop() and the millis() function, rather than delay().

Project Idea: Traffic Light=

Connect a red, a yellow and a green LED, plus a switch, to the Arduino. Start with the lights showing green. When the switch is pressed, cycle through the traffic light sequence: yellow, red, red and yellow, green.

Analog Outputs

Project: Breathing Light

This project modifies the sketch from the first project to make the LED fade in and out.

An example code file for this project can be download from this link Breathing_Light.ino

Breathing_Light.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder For example on a windows PC create a folder called "Breathing_Light" under C:\Users\<your user name>\Documents\Arduino\Projects\ e.g. C:\Users\<your user name>\Documents\Arduino\Projects\Breathing_Light

Breathing Light Stripboard setup. This is the same as the "Blink" setup but with modified code.

The circuit used is the same as that of the first project. Rebuild that project if necessary, or the circuit from the second project will also work without modification.

The sketch used for this project - ‘breathe’ - is on the next page.

void setup() {
  // Configure the pin connected to the LED.
  pinMode(6, OUTPUT);
}


void loop() {
  // Run this section repeatedly, with the variable
  // 'i' taking values between 0 and 255, inclusive;
  for (int i = 0; i < 256; i = i + 1) {
    // Change the average output level on the LED's pin
    analogWrite(6, i);
    // Delay for 10 milliseconds each iteration
    // for a total ramp-up time of 2.56 seconds.
    delay(10);
  }
  // Now count downwards from 255 to 0, exclusive.
  for (int i = 254; i > 0; i = i - 1) {
    // Set the average output level of the LED
    analogWrite(6, i);
    // Delay such that the total fade out takes around 2.5
    // seconds.
    delay(10);
  }
  // Execution will now jump back up to the top of 'loop',
  // starting the fade-in again.
}
 

Connect the Arduino, and upload the sketch as before. You should find the LED is slowly fading between minimum and maximum brightness. The internals of this project are explained in the next section.

analogWrite()

Arduinos are by themselves, only capable of setting a high or low voltage on their output pins, nothing in the middle (that is, they’re digital outputs). However, it’s sometimes necessary to control another component (for example, an LED) that you don’t want to be fully off or fully on, but rather partially lit (an analog output). A compromise is that the Arduino can be instructed to turn an output on and off very rapidly, so that, ‘on average’, the output value is somewhere between the two extremes. The instruction for this is:

       analogWrite(pin, value)

Where value is the fraction of time the pin should be at a high voltage, and therefore the average output level of the pin. Values can range between 0 - fully off, and 255 - fully on. A value of 128, for example, sets the pin to be high about 50% of the time.

Only pins 3, 5, 6, 9, 10 and 11 can be controlled in this way.

Many common external components, such as LEDs and motor drivers, are happy with a rapidly-alternating signal like this. For others, the signal can be converted to true analog with a few external components.

for() statements

Another control-flow statement you may see or find useful is ‘for’. It’s another type of loop construction, but has a bit more functionality than while:

       for (counter = 0; counter < 5; counter = counter + 1) {
               // This block will execute 5 times.
               …
       }

The for-statement has three components to it. The first is executed when the loop first begins, and is a ‘setup’ for the loop. The second is the exit condition for the loop, and behaves in the same way as it does in ‘while’ - if the condition is false when it’s checked, the loop ends (‘terminates’). The third component is executed once every time through the loop, as if it were the last instruction inside the block. In particular, the third component is executed just before the exit condition is checked. In this example, the loop will first execute with counter equal to zero, then, when the body of the loop has been run, the counter will be incremented, the exit condition checked (it will be true), and the loop run again, with counter equal to 1. The loop will also run with counter values of 2, 3, and 4, but after the final loop (with counter value 4), the increment will run, making counter 5, and the condition will no longer be true, causing the loop to end. As an aside, ‘++counter’ is, approximately, a shorthand for ‘counter = counter + 1’, which is often seen in for() statements.

Things to try: Breathing Light

  • Modify the pattern to resemble a Christmas decoration fade pattern - for example, fade slowly twice, then quickly three times, then repeat. A loop may be helpful here.
  • Add another LED, and have it fade in as the first LED fades out.

Project Idea: Dimmer Switch

Connect an LED and two switches to the Arduino. Pressing one switch should decrease the brightness of the LED; the other one should increase it.

  • The circuit should resemble the one used in the ‘toggle’ project.
  • Store the brightness of the LED in a variable.
  • In loop(), check the inputs: if one is high, increase the variable. If the other is high, decrease it. Debouncing probably isn’t necessary here.
  • Make sure the brightness can’t go below zero or above 255.

7-Segment Displays

Project: Counter

This project connects a seven-segment display, as seen on digital clocks - to the Arduino, and uses it to count the digits zero to nine.

An example code file for this project can be download from this link 7_Segment_Display_-_Counter.ino

7_Segment_Display_-_Counter.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder For example on a windows PC create a folder called "7_Segment_Display_-_Counter" under C:\Users\<your user name>\Documents\Arduino\Projects\ e.g. C:\Users\<your user name>\Documents\Arduino\Projects\7_Segment_Display_-_Counter

The display is made up of seven (eight, including the decimal point) individual LEDs. These LEDs require 100-ohm resistors, so in addition to the display and jumper wires, you’ll need seven of these.

7 Segment Display Stripboard setup

The wiring for the seven-segment display is a little tricky. The terminals of the display are numbered from one to ten, with pin ‘1’ being to the bottom-left of the digit (the decimal point is on the bottom-right) and pins being numbered anticlockwise from there.

Each segment of the display (except the decimal point, which we don’t use) is connected via a 100-ohm resistor (coloured brown-black-brown-gold) to the Arduino digital pins 2 to 8.

  • Pin 1 of the display (segment ‘E’) should be connected to one end of a resistor, and the other end to Arduino pin D6.
  • Pin 2 of the display (segment ‘D’) should be connected via a resistor to Arduino pin D5.
  • Pin 3 (ground) should be connected to the ground rail. Make sure, if you connect it after the break in the rail, that the gap is bridged by a wire.
  • Pin 4 (segment ‘C’) should be connected via resistor to Arduino pin D4.
  • Pin 5 (decimal point) should be left unconnected.
  • Pin 6 (‘B’) should be connected via resistor to Arduino pin D3.
  • Pin 7 (‘A’) should be connected via resistor to Arduino pin D2.
  • Pin 8 of the display (ground) need not be connected. Pins 3 and 8 are connected internally.
  • Pin 9 (‘F’) should be connected via resistor to Arduino pin D7.
  • Pin 10 (‘G’) should be connected via resistor to Arduino pin D8.

The sketch for this project - ‘counter’ - covers several pages.

// The display segments are named as follows:
//  aaa
// f   b
// f   b
// f   b
//  ggg
// e   c
// e   c
// e   c
//  ddd

// Declare some variables representing the segments.
// 'const' means the value of these variables should be constant - they can't be reassigned.
const byte SEG_G = 0b1000000;
const byte SEG_F = 0b0100000;
const byte SEG_E = 0b0010000;
const byte SEG_D = 0b0001000;
const byte SEG_C = 0b0000100;
const byte SEG_B = 0b0000010;
const byte SEG_A = 0b0000001;

// This creates an array of ten elements - one for each digit '0' to '9'
// containing the patterns to display each.
const byte digits[10] = {
  // The '|' symbol combines the patterns together by performing a bitwise 'or'
  // Zero has all segments lit except G.
  SEG_F | SEG_E | SEG_D | SEG_C | SEG_B | SEG_A,
  // One has segments B and C lit.
  SEG_B | SEG_C, 
  // Two has A, B, G, E and D lit.
  SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,
  // Three has A, B, G, C and D lit.
  SEG_A | SEG_B | SEG_G | SEG_C | SEG_D,
  // Four has F, G, B and C lit.
  SEG_F | SEG_G | SEG_B | SEG_C,
  // Five has A, G, F, D and C lit.
  SEG_A | SEG_G | SEG_F | SEG_D | SEG_C,
  // Six has all segments lit except B.
  SEG_G | SEG_F | SEG_E | SEG_D | SEG_C | SEG_A,
  // Seven has A, B and C lit.
  SEG_A | SEG_B | SEG_C,
  // Eight has all segments lit.
  SEG_G | SEG_F | SEG_E | SEG_D | SEG_C | SEG_B | SEG_A,
  // Nine has all segments lit except E.
  SEG_G | SEG_F | SEG_D | SEG_C | SEG_B | SEG_A,
};

void setup() {
  // Digital pins 2 to 8 are used to connect to the display.
  for (int i = 2; i <= 8; i = i + 1) {
    pinMode(i, OUTPUT);
  }
}

// Create a counter variable.
int counter = 0;

void loop() {
  // Retrieve from the array the pattern to display the current digit.
  byte pattern = digits[counter];

  // If the pattern includes segment G, light it. Otherwise, turn it off.
  if ((pattern & SEG_G) != 0) {
    digitalWrite(8, HIGH);
  }
  else {
    digitalWrite(8, LOW);
  }
  
  // Similarly for the remaining segments
  if ((pattern & SEG_F) != 0) {
    digitalWrite(7, HIGH);
  }
  else {
    digitalWrite(7, LOW);
  }

  if ((pattern & SEG_E) != 0) {
    digitalWrite(6, HIGH);
  }
  else {
    digitalWrite(6, LOW);
  }

  if ((pattern & SEG_D) != 0) {
    digitalWrite(5, HIGH);
  }
  else {
    digitalWrite(5, LOW);
  }

  if ((pattern & SEG_C) != 0) {
    digitalWrite(4, HIGH);
  }
  else {
    digitalWrite(4, LOW);
  }

  if ((pattern & SEG_B) != 0) {
    digitalWrite(3, HIGH);
  }
  else {
    digitalWrite(3, LOW);
  }

  if ((pattern & SEG_A) != 0) {
    digitalWrite(2, HIGH);
  }
  else {
    digitalWrite(2, LOW);
  }

  // Advance the counter.
  counter = counter + 1;

  // Limit it to '9'.
  if (counter == 10) {
    counter = 0;
  } 

  // Delay one second.
  delay(1000);
}
 

Connect the Arduino to power, and you should see the display count from zero to nine, and restart. If the display looks garbled, some connections may need to be rechecked.

The next section covers the new material in this sketch.

Arrays

Arrays are a method of storing several related variables without having to declare and name them individually, like a book with different contents on each page. The syntax for declaring arrays is:

       int array_name[10];

‘int’, as for variables, is the type of data that will be stored in each element of the array. The ‘10’ is the number of elements in the array (its size). Each element of the array is independant - saving a value to it won’t affect the other entries of the array - and accessed using square-bracket notation:

       array_name[4] = array_name[7] + array_name[3];

In Arduino sketches, array ‘indexes’ (the numbers that specify which element of the array is being accessed) start at zero. ‘array_name[4]’ is therefore the fifth element.

Binary

Internally, the Arduino, like most computers, represents numbers in binary, or base-2, where each digit represents a power of two. The decimal system usually used has each digit representing powers of 10. In the decimal number:

  146

The ‘1’ is units of 100, the 4 is units of 10, and the 6 is units of 1. The total value is (100 x 1) + (10 x 4) + (1 x 6). In the equivalent binary number:

  10010010

The rightmost column again represents units of ‘1’, then, moving left from there, ‘2’, ‘4’, ‘8’, ‘16’, ‘32’, ‘64’ and ‘128’. This number therefore represents (128 x 1) + (64 x 0) + (32 x 0) + (16 x 1) + (8 x 0) + (4 x 0) + (2 x 1) + (1 x 0) - that is, 128 + 16 + 2, or 146.

In the Arduino IDE, numbers can also be input in binary, using 0b notation:

       0b10010010

Bitwise operators

It’s sometimes helpful to consider the bits of a binary number separately - for example, in this project, we use each a single number made up of seven bits to tell the display which of the seven segments to light.

To interact with individual bits, variations of and ‘&’, or ‘|’, and not ‘~’ work on each bit separately - they work ‘bitwise’. The output of the expression is the same length of the input, where each the value of each bit of the output is based on the corresponding bits from the input(s).

As with decimal digits, bits are numbered and paired up from the right and working left - so the ‘first’ bit of the output is the rightmost, and uses the rightmost bits from both inputs, the ‘third’ bit uses input bits that are also third-from-right. Again, as with decimal numbers, if a bit ‘isn’t there’ - for example, the fifth bit of a four-bit number - it’s treated as zero.

For the ‘&’ operator, the bit in the output is set - that is, has value ‘1’ - if and only if both the corresponding bits in the inputs are set; otherwise (if at least one of them is zero), the bit is cleared - has value ‘0’.

The ‘|’ operator, on the other hand, sets a bit if either input bit is set, and only clears a bit if both input bits are clear.

The ‘~’ operator takes only one input and ‘inverts’ it - setting all the bits that were clear, and clearing all the bits that were set.

For example:

       0b10010010 & 0b10110100 == 0b10010000
       0b10010010 | 0b10110100 == 0b10110110
       ~0b10010010 == 0b01101101

Bitwise operators are used by the counter project to identify segments of the display. Each segment, starting at the top and going clockwise, is assigned a letter - ‘A’ through to ‘G’ (‘G’ is the middle horizontal segment). The counter project treats the first bit of each number as referring to segment ‘A’, the second to segment ‘B’, and so on, with the seventh bit controlling segment ‘G’.

The section near the top of the sketch creates variables for each of these segments - so ‘SEG_A’ contains the pattern for segment ‘A’ (and only that segment) lit.

The next section - where the array is created - is where the full patterns for each digit are defined. Combining patterns together with ‘|’, as this sketch does, results in a pattern where multiple segments are lit.

Further on in the sketch, it’s necessary to ‘extract’ information about the individual segments of a pattern, so we know whether to turn a specific segment on or off. This is done with the ‘&’ operator. Remember that ‘&’ only leaves a bit set in the output if it’s set in both inputs. Here, one input is always one of the individual segment patterns, which has only one bit set, and the other is the pattern we want to display. Because only one bit is set in the first input, only that bit can possibly be set in the output, and then only if that bit is also part of the pattern we want to display. The other bits will always be cleared. The result of this bitwise operation is compared against zero - if all bits are cleared, meaning the pattern we want to display does not contain this segment, the value of the number as a whole will be zero and the segment will be turned off. If the value of the number is not zero, the bit was still set and the pattern we want to display does contain this segment, so we turn it on.

There’s also exclusive-or ‘^’, which results in the output bit being set where either input bit is set, but not both:

       0b10010010 ^ 0b10110100 == 0b00100110

Finally, there are left-shift and right-shift operators, which move bits left and right within a number:

       0b10010010 << 2 == 0b01001000
       0b10010010 >> 2 == 0b00100100

Note that bits shifted out of the number entirely are lost.

Things to try: Counter

  • Make the counter go more slowly as it increases. For example, going from 3 to 4 might take twice as long as 2 to 3.
  • Trickier: Rewrite the main section of the sketch - where the segments are turned on or off as appropriate - to use a loop rather than the same lines copied and pasted. You may need to use another array or a shifting operator.

Project Idea: Scorekeeper

Connect the 7-segment display and two buttons to the Arduino. Start with a score of zero: One button is for gaining points: if it’s pressed, increase the score. The other is for losing points. Show the current total on the display.

  • What would you like to happen if the score goes below zero or above 9?

Functions

Project: Dice

This project extends the previous uses the display to simulate a 6-sided dice.

An example code file for this project can be download from this link Dice.ino

Dice.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder For example on a windows PC create a folder called "Dice" under C:\Users\<your user name>\Documents\Arduino\Projects\ e.g. C:\Users\<your user name>\Documents\Arduino\Projects\Dice

Rebuild the previous project if necessary; you’ll also need a switch and a 10K resistor.

Dice Stripboard setup

Connect one terminal of the switch to the supply rail, and one of the adjacent terminals via a 10K pull-down resistor to the ground rail. Connect the same terminal (or the one across from it) to Arduino pin D9.

The code for this project - ‘dice’ - shares a great deal with the previous one.

// The display segments are named as follows:
//  aaa
// f   b
// f   b
// f   b
//  ggg
// e   c
// e   c
// e   c
//  ddd

// Declare some variables representing the segments.
// 'const' means the value of these variables should be constant - they can't be reassigned.
const byte SEG_G = 0b1000000;
const byte SEG_F = 0b0100000;
const byte SEG_E = 0b0010000;
const byte SEG_D = 0b0001000;
const byte SEG_C = 0b0000100;
const byte SEG_B = 0b0000010;
const byte SEG_A = 0b0000001;

// This creates an array of ten elements - one for each digit '0' to '9'
// containing the patterns to display each.
const byte digits[10] = {
  // The '|' symbol combines the patterns together by performing a bitwise 'or'
  // Zero has all segments lit except G.
  SEG_F | SEG_E | SEG_D | SEG_C | SEG_B | SEG_A,
  // One has segments B and C lit.
  SEG_B | SEG_C, 
  // Two has A, B, G, E and D lit.
  SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,
  // Three has A, B, G, C and D lit.
  SEG_A | SEG_B | SEG_G | SEG_C | SEG_D,
  // Four has F, G, B and C lit.
  SEG_F | SEG_G | SEG_B | SEG_C,
  // Five has A, G, F, D and C lit.
  SEG_A | SEG_G | SEG_F | SEG_D | SEG_C,
  // Six has all segments lit except B.
  SEG_G | SEG_F | SEG_E | SEG_D | SEG_C | SEG_A,
  // Seven has A, B and C lit.
  SEG_A | SEG_B | SEG_C,
  // Eight has all segments lit.
  SEG_G | SEG_F | SEG_E | SEG_D | SEG_C | SEG_B | SEG_A,
  // Nine has all segments lit except E.
  SEG_G | SEG_F | SEG_D | SEG_C | SEG_B | SEG_A,
};

void setup() {
  // Digital pins 2 to 8 are used to connect to the display.
  for (int i = 2; i <= 8; i = i + 1) {
    pinMode(i, OUTPUT);
  }
  // Digital pin 9 is the button input.
  pinMode(9, INPUT);
}

// Create a place to store the result of the roll.
int dicevalue = 0;

// This function takes a bit pattern as an argument and shows it on the display.
void displayPattern(byte pattern) {
  // Iterate over every segment from A to G.
  for (int segment = 0; segment < 7; segment = segment + 1) {
    // The bit pattern for this segment is:
    byte segpattern = 0b0000001 << segment;
    // The pin for this segment is:
    int pin = 2 + segment;
    // If the pattern we want to display includes includes this segment,
    if ((pattern & segpattern) != 0) {
      // Light it.
      digitalWrite(pin, HIGH);
    }
    else {
      // Otherwise, extinguish it.
      digitalWrite(pin, LOW);
    }
  }  
}

// This function takes a digit as an argument and shows it on the display.
void displayDigit(int value) {
  // Retrieve from the array the pattern to display the current digit.
  byte pattern = digits[value];

  displayPattern(pattern);
}

void loop() {
  displayDigit(dicevalue);
  
  // Is the button being held?
  if (digitalRead(9)) {
    // Roll the dice!
    // In the random() function, the first value can be generated but the second one can't.
    dicevalue = random(1, 7);

    // Delay just a bit, so the number change is visible.
    delay(100);
  }
}
 

After uploading this sketch to the Arduino, press the button a few times. You should see random numbers displayed. The next section will cover the new material in this sketch.

Functions

Functions, such as digitalRead() and millis() that have already been introduced, are sections of code, like setup() and loop(), that can be executed by instructions elsewhere in the program. A section of code might be made into a function to avoid duplicating code (which can lead to errors, if a change made to one copy is not correctly transferred to the duplicates), to isolate sections of the program to test them or because you want to use them in another sketch, or as a way of organising your code. (Most people find that smaller, simpler sections of code are easier to think about.)

‘Calling’, or ‘invoking’ a function is done by using the name of the function, followed by a pair of brackets ‘()’. When such an instruction is encountered, the Arduino temporarily stops executing that instruction, and control jumps to the specified function, proceeding through it top-to-bottom in the usual way. When the function ‘returns’ - either because it reaches the end of the function body, or because it causes a ‘return’ statement to execute - execution resumes from the original instruction. Some functions return values, which mean they can be used in expressions - like digitalRead(). Other functions can take values by including them between the brackets - these values are then available to the function.

Another function that’s available by default in the Arduino IDE is ‘random’. This function returns a (nearly-)random number, between the two values passed into it. For example:

       random(10, 20)

will return a number between 10 and 19, inclusive. Note that the first number can be returned, but the second number will never be.

Each time the sketch restarts, if the same sequence of random() calls are made, the same random values will be generated.

digitalRead() and random(), amongst others, are functions built into the Arduino IDE. To define your own functions, the code is:

       int function_name(byte parameter) {
               …
               return parameter + 17;
       }

‘int’ is the return type of the function - the type of value that will be sent back to the calling instruction. ‘void’ is the type that should be used if the function does not return a value. ‘byte’ is the type of the parameter - there can be any number of parameters, separated by commas.

When a parameter is passed into a function, a copy of the value is made. Changes to the parameter within the function itself won’t affect its value as seen by other code.

For functions that return a value, the ‘return’ statement must include the value to return from the function. If the function does not return a value (its return type is ‘void’) ‘return’ on its own is sufficient. Return statements are frequently the last lines of a function, but can appear elsewhere too.

Finally, functions can only call other functions that precede them in the sketch. If a function has to call another that’s defined later, you can insert a ‘prototype’ of the function further up the sketch: this is the same as the first line of the function - the return type, the name, and any parameters - but instead of the body of the function in brackets, just end it with a semicolon:

    void function_name(int parameter1, byte parameter2);


Libraries

  • Installing Libraries
  • Debounce

TO DO

Things to Try: Dice

  • Make the random number vary between 0 and 9.
  • Simulate a coin toss: When the button’s pressed, randomly display either ‘H’ or ‘t’ on the display.
  • Make a ‘roulette wheel’. Turn on, at random, one of the six outer segments of the display.

Project Idea: Multi-dice

Some games require a variety of dice. The Arduino can be used to replace many of them with a single device.

Connect the display and several switches. Each switch could simulate a different type of dice - for example, heads/tails, 1-4, 1-6, 0-9.

  • How could numbers bigger than 9 be shown by the Arduino?

Sounders

Project: Organ

This project uses the sounder to create a simple - 3-key - keyboard instrument.

An example code file for this project can be download from this link Organ.ino

Organ.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder For example on a windows PC create a folder called "Organ" under C:\Users\<your user name>\Documents\Arduino\Projects\ e.g. C:\Users\<your user name>\Documents\Arduino\Projects\Organ

The project requires three switches with 10K pull-down resistors, plus the sounder.

Organ Stripboard setup

Wire three switches and their pulldown resistors to Arduino digital pins 7, 8 and 9.

Wire one terminal of the sounder (it doesn’t matter which) to the ground rail, and the other terminal to Arduino pin D6.

The sketch for this project - ‘organ’ - is on the next page.

void setup() {
  // The sounder is connected to pin 6.
  pinMode(6, OUTPUT);
  // The organ keys are connected to pins 7, 8 and 9.
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
}


void loop() {
  // Check the first key.
  if (digitalRead(7)) {
    // 3,520 Hz is approximately an 'A'.
    tone(6, 3520);
  }
  // If that's not pressed, try the next key
  else if (digitalRead(8)) {
    // 3,951 Hz is a 'B'.
    tone(6, 3951);
  }
  // If that's not pressed, try the next key
  else if (digitalRead(9)) {
    // 4,186 is a 'C'.
    tone(6, 4186);
  }
  // If no keys are pressed, silence the sounder.
  else {
    noTone(6);
  }
}
 

When you’ve uploaded this sketch, press the buttons. They should correspond to A, B and C notes.

Tone

One of the components in this kit is a ‘piezo’ buzzer. This is a speaker, of sorts, and can be used to generate simple sounds and music. To play a note of a specific frequency, a signal alternating at that frequency must be fed into the buzzer.

The tone() function is used to generate such frequencies on an Arduino output pin:

       tone(pin, frequency)
 

Any output pin can be used, and the frequency parameter should be set to the frequency of sound (in Hertz) that you want to generate. Higher values of frequency result in higher pitched notes. For reference, middle C is approximately 262 Hz, and humans can hear sounds between roughly 20 Hz and 20,000 Hz.

Piezo buzzers are quite limited in the frequencies of sounds they can usefully play. The buzzer in this kit is designed to produce sounds of around 4,000 Hz; the further from this frequency the sound is, the quieter the buzzer will be.

To stop the sound, call

       noTone(pin)

with the same pin argument.

Project Idea: Record/playback

Some digital pianos have a ‘record’ function.

Amend the sketch to have it remember the first three notes played. Add another switch, and when this switch is pressed, play those three notes again.

  • Consider using an array to store the notes; this way, if you want to store a different number of notes, it should be easy to change.
  • One way of doing this is to remember (in a variable) what note was being played the last time through the loop in a variable. If, next time through the loop, a different note is being played, add it to the array.
  • Trickier: Instead of the first three, remember the most recent three.
  • Also trickier: Remember the durations of the notes, and play them for the same duration.
  • Trickier still: Also remember the intervals between notes.

Analog Input

Project: Nightlight

It’s possible to buy lamps that turn on automatically at dusk, and off again at dawn. This project uses an LED rather than a proper lamp, but functions similarly.

An example code file for this project can be download from this link Nightlight.ino

Nightlight.ino

Download the file and save it in to a folder of the same name under your Arduino Projects Folder For example on a windows PC create a folder called "Nightlight" under C:\Users\<your user name>\Documents\Arduino\Projects\ e.g. C:\Users\<your user name>\Documents\Arduino\Projects\Nightlight

It extends the circuit of the first project, ‘Blinky’, so rebuild that project first. Then the adjustable resistor and the light sensor - the LDR or photosensitive resistor - will also be required.

nightlight_bb.png 
Nightlight Stripboard setup

Plug in the adjustable resistor across the central gap of the breadboard. Connect its central terminal - the wiper - to the positive supply rail. Connect one terminal (it doesn’t matter which) of the light sensor to one of the end terminals (again, it doesn’t matter which) of the adjustable resistor, and the other terminal of the light sensor to the ground rail. Finally, connect the terminal shared between the adjustable resistor and the light sensor to the Arduino analog input pin A0.

The code for this project is ‘nightlight’:

void setup() {
  // The light is connected to pin 6.
  pinMode(6, OUTPUT);
  
  // No configuration is necessary for the analog input pins.
}


void loop() {
  // Define the point at which we want the light to switch on
  const int threshold = 512;


  // Read the value from the light sensor.
  // Note that pin 0 here refers to analog pin 0,
  // (A0) not D0.
  int value = analogRead(0);


  // If it's dark, the sensor will have a high resistance,
  // so the analog pin will record a high voltage.
  if (value > threshold) {
    // In that case, turn the nightlight on.
    digitalWrite(6, HIGH);
  }
  else {
    // Otherwise, turn it off.
    digitalWrite(6, LOW);
  }
}
 

Once the sketch is uploaded, experiment with the adjustable resistor. You should find that different settings make the LED turn on and off. Tune it so the LED is ‘just’ off, then cover the light sensor. With luck, the LED will now light when the sensor is in darkness, and extinguish when it’s well lit.

You can also change the threshold in the sketch - it’s currently set halfway between the maximum (1023) and minimum (0), at 512.

The new elements to this sketch are explained in the next section.

ADCs

As previously mentioned, Arduino outputs are digital - either low or high, with no intermediate values. Inputs, however, are slightly different: some Arduino pins can read signals that fall between ground and the supply voltage. These pins are the analog inputs - A0 to A7. They’re attached, internally, to a component called an ‘Analog to Digital Converter’, or ADC.

The function to read an analog voltage from these pins is:

       analogRead(analogPin) 

Note that the analogPin parameter should not include the ‘A’ - that is, to read from pin A3, use a value of 3.

The analogRead function returns a value between 0 and 1,023 - roughly, a 0V input signal will cause analogRead to return 0, and a signal at the supply voltage (5V) will cause analogRead to return 1,023. In other words, each increase of 1 in the returned value corresponds to a 0.0049V increase in the signal on the pin.

The analog inputs of the Arduino are not particularly accurate or stable, and you may see variations of tens of units in the return value from analogRead.

Potential Dividers

A number of analog sensors behave like resistors with a changing value depending on the property being sensed. The light sensor in this kit is a sensor of this type - as the light level on the sensor increases, its resistance decreases.

The Arduino cannot measure resistance directly - the only analog input it can handle is voltage. To convert the resistance of the sensor into a voltage, a type of circuit called a potential divider is used.

To make a potential divider, connect a sensor and an adjustable resistor to the same Arduino analog input; connect the other end of the sensor to ground, and the other end of the adjustable resistor to the supply voltage. The action of this circuit is to make the voltage detected by the Arduino dependant on the ratio of the sensor’s resistance alone to the total resistance of sensor and resistor. When the resistance of the sensor is low (compared to the resistor), the voltage on the input pin will be low (analogRead will return a number close to 0). When the resistance of the sensor and the resistor are equal, the voltage will be half the supply voltage (analogRead will return approximately 512). If the resistance of the sensor is very high compared to the resistor, the voltage will be close to the supply (analogRead will return a value near 1023).

An adjustable resistor is used to ‘tweak’ the output of the divider. If the resistor is adjusted to a level similar to the resistance of the sensor under ‘average’ conditions, the useful range of input is maximized. If the resistor is too small, almost all sensor inputs will cause the input voltage to be high; too great a resistance and the input voltage will usually be low.

Serial I/O

If there’s a problem with an Arduino sketch, it can be useful to see ‘inside’ to work out what’s going wrong. The serial monitor allows the Arduino and the computer you’re editing the sketch on to communicate; allowing you to send messages from the Arduino when a certain section is run, or to show the value of a variable.

Serial communication has two parts: it needs to be started, usually in setup(), with the function:

        Serial.begin(9600) 

The parameter is the speed of communication. Leave this at 9600 for now. Later, to send a message, use one of

        Serial.print(“A text message should go between double quotes”);
              Serial.print(some_variable); 

Messages sent by the Arduino can be read on the computer by using the Serial Monitor window of the IDE, accessed by the Tools -> Serial Monitor option in the menu.

Further Ideas

Project Idea: Cricket

This device is designed to annoy. Monitor the ambient light level. When the room is dark, play noises of random frequency and duration at random intervals. When the room is light (because someone’s looking for the source of the noise), stay silent. Power the device from batteries, and hide it somewhere. Project Idea: Theremin

A theremin is an electronic musical instrument, where the pitch and volume of the sound are varied by the musician moving their hand through the space near the theremin.

A real theremin uses electric fields that interact with the hand as it moves, but we can simulate some of the effect using a light sensor. When the hand is close to the light sensor, making it sense darkness, play a low frequency note. As the hand moves away, and the sensor receives more light, play a higher frequency.

  • Try performing some arithmetic on the value from the ADC to select the frequency to play.
  • You might want to output the value of the ADC through the serial monitor, to ‘tune’ the values used in the instrument.
  • Consider, for the sanity of anyone nearby, muting the sounder when the hand’s not present or too far away.

Project Idea: Simon Says

The Simon Says game is about repeating patterns. The game has a set of LEDs and corresponding buttons. Random sequences of lights are flashed, and the player has to re-enter the same sequence on the buttons. If the player gets the sequence wrong, the game replays it; but if they get it right, the game generates a new, longer, sequence.

  • Consider using an array to store the sequence.

Project Idea: Lights Out

This project is based on a toy from the ‘90s. Several lights and buttons are available; each button is connected to some subset of the lights - pressing it toggles those lights on or off. The object of the game is to press the correct buttons to result in all the lights being turned off at the same time.

  • Binary ‘xor’ operations may be useful.
  • Is it possible to ensure that the starting state of the lights is solvable?
  • Try to generate a solvable starting state at random.
  • Try randomising the connections between buttons and lights every time the game is started.

Project Idea: Drawer Alarm

Build an alarm that’s triggered by light. When the sensor detects that the ambient light level exceeds a threshold, start a countdown. If the right sequence of buttons (the code) is not entered before the countdown expires, sound the alarm.

  • Should the code be built into the sketch? Is there a way to let the user change it easily?
  • Should the alarm silence itself once the drawer is closed?
  • Try counting the number of times the alarm’s been activated since the last time it was correctly ‘disarmed’.

Project Idea: Reaction Timer

In this game, the reactions of the player are timed. When a light or sound goes off, a timer is started; it’s stopped when the player presses the button. Display the result of the timer in a suitable way.

  • Try having two or more different stimuli, each of which requires a different button to be pressed.
  • How about having a ‘round’ of such tests, and a combined score?
  • What’s a sensible way to display the results?