A few simple projects

In this chapter, we will go step-by-step through a few simple projects to demonstrate various ways to use the Arduino.


Blinking LED

Many impressive projects involve LED light effects of some sort. At the heart of it all is the concept of turning an LED on and off in a regular pattern. Doing this is very easy!

To light an LED, all you need is a power source and a resister. We will use the Arduino itself to provide power from one of the pins. Turning this pin on and off (changing the voltage state from from HIGH to LOW) will cause the LED to blink.

As for the resistor, you have a lot of leeway. Using a lower resistor value results in brighter light. The lowest safe resistance for common off-the-shelf LEDs is usually 220 to 330 ohms, which produces the brightest light without damaging the LED or the Arduino.

The following code snippet will make the LED change state every 100 milliseconds, so it will blink with 5 full cycles per second.

// Set to the pin your circuit uses.
const int ledPin = 2;

// nothing to set up
void setup() { }

void loop()
{
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    delay(100);
}

The above code assumes you have connected your LED to pin 2 on the Arduino. You can use a different pin, by changing the ledPin = 2 to the appropriate value.

Each call to delay(100) makes the Arduino pause for 100 milliseconds. Changing this number will make the LED blink faster or slower.

Multiple LEDs

It is safe to power more than one LED using the Arduino board, but each LED should use a separate pin if you plan to light more than one at the same time. For projects needing more than 5 or 10 lights, you should use a separate power source to avoid damaging the Arduino.


Controlling a servo motor

Servo motors are an important part of many robotics projects. A servo can move to arbitrary positions within some range of motion, usually 180 degrees. You might think of them like mechanical elbows.

Most Arduino boards can only supply enough power to move very tiny servos (like the 9g variety for steering small RC vehicles) – and no more than one unless you are careful to move them one at a time. This is handy for prototyping and debugging isolated parts of a larger robot before moving them off to a different circuit with external power.

Arduino includes a library for controlling common servos. Usage is very simple:

  1. Instantiate a Servo object.
  2. Assign the pin number that will send control signals to the servo.
  3. Call methods on the Servo object to set its position.
#include <Servo.h>

// Instantiate a Servo as a variable named myServo.
Servo myServo;

void setup() {
  // Assign pin 9 to the servo.
  myServo.attach(9);
}

void loop() {
  // Move to the 90 degree (middle) position.
  myServo.write(90);
}

For a slightly more complex example, this code will move the servo back and forth in short increments.

#include <Servo.h>

Servo myServo;

void setup() {
  myServo.attach(9);
}

void loop() {
  myServo.write(165);
  delay(250);
  myServo.write(150);
  delay(250);
  myServo.write(15);
  delay(250);

  // Change the angle for multiple steps in a loop
  for (int angle = 90; angle <= 150; angle += 15) {
    myServo.write(angle);
    delay(250);
  }
}

And here is a demonstration video:


Buttons and switches

Most projects involve buttons or switching of some kind. The basic principle is simple: Two wires are disconnected until the switch connects them, closing the circuit. (Sometimes the principle is inverted, where pushing a button opens the circuit until it’s released.)

On the software side, you just check whether the signal pin is in a LOW or HIGH state, and branch accordingly.

const int buttonPin = 2;

void setup() {
  // Prepare the Arduino to read the button as input.
  pinMode(buttonPin, INPUT);
}

void loop() {
  // Get the button state, either HIGH or LOW
  int value = digitalRead(buttonPin);

  if (value == HIGH) {
    // Do something for HIGH
  }
  else {
    // Do something for LOW
  }
}

Debouncing

When switches make or break contact, there can be some noise in the signal received by the Arduino. This causes the state to be misread and the wrong code branch to execute. Dealing with this issue is called debouncing. The most straightforward way to solve debouncing is to read the signal more than once and only act when the readings are consistent with each other. This leads to predictable behavior at the cost of latency (on the order of a few milliseconds).

The implementation is rather simple. It just introduces some boilerplate in the way you handle state.

// Deboucing example
const int buttonPin = 2;

int buttonState;
int lastButtonState = LOW;
long lastDebounceTime = 0;
long debounceDelay = 50;

void setup() {
  pinMode(buttonPin, INPUT);
}

void loop() {
  int value = digitalRead(buttonPin);
  if (value != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (value != buttonState) {
      buttonState = value;
     if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
  digitalWrite(ledPin, ledState);
  lastButtonState = value;
}

Control servo with buttons

Now that we’ve introduced both servos and buttons, let’s see how they can be combined. Debouncing won’t be necessary because the servo is already not very responsive.

Two Buttons and Servo, breadboard view

Here is the full code:

#include <Servo.h>

const int servoPin = 9;
const int leftButtonPin = 2;
const int rightButtonPin = 4;
const int minAngle = 15;
const int midAngle = 90;
const int maxAngle = 165;

Servo servo;

void setup() {
  pinMode(leftButtonPin, INPUT);
  pinMode(rightButtonPin, INPUT);
  servo.attach(servoPin);
}

void loop() {
  int leftButtonState = digitalRead(leftButtonPin);
  int rightButtonState = digitalRead(rightButtonPin);

  if (rightButtonState == HIGH) {
    servo.write(maxAngle);
  }
  else if (leftButtonState == HIGH) {
    servo.write(minAngle);
  }
  else {
    servo.write(midAngle);
  }

  delay(100);
}

Transistors

Transistors are just about everywhere in electronics. They are used in digital switches, amplifiers, voltage regulators, and many other simple components that work together in complex digital circuits. Two types you’re likely to use are the bipolar junction transistor (BJT) and the field effect transistor (FET).

Both types of transistor have three pins. The pins on the bipolar junction transistor are called the emitter, collector, and base. On the field effect transistor, the pins are called the source, drain, and gate.

In both cases, the basic principle is that voltage applied to one pin (the base/gate) determines whether current can flow across the two other pins. In this way, the transistor acts as a switch based on high and low voltages instead of physically flipping a switch or pressing a button.

Example: AND logic gate

Let’s look at a circuit that uses transistors. This circuit will implement the logical AND operation using two buttons for input and one LED for output. The LED is off by default. If you press button 1 or button 2, the LED remains off. But if you press both button 1 and button 2, the LED will light up. Thus, the AND gate.

AND gate schematic view
AND gate breadboard view


Shift Registers

A shift register is a simple memory device that allows data to be “shifted” bit-by-bit. A common shift register for Arduino projects is the 74HC595. One place you might use this device is to control up to eight LEDs using only three Arduino pins instead of a separate pin for each LED. It is also useful for controlling a 7-segment LCD display or various other components.

Here is an example implementation controlling eight LEDs:

AND gate schematic view
AND gate breadboard view

/**
 * Example using a shift register to control 8 LEDs.
 */
const int dataPin = 4;
const int latchPin = 5;
const int clockPin = 6;

byte bits = 0;

void setup() {
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

void loop() {
  bits = 0;
  updateShiftRegister();
  delay(500);
  for (int i = 0; i < 8; ++i) {
    bitSet(bits, i);
    updateShiftRegister();
    delay(500);
  }
}

void updateShiftRegister() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, bits);
  digitalWrite(latchPin, HIGH);
}

And a demonstration video (warning: music begins to play after a few seconds):


 MENU