Maker.io main logo

LilyPad ProtoSnap Plus Activity Guide

2018-02-14 | By SparkFun Electronics

License: See Original Project

Courtesy of Sparkfun

Introduction

This guide will get you started with some introductory programming activities exploring each of the LilyPad pieces on the LilyPad ProtoSnap Plus. If you’ve never used Arduino to program before, this guide will walk you through the basics with example code to upload and explore.

You can follow along with this guide with both the LilyPad ProtoSnap Plus standalone board or the LilyPad ProtoSnap Plus Kit. This guide will not cover construction of a project with conductive thread, so either product will work for you.

LilyPad ProtoSnap Plus

LilyPad ProtoSnap Plus

LilyPad ProtoSnap Plus Kit

LilyPad ProtoSnap Plus Kit

Required Materials

If using the LilyPad ProtoSnap Plus standalone board, you will need to supply your own micro-B USB cable to upload code. The LilyPad ProtoSnap Plus Kit includes one in the box.

USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

USB micro-B Cable - 6"

 USB micro-B Cable - 6"

Suggested Reading

What is an Arduino?

What is an Arduino?
What is this 'Arduino' thing anyway?

Getting Started with LilyPad

Getting Started with LilyPad
An introduction to the LilyPad ecosystem - a set of sewable electronic pieces designed to help you build soft, sewable, interactive e-textile projects.

Before You Begin

Don’t snap apart your LilyPad ProtoSnap Plus

To follow along with this guide, please install Arduino support for the LilyPad USB Plus by following the instructions in the LilyPad ProtoSnap Plus Hookup Guide.

LilyPad ProtoSnap Plus Hookup Guide

LilyPad ProtoSnap Plus Hookup Guide
October 5, 2017
The LilyPad ProtoSnap Plus is a sewable electronics prototyping board that you can use to learn circuits and programming with Arduino, then break apart to make an interactive fabric or wearable project.

Before you begin

Once you’ve installed the LilyPad USB Plus extensions to Arduino, you’re ready to start programming the board!

Note that you won’t have to install the extensions again, but you will need to perform the below three steps every time you want to program the board. These three steps are:

Connect the LilyPad ProtoSnap Plus

Let’s go over the three steps in detail:

1. Connect the LilyPad ProtoSnap Plus to Your Computer

Place the LilyPad ProtoSnap Plus on a clean, non-metal work surface. Connect the LilyPad ProtoSnap Plus to a USB port on your computer using a micro-B USB cable. The cable can only be inserted one way, and should snap in securely.

USB Cable

Tip

Connector to Computer

Slide the switch on the LilyPad USB Plus to the ON position. You will not be able to upload code to the board if it is set to the OFF position.

Turn LilyPad ProtoSnap Plus ON

2. Select LilyPad USB Plus from the Board Menu

If the Arduino board support was installed correctly, "LilyPad USB Plus" option will be available in the Tools > Board list under the SparkFun AVR Boards group. Open the menu and select LilyPad USB Plus. Depending on how many boards are already in the list, you may need to scroll down a bit to get to it. A dot (Windows) or check mark (Mac) will show next to the board in the menu when it is selected, and it will show next to Board in the Tools menu.

Important

Select Board Definition

Troubleshooting

3. Select LilyPad USB Plus from the Port Menu

Arduino needs to know which port your LilyPad USB Plus is attached to so it can program it. Whenever you plug a USB device into your computer, your computer will assign it a port number. This used to be difficult to determine, but this board has a handy feature that identifies itself. Go to the Tools > Port menu, and select the port that has "LilyPad USB Plus" next to it.

On Windows ports are listed as COM##; on a Mac or Linux machine they will be "/dev/cu.usbmodem####". Your screen may look different than the image below, depending on what operating system you are using, but all should show LilyPad USB Plus next to the port address.

COM Port

Troubleshooting

Hardware Overview

The LilyPad ProtoSnap Plus features twelve LilyPad components connected to a LilyPad microcontroller by conductive pathways called traces. For reference, each component on the ProtoSnap has a nearby label with its name and the number of the LilyPad USB Plus sew tab it is connected to. For more information on features and technical specs, please refer to the LilyPad ProtoSnap Plus Hookup Guide.

LilyPad Protosnap Plus parts Highlighted

LilyPad USB Plus

The LilyPad USB Plus is an Arduino-compatible microcontroller similar to the LilyPad Arduino USB - ATmega32U4 Board but with some additional features and three additional sew tabs. It is currently only available on the LilyPad ProtoSnap Plus.

Additional SMD LEDs

Features:

  • USB port for connecting to a computer.
  • Two sets of power (+) and ground (-) sew tabs.
  • Built-in RGB LED attached to pins 12 (R), 13 (G), and 14 (B).
  • A row of six white LEDs attached to pins 15-20.
  • Charging circuit for single-cell (3.7V) Lithium-Polymer batteries.

What is a Program?

Programs are sets of instructions that tell a computer to do something, (also called "code" or a "sketch" in Arduino) . This could be blinking LEDs, playing sounds, making decisions based on input from sensors, or a combination of all those things.

When the computer runs a program, it will start at the first instruction, carry it out, and move on to the next one. These instructions come from a specific list of words that the computer knows. If you type in a word that the computer doesn’t know (or more likely, you misspell a word that the computer should know), you’ll get an error when you try to run your program. Don’t feel bad, this happens to everyone and is a normal part of writing programs, and we’ll provide you with some troubleshooting tips as you follow along with the activities in this guide.

In the Arduino system, you’ll write programs on your computer in a free application called the Arduino IDE ("IDE" stands for Integrated Development Environment). This is a specialized text editor with extra buttons to check and send your code to the LilyPad USB Plus at the center of your ProtoSnap board. There are lots of programming examples built into the Arduino IDE, we’ll be using some of them in these activities.

What is a Microcontroller?

The LilyPad USB Plus at the center of your ProtoSnap board contains a tiny computer called a microcontroller. It can’t do all the things that a larger computer does, but it’s very good at running programs that control simple hardware like LEDs.

Unlike larger computers, microcontrollers don’t have keyboards and screens for input and output. Most of your input and output will happen through sew tabs; the silver petals with holes in them evenly spaced around the outer edge of all LilyPad boards. Your program can control the sew tabs. It can use them for output by turning them on and off (internally connecting them to voltage or not). It can also use them for input, measuring any voltage coming from other components. It can use this information to read buttons, switches, and various sensors, and use that information to make decisions. (We’ll explore this in future activities.)

If you look closely at the sew tabs, you’ll see that every sew tab has a label next to it. These are the names of the sew tabs, which you’ll need to know to control them from your program. You might have noticed that some of the sew tabs have an "A" as part of the label, and some include a tilde or squiggle "~". These symbols describe special features that some of the sew tabs have. We’ll tell you about these special features in future activities.

Some of the sew tabs have a "+" or "-" next to them. You can use these sew tabs to provide power and ground to LilyPad boards connected to the LilyPad USB Plus.

Sew Tabs and Pins

Read more about the LilyPad USB Plus’s individual sew tabs and connections (including a chart) in the LilyPad ProtoSnap Plus Hookup Guide.

1: Blinking LEDs

In this activity, you’ll run your first program on the LilyPad USB Plus at the center of the LilyPad ProtoSnap Plus. It will "just" make an LED blink, but there’s a lot going on even in this simple task. Let’s get started!

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • Yellow LilyPad LEDs

Activity 1: Blinking LEDs

What is an LED

New Concepts Introduced in This Activity

Exploring Your First Program

We’ve provided a pre-written example program that we’ll load into the Arduino IDE.

Basic Program Structure

We’ll walk you through the example program, explain how it’s constructed, and go over the two basic functions every program needs; setup() and loop().

Lighting Up LEDs

We’ll show you how to light up and blink LEDs using the pinMode(), digitalWrite(), and delay() commands.

Modifying Code

A great way to learn to program is to make small changes to a program that someone else has written, and see what happens. We’ll suggest places to try this, and give you a few challenges at the end of each activity.

Example Code

For each of these activities, we’ll start with a pre-written program that you’ll explore and modify. To load the first program, start up the Arduino IDE and go to:

File > Examples > LilyPadProtoSnapPlus > LPP_01_Blink

Select Example

Your menu of options may look different depending on what boards you have installed in Arduino.
You may have to scroll down to see the LilyPad ProtoSnap Plus examples option.

if you don

You can also copy and paste the following code into the Arduino IDE (be sure to delete any code already in the window first).

Copy Code
/*
LilyPad ProtoSnap Plus Activity 1: Blinking LEDs
SparkFun Electronics
https://www.sparkfun.com/products/14346

Blink the pair of yellow LEDs attached to sew tab A5 on the LilyPad USB Plus

Follow the tutorial at:       
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#1-blinking-leds

This example is based on: Blink by Scott Fitzgerald
https://www.arduino.cc/en/Tutorial/Blink

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// The setup function runs once when the microcontroller starts up or resets:

void setup()
{
  // Before you use a sew tab (pin), you must set it to be either an input or output:

  pinMode(A5, OUTPUT);    // Set pin A5 to be an output
}

// After the setup function runs, the loop function runs over and over forever:

void loop()
{
  digitalWrite(A5, HIGH); // Give pin A5 a HIGH voltage level (on), which lights up the LED
  delay(1000);            // Pause for 1000 milliseconds (one second), the LED stays on
  digitalWrite(A5, LOW);  // Give pin A5 a LOW voltage level (off), which turns off the LED
  delay(1000);            // Pause for 1000 milliseconds (one second), the LED stays off
}

Once you’ve connected your LilyPad ProtoSnap Plus to your computer as shown in the Before You Begin section, and loaded or copied the example program into the Arduino IDE, click the upload button (the round button with the right arrow at the top of the window) and see what happens!

Upload Button

What You Should See

Once the code has uploaded, the pair of yellow LEDs on the ProtoSnap Plus will blink once per second

 

Why do two LEDs light up

Understanding Your Program

In this section, we’ll explain what this program does. For this first activity we’ll be pretty thorough. As we progress through future activities, we’ll just highlight new concepts as we introduce them.

Program Overview

  1. Turn the LED on by sending power to Pin A5.

  2. Wait 1 second.

  3. Turn the LED off by cutting power to Pin A5.

  4. Wait 1 second.

  5. Repeat.

Comments

At the top of the program, you’ll find text describing what the program does, who wrote it, etc. These are called comments. They are there solely for your information and are ignored by the microcontroller. Comments in the Arduino IDE will show up as gray text.

Example Comments

We use special symbols to tell the microcontroller to ignore comments.

  • If you want to write a block of text on multiple lines as we’ve done above, the microcontroller will ignore any text between /* and */.
  • If you want to put a comment on a single line, the microcontroller will ignore any text after two slashes //.

adding comments

Setup() Function

The next section of our program contains a function. A function is a named block of code that does a defined task or set of tasks. When a function is run, all of the code contained between the curly brackets { and } is run. Arduino has two essential functions that are required for every program to run properly: they are setup() and loop(). Arduino programs can use many functions (both built-in and user defined), but they must at least have those two. These and other control structure functions built into the Arduino software will display in green text. Let’s explore the setup function.

Setup

When the microcontroller starts up or is reset, the setup() function runs once. As you may have guessed from the name, the setup() function is typically used to "set up" the hardware so that it operates properly during the rest of the program.

Statements and Commands

Inside functions, we put statements. A statement is a single instruction to the microcontroller. Statements always end with semicolons ;. It’s a common error to forget the semicolon, so if you get an error when uploading your code, double-check that every statement ends with ;.

Most statements will include commands. Commands are specific functions you can use to complete common tasks in Arduino. There are many built-in commands that can be used for all sorts of things - input and output, math, decision making, etc. These commands display in orange text. We’ll cover many useful commands in this guide.

In this program, we’ve put one command in the startup function, called pinMode(). Note the unusual capitalization, called "camel case". Commands are case-sensitive, so pay special attention to this.

The pinMode() command, as you may have guessed, sets the mode of a pin. Pins are the metal legs on microcontroller chips that are attached to the sew tabs on your LilyPad board. Pins can be configured as inputs or outputs. In this program, we’re going to use pin A5 to control an LED, which is a component sending information (light) to the world, so we’ll make it an OUTPUT.

Commands take various numbers of parameters, which are the information the command needs from you. Parameters go inside parentheses () after a command, and are separated by commas if there are multiple. The pinMode command takes two parameters; the number of the pin, and whether you want it to be an INPUT or an OUTPUT. Here, we’re setting pin A5 to be an OUTPUT.

reserved words in Arduino

Loop() Function

The second essential function needed to run an Arduino program is called loop(). After the setup() function runs once, the loop() function runs over and over, forever (or until you turn off or reset the microcontroller).

A loop() function usually contains the main tasks and behaviors of your program; the things you want it to do repeatedly. You can use this to your advantage; for example, in this program we want to blink an LED continuously. Because the loop() function repeats, we only need to write the code to blink it once, and the loop() function will make it blink over and over.

loop

The first thing we’ll do is turn our LED on. To do that, we’ll use the digitalWrite() command.

Like pinMode(), digitalWrite() takes two parameters: the pin we want to control, and whether we want to make the pin a HIGH voltage level (on), or a LOW voltage level (off). We want to turn the LED on, so we’ll set pin A5 to HIGH.

Because the microcontroller runs so fast, if we immediately turned the LED off, you’d never notice it. So we’ll slow things down with a command called delay() that does nothing but pause the program for a set amount of time.

The delay() function takes one parameter, the number of milliseconds to wait. There are 1000 milliseconds in one second, so here we’re pausing for one second. If you make this value smaller, the LED will blink faster, and vice-versa. Try it!

After we’ve waited one second, we’ll turn the LED off with a second digitalWrite(), this time setting the pin to LOW to turn the LED off.

Finally, we’ll add a second delay(). This one pauses while the LED is off, finishing the complete on-off "blink" cycle. If we didn’t have the second delay(), the LED would immediately turn on again when loop() starts over. This happens so quickly you wouldn’t notice it being off.

Coding Challenges

  • Try changing the number inside delay() - Can you make the LED blink faster or slower?
  • Changing the pin number inside the digitalWrite() function will change the sew tab being controlled by the code. Can you light up one of the other LilyPad LEDs on the ProtoSnap by changing this number? Hint: don’t forget to set that LED to be an OUTPUT first.
  • Can you modify the code to blink multiple LEDs?

2: Basic Color Mixing

Now that you know how to turn LEDs on and off, let’s try controlling a colorful LED. The LilyPad USB Plus at the center of the LilyPad ProtoSnap Plus has a built-in RGB (Red Green Blue) LED that can be controlled in your code just like the LED pairs from the last activity. Unlike the LEDs used in the Blink example, this LED is special - it is actually 3 small LEDs in one package - a red, green, and blue. You can access them in code to a variety of color combinations.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad USB Plus’s built-in RGB LED
  • Red LilyPad LEDs
  • Green LilyPad LEDs
  • Blue LilyPad LEDs

Activity 2: Basic Color Mixing

What is an RGB LED

New Concepts Introduced in This Activity

Declaring and Using Variables

A variable is a placeholder for values in your code, typically a descriptive word. While we could continue to write the sew tab or pin number we are referencing in our programs, a variable can make it easier to read, update, and share information within your code. Every time you want to create and use a variable, you must declare it - tell the program what type of data it is storing.

creating and naming variables

Color Mixing

In order to create colors with the RGB LED, you’ll have to set each of the LEDs within it individually. The combination of light from the LEDs mixed together creates new colors. The example code will display color in the RGB LED as well as lighting up the individual colored LED pairs at the bottom of the ProtoSnap Plus to to make it easier for you to track what is happening within the RGB LED.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_02_BasicColorMixing

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 2: Basic Color Mixing
SparkFun Electronics
https://www.sparkfun.com/products/14346

Create primary and secondary colors on the built-in RGB (Red/Green/Blue) LED

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#2-basic-color-mixing

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// The LilyPad USB Plus has a built-in RGB (Red / Green / Blue) LED.
// In this activity we'll use digitalWrite to tun the three LEDs on and off
// in various combinations to create eight primary and secondary colors.

// Create integer variables for our LED pins:

// The built-in LED:

int RGB_red = 12;
int RGB_green = 13;
int RGB_blue = 14;

// The colored LEDs along the bottom edge of the board:

int redLED = 6;
int greenLED = A7;
int blueLED = A8;

void setup()
{
  // Make all of our LED pins outputs:

  pinMode(RGB_red, OUTPUT);
  pinMode(RGB_green, OUTPUT);
  pinMode(RGB_blue, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);
}

void loop()
{

  // This code will step through the six primary and secondary colors, plus white and black.

  // For each of these colors, we'll turn the necessary RGB LEDs on or off.
  // We'll also turn on the same LEDs on the bottom edge, so you can see what's being mixed.

  // Black (all LEDs off)

  // RGB LEDs:

  digitalWrite(RGB_red, LOW);
  digitalWrite(RGB_green, LOW);
  digitalWrite(RGB_blue, LOW);

  // Bottom-edge LEDs

  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, LOW);
  digitalWrite(blueLED, LOW);
  delay(1000);

  // Red (red LED on)

  digitalWrite(RGB_red, HIGH);
  digitalWrite(RGB_green, LOW);
  digitalWrite(RGB_blue, LOW);

  digitalWrite(redLED, HIGH);
  digitalWrite(greenLED, LOW);
  digitalWrite(blueLED, LOW);
  delay(1000);

  // Yellow (red and green LEDs on)

  digitalWrite(RGB_red, HIGH);
  digitalWrite(RGB_green, HIGH);
  digitalWrite(RGB_blue, LOW);

  digitalWrite(redLED, HIGH);
  digitalWrite(greenLED, HIGH);
  digitalWrite(blueLED, LOW);
  delay(1000);

  // Green (green LED on)

  digitalWrite(RGB_red, LOW);
  digitalWrite(RGB_green, HIGH);
  digitalWrite(RGB_blue, LOW);

  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, HIGH);
  digitalWrite(blueLED, LOW);
  delay(1000);

  // Cyan (blue and green LEDs on)

  digitalWrite(RGB_red, LOW);
  digitalWrite(RGB_green, HIGH);
  digitalWrite(RGB_blue, HIGH);

  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, HIGH);
  digitalWrite(blueLED, HIGH);
  delay(1000);

  // Blue (blue LED on)

  digitalWrite(RGB_red, LOW);
  digitalWrite(RGB_green, LOW);
  digitalWrite(RGB_blue, HIGH);

  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, LOW);
  digitalWrite(blueLED, HIGH);
  delay(1000);

  // Magenta (red and blue LEDs on)

  digitalWrite(RGB_red, HIGH);
  digitalWrite(RGB_green, LOW);
  digitalWrite(RGB_blue, HIGH);

  digitalWrite(redLED, HIGH);
  digitalWrite(greenLED, LOW);
  digitalWrite(blueLED, HIGH);
  delay(1000);

  // White (all LEDs on)

  digitalWrite(RGB_red, HIGH);
  digitalWrite(RGB_green, HIGH);
  digitalWrite(RGB_blue, HIGH);

  digitalWrite(redLED, HIGH);
  digitalWrite(greenLED, HIGH);
  digitalWrite(blueLED, HIGH);
  delay(1000);
}

 What You Should See

After uploading your code, the RGB LED will step through a color sequence beginning with all LEDs off (‘black’), red, yellow, green, cyan, blue, magenta, and white. Once the color sequence is complete, the program will loop back to the beginning and repeat the sequence. To better showcase these color combinations, the code also turns on the colored LED pairs at the bottom of the LilyPad ProtoSnap Plus to coordinate with the RGB channels.

 

 

LEDs too bright

Turning on different combinations of three LEDs inside the RGB LED will create new colors. Combining the primary colors of light (red, green, and blue) gives different results than combining pigments in paints or inks. Turning on all three colors will create white - this is called additive color. Take a look a the graphic below to see what colors combine to create primary and secondary colors with light.

Venn Diagram for Additive Colors

Understanding Your Program

Program Overview

1.Turn all of the LEDs off by cutting power to the pins associated with their variables (LOW).
Wait 1 second.
2.Display red:
R: ON, G: OFF, B: OFF
Wait 1 second.
3.Display yellow:
R: ON, G: ON, B: OFF
Wait 1 second.
4.Display green:
R: OFF, G: ON, B: OFF
Wait 1 second.
5.Display cyan:
R: OFF, G: ON, B: ON
Wait 1 second,
6.Display blue:
R: OFF, G: OFF, B: ON
Wait 1 second.
7.Display magenta:
R: ON, G: OFF, B: ON
Wait 1 second.
8.Display white:
R: ON, G: ON, B: ON
Wait 1 second.
9.Repeat.

Code to Note

Code to note

Code/Description

Coding Challenges

  • Can you create a new color sequence on the RGB LED using a new order of colors being displayed?
  • Try changing the delay to create a faster or slower color sequence.
  • Create a new variable called yellowLED and assign it to the yellow LEDs on the ProtoSnap Plus. Can you make the yellow LEDs light up each time the RGB LED creates yellow? Remember to set the pinMode() for this LED to OUTPUT in the setup().
  • Create a variable called delayTime at the top of your code near the other variable declarations. Then replace the 1000 in each delay() function with this variable. This way you can easily set the delay between color steps once at the beginning of your code instead of copying and pasting in each part of the sequence.

3: Custom Color Mixing

In this program, you will continue mixing colors with the RGB LED, but use a new function to change the brightness of each channel in relation to each other. Adjusting the brightness of the red, green, and blue LEDs within the RGB will allow you to create a new range of values and color combinations.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad USB Plus’s built-in RGB LED
  • Red LilyPad LEDs
  • Green LilyPad LEDs
  • Blue LilyPad LEDs

Activity 3: Custom Color Mixing

New Concepts Introduced in This Activity

Analog Output (Pulse Width Modulation)

Up until this point, you have been controlling LEDs by setting them to one of two states: HIGH (ON) or LOW (OFF). This is great for blinking, but what about adjusting the brightness of your LEDs? This is where analog output comes in handy. Your LilyPad USB Plus can mimic a range of brightness on the LEDs by using pulse width modulation. The microcontroller on the LilyPad USB Plus can switch voltage to the sew tabs on and off so quickly that it appears to your eyes as if more or less voltage is being provided to an LED. For example, by changing the percent of time that a pin is on, from 0 percent (always off) to 100 percent (always on), you can create the appearance of a range of brightnesses. This percentage is called a duty cycle.

Activity 4 Fading LEDs

Color Mixing Continued

In the last example, you created basic primary and secondary colors by turning the red, green, and blue channels on or off with different combinations. In this activity, youll create tertiary colors by combining the three color channels at 50% brightness levels. There are actually millions of color combinations available using RGB LEDs once you begin experimenting with adjusting the brightness/saturation of each. This example will cover a set of twelve tertiary colors.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_03_CustomColorMixing

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 3: Custom Color Mixing
SparkFun Electronics
https://www.sparkfun.com/products/14346

Expand your color options using analogWrite and the RGB (Red Green Blue) LED

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#3-custom-color-mixing

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// The LilyPad USB Plus has a built-in RGB (Red / Green / Blue) LED.
// In this activity we'll use analogWrite to control the brightness of the three LEDs.
// Here we'll create a rainbow of tertiary colors by adding a 50%-brightness option.

// Create integer variables for our LED pins:

// The built-in LED:

int RGB_red = 12;
int RGB_green = 13;
int RGB_blue = 14;

// The colored LEDs along the bottom edge of the board:

int redLED = 6;
int greenLED = A7;
int blueLED = A8;

void setup() {

// Make all of our LED pins outputs:

  pinMode(RGB_red, OUTPUT);
  pinMode(RGB_green, OUTPUT);
  pinMode(RGB_blue, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);
}

void loop()
{
  // In this code we'll step through twelve rainbow colors (primary, secondary, tertiary).

  // Unlike digitalWrite, which can be only HIGH (on) or LOW (off),
  // analogWrite lets you smoothly change the brightness from 0 (off) to 255 (fully on).
  // When analogWrite is used with the RGB LED, you can create millions of colors!

  // In the analogWrite functions:
  // 0 is off
  // 128 is halfway on (used for the tertiary colors)
  // 255 is full brigthness.

  // Red

  analogWrite(RGB_red,255);
  analogWrite(RGB_green,0);
  analogWrite(RGB_blue,0);

  analogWrite(redLED,255);
  analogWrite(greenLED,0);
  analogWrite(blueLED,0);
  delay(1000);

  // Orange

  analogWrite(RGB_red,255);
  analogWrite(RGB_green,128);
  analogWrite(RGB_blue,0);

  analogWrite(redLED,255);
  analogWrite(greenLED,128);
  analogWrite(blueLED,0);
  delay(1000);

  // Yellow

  analogWrite(RGB_red,255);
  analogWrite(RGB_green,255);
  analogWrite(RGB_blue,0);

  analogWrite(redLED,255);
  analogWrite(greenLED,255);
  analogWrite(blueLED,0);
  delay(1000);

  // Chartruese

  analogWrite(RGB_red,128);
  analogWrite(RGB_green,255);
  analogWrite(RGB_blue,0);

  analogWrite(redLED,128);
  analogWrite(greenLED,255);
  analogWrite(blueLED,0);
  delay(1000);

  // Green

  analogWrite(RGB_red,0);
  analogWrite(RGB_green,255);
  analogWrite(RGB_blue,0);

  analogWrite(redLED,0);
  analogWrite(greenLED,255);
  analogWrite(blueLED,0);
  delay(1000);

  // Spring Green

  analogWrite(RGB_red,0);
  analogWrite(RGB_green,255);
  analogWrite(RGB_blue,128);

  analogWrite(redLED,0);
  analogWrite(greenLED,255);
  analogWrite(blueLED,128);
  delay(1000);

  // Cyan

  analogWrite(RGB_red,0);
  analogWrite(RGB_green,255);
  analogWrite(RGB_blue,255);

  analogWrite(redLED,0);
  analogWrite(greenLED,255);
  analogWrite(blueLED,255);
  delay(1000);

  // Azure

  analogWrite(RGB_red,0);
  analogWrite(RGB_green,128);
  analogWrite(RGB_blue,255);

  analogWrite(redLED,0);
  analogWrite(greenLED,128);
  analogWrite(blueLED,255);
  delay(1000);

  // Blue

  analogWrite(RGB_red,0);
  analogWrite(RGB_green,0);
  analogWrite(RGB_blue,255);

  analogWrite(redLED,0);
  analogWrite(greenLED,0);
  analogWrite(blueLED,255);
  delay(1000);

  // Violet

  analogWrite(RGB_red,128);
  analogWrite(RGB_green,0);
  analogWrite(RGB_blue,255);

  analogWrite(redLED,128);
  analogWrite(greenLED,0);
  analogWrite(blueLED,255);
  delay(1000);

  // Magenta

  analogWrite(RGB_red,255);
  analogWrite(RGB_green,0);
  analogWrite(RGB_blue,255);

  analogWrite(redLED,255);
  analogWrite(greenLED,0);
  analogWrite(blueLED,255);
  delay(1000);

  // Rose

  analogWrite(RGB_red,255);
  analogWrite(RGB_green,0);
  analogWrite(RGB_blue,128);

  analogWrite(redLED,255);
  analogWrite(greenLED,0);
  analogWrite(blueLED,128);
  delay(1000);

}

 What You Should See

After uploading your code the RGB LED will step through a rainbow sequence of red, orange, yellow, chartruese, green, spring green, cyan, azure, blue, violet, magenta, and rose, repeatedly. To better showcase these color combinations, the code also turns on the colored LED pairs at the bottom of the LilyPad ProtoSnap Plus to coordinate with the RGB channels.

 

 

LEDs too bright

By adjusting the brightness of each LED in the RGB LED individually, we open up a much wider range of color options to display than the previous activity. In fact, there are many more combinations than we show in the example code. The image below shows a chart of the tertiary colors the example program creates by stepping down the LEDs to half brightness, creating a rainbow with more color transitions than the Basic Color Mixing example. By using analog output to adjust the brightness of each color channel individually, the RGB LED can display almost any color you can choose from a color picker - if you are familiar with RGB sliders in a graphics program, you’ll recognize the 0-255 values used in this code.

Color Picker

Understanding Your Program

Program Overview

1.Display red:
R: 100%, G: 0%, B: 0%
Wait 1 second.
2.Display orange:
R: 100%, G: 50%, B: 0%
Wait 1 second.
3.Display yellow:
R: 100%, G: 100%, B: 0%
Wait 1 second.
4.Display chartruese:
R: 50%, G: 100%, B: 0%
Wait 1 second.
5.Display green:
R: 0%, G: 100%, B: 0%
Wait 1 second.
6.Display spring green:
R: 0%, G: 100%, B: 50%
Wait 1 second.
7.Display cyan:
R: 0%, G: 100%, B: 100%
Wait 1 second.
8.Display azure:
R: 0%, G: 50%, B: 100%
Wait 1 second.
9.Display blue:
R: 0%, G: 0%, B: 100%
Wait 1 second.
10.Display violet:
R: 50%, G: 0%, B: 100%
Wait 1 second.
11.Display magenta:
R: 100%, G: 0%, B: 100%
Wait 1 second.
12.Display rose:
R: 100%, G: 0%, B: 50%
Wait 1 second.
13.Repeat.

Code to Note

Code/Description

Coding Challenges

  • Try using a color picker to find the R, G, and B values for an interesting color and use that in your program.
  • Try creating your own rainbow light patterns using different values for the color mixes.

4: Fading LEDs

So far in these activities, we’ve controlled the brightness of LEDs manually. In this activity, you’ll start letting the computer do the hard work. By using iteration (counting over a range of numbers), you can fade LEDs smoothly from off to on, a very nice effect you can use in your own projects.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • Yellow LilyPad LEDs
  • Red LilyPad LEDs

Activity 4: Fading LEDs

New Concepts Introduced in This Activity

Iteration Using For-Loops

We’ve already seen that the loop() function repeats forever. But there are many occasions in programming where you’ll want the microcontroller to do something a certain number of times, or count up or down between two numbers. The for() loop is perfect for this.

In this example, we will use the for() loop to slowly increment the brightness of a LED from fully off to fully on, then do the same thing in reverse to turn it off. This creates a "fading" or "breathing" pattern that is great for art projects.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_04_Fading

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 4: Fading LEDs
SparkFun Electronics
https://www.sparkfun.com/products/14346

Use for-loops to smoothly vary the brightness of LEDs

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#4-fading-leds

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// In the previous activity we showed you how to manually change the brightness of a LED.
// In this activity we'll show you how to program the computer to do all the work.

// Create integer variables for the LED pins we'll be using:

int redLED = 6;
int yellowLED = 5;

void setup()
{
  // Set the LED pins to be outputs:

  pinMode(redLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
}

void loop()
{
  // The two "for loops" below will make a LED fade on and off in a "breathing" pattern.

  // Create a new integer variable called brightness:

  int brightness;

  // Now we'll have the program automatically change the value of brightness
  // using a command called "for".

  // for is like a tiny version of loop. The for command has several parts:
  // 1. something to do before starting (brightness = 0)
  // 2. a test to decide whether to keep going (brightness <= 255)
  // 3. a block of commands to run (everything within the {} below the for)
  // 4. a command to run before doing it again (brightness = brightness + 1)

  // Here's a for command which will start brightness at 0, check to see if it's less than
  // or equal to 255, run the commands after it, then add one to brightness and start over:

  for (brightness = 0; brightness <= 255; brightness = brightness + 1)
  {
    // Within the loop, we'll use brightnes variable to control the brigthness of the LEDs:

    analogWrite(redLED, brightness);
    analogWrite(yellowLED, brightness);

    // NOTE that not all pins work with analogWrite!
    // The ones with a "~" in front of them will change brightness,
    // the others will only turn on if brightness > 128.
    // Both types are used above, run the code and note the difference between them.

    // The delay command controls the speed - if you make the delay larger,
    // it will slow down the loop. Smaller, and it will run faster:

    delay(5);
  }

  // What if we want the LED to start at full brightness and fade to black?
  // We can easily set up the for loop to run in reverse:

  for (brightness = 255; brightness >= 0; brightness = brightness - 1)
  {
    analogWrite(redLED, brightness);
    analogWrite(yellowLED, brightness);
    delay(5);
  }
}

What You Should See

Once you upload the program, the yellow and red LEDs on the ProtoSnap will light up. The red leds on ~6 will fade smoothly on and off, while the yellow LEDs on A5 will blink.

If you look at the code, both pins should be fading. This illustrates the difference between the "~" sew tabs which can handle pulse-width modulation, and those that can’t.

 

Understanding Your Program

Program Overview

1.Set up the pins we’ll be using
2.Create a for() loop that makes a variable iterate from 0 to 255
3.Use that variable to fade the LEDs from off to on
4.Create a for() loop from makes a variable iterate from 255 to 0
5.Use that variable to fade the LEDs from on to off
6.Repeat

Code to Note

Iteration, or making variables change over time, is a very powerful tool in programming. Here we’re using it to smoothly change the brightness of an LED using the analogWrite() command, but you can use it anywhere you want to do something a certain number of times, or you want to change a variable from one value to another in even steps.

Unlike other commands, the for() loop is set up using three statements, which we’ll cover below. You’ll use the same pattern often in your own programming.

Code/Description

Code/Description

Coding Challenges

  • Change the delay() values to make the "pulsing" pattern go faster or slower.
  • Try modifying the code to make other LEDs pulse.
  • Can you create a "heartbeat" pattern? (Two on-off pulses then a rest.)

5: Play a Tune

The microcontroller on the LilyPad USB Plus can turn its outputs on and off very quickly. If you carefully choose the frequency at which you’re turning an output on and off, and send that signal to the buzzer on the LilyPad ProtoSnap Plus, you can create tones and simple musical tunes.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad Buzzer

Activity 5: Play a Tune

What is a buzzer

New Concepts Introduced in This Activity

Making Tones

You’ll use the tone() and noTone() commands to drive the buzzer at specific frequencies.

A tone’s pitch is what we perceive when we think of a note as being very high (screams, forks scratching plates, etc.) versus very low (like earth-rumbling bass). The pitch of a tone is very closely related to the frequency played through a speaker. If we toggle a pin from HIGH-to-LOW then LOW-to-HIGH 440 times per second, for example, it produces a 440 Hz (hertz) frequency - a "middle A" pitch. Humans can hear frequencies ranging from 20 (low-pitch, bass) to 20,000 Hz (high-pitch, "ow, my ears").

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_05_Tune

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 5: Play a Tune
SparkFun Electronics
https://www.sparkfun.com/products/14346

Play musical notes through the buzzer on the LilyPad ProtoSnap Plus

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#5-play-a-tune

Uses frequencies from "melody" by Tom Igoe: https://www.arduino.cc/en/Tutorial/toneMelody

This code is released under the MIT License: (http://opensource.org/licenses/MIT)

******************************************************************************/

// Create an integer variable naming the pin we'll use for the buzzer.
// On the ProtoSnap Plus, it's on A3.

int buzzer = A3;

// Map musical notes to their frequencies by creating variables for them.
// You can find the frequencies for higher and lower notes at:
// https://www.arduino.cc/en/Tutorial/toneMelody

int NOTE_C5 = 523;
int NOTE_CS5 = 554;
int NOTE_D5 = 587;
int NOTE_DS5 = 622;
int NOTE_E5 = 659;
int NOTE_F5 = 698;
int NOTE_FS5 = 740;
int NOTE_G5 = 784;
int NOTE_GS5 = 831;
int NOTE_A5 = 880;
int NOTE_AS5 = 932;
int NOTE_B5 = 988;
int NOTE_C6 = 1047;

// We'll also create a variable for how long to play each note in milliseconds.
// If you make this smaller, the notes will play faster.

int tempo = 500;

void setup()
{
  // Set the buzzer pin to be an output:

  pinMode(buzzer, OUTPUT);
}

void loop()
{
  // This code will play a simple scale from C5 to C6.

  // The tone command takes two parameters: a pin number and a frequency.
  // The tone will play until we stop it with the noTone command.
  // Each of the below blocks plays one note; the note plays during the delay command.

  tone(buzzer,NOTE_C5);
  delay(tempo);

  tone(buzzer,NOTE_D5);
  delay(tempo);

  tone(buzzer,NOTE_E5);
  delay(tempo);

  tone(buzzer,NOTE_F5);
  delay(tempo);

  tone(buzzer,NOTE_G5);
  delay(tempo);

  tone(buzzer,NOTE_A5);
  delay(tempo);

  tone(buzzer,NOTE_B5);
  delay(tempo);

  tone(buzzer,NOTE_C6);
  delay(tempo);

  // A longer delay at the end pauses the sound before looping again.
  // Here we're delaying four times the "tempo" value:

  noTone(buzzer);
  delay(tempo * 4);

  // Try writing your own song using the noted defined at the top of the program!
  // You can change the note duration by multiplying or dividing the "tempo" value
}

What You Should See

Once the code uploads, the buzzer will begin playing a simple musical scale over one octave, pause, and repeat.

 


Turn the volume up on your computer to hear the buzzer play a tune in the video

Understanding Your Program

Program Overview

1.Define variables for the audio frequencies we’ll be using, and the tempo (speed at which we’ll be playing).
2.Configure the sew tab connected to the buzzer to be an output.
3.Play a series of notes using the tone command.
4.Pause and repeat.

Code to Note

Code/Description

Code/Description

Coding Challenges

  • This program plays a simple scale. Can you change the program to play an actual song?
  • In this program we used a variable called tempo to change the durations of all the notes. In actual music, notes have different durations, and rests (periods of no sound) are important as well. Can you change the durations of individual notes by adding math to the delay values? Hint: If tempo is the duration of a whole note, tempo / 2 would be the duration of a half note, etc.

6: Buttons and Switches

In the activities thus far, you have been using outputs - components that receive a signal or power from the LilyPad USB Plus and send information (light and sound) to the world. In the next few activities, we will start to receive input from the world using buttons and sensors to affect the LilyPad boards on the ProtoSnap Plus.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad Button
  • Yellow LilyPad LEDs
  • Blue LilyPad LEDs
  • LilyPad Slide Switch

Activity 6: Buttons and Switches

Switch button

New Concepts Introduced in This Activity

Digital Input

Just as digital outputs have two states, ON or OFF (HIGH or LOW in code), digital inputs also have two states. We’ll use a special function called digitalRead() to check if the button has been pressed or if the switch has been flipped when attached to a sew tab on the LilyPad USB Plus.

Internal Pull-up Resistors

A pull-up resistor is a small circuit that holds the voltage HIGH (3.3V) on a pin until a button is pressed, pulling the voltage LOW (0V). The most common place you will see a pull-up resistor is when working with buttons. A pull-up resistor keeps the button in one state until it is pressed. The LilyPad USB Plus has built-in pull-up resistors, which we will use in code.

Variables for State Change

In Fading LEDs, the for() loop set a variable that was changed during the program. In this activity, you’ll read the state of a button or switch to a variable to hold its state for later use in your program.

If Statements

In the Fading LEDs example, we explored a specialized function, the for() loop. In this activity, we’ll use another function called an If Statement that will check if a state is true or false. Then we will make decisions based on the reading it receives. If/else functions are a way to start adding behavior based on input in your code, whereas the for() loop example created some automation. As you learn more specialized functions in Arduino (or write your own), your programs will become more complex and able to execute more complicated commands and interactions.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_06_Button

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 6: Buttons and Switches
SparkFun Electronics
https://www.sparkfun.com/products/14346

Explore digital input and program flow control using the button and switch

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#6-buttons-and-switches

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// Create integer variables for the pins we'll be using

int buttonPin = A4;
int switchPin = A9;

int buttonLED = A5;
int switchLED = A8;

void setup()
{
  // Initialize the button and switch pins as inputs with pullups.
  // Pullups keep the inputs from "floating" when a switch or button is open / unpressed.

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(switchPin, INPUT_PULLUP);

  // Initialize the LED pins as outputs:

  pinMode(buttonLED, OUTPUT);
  pinMode(switchLED, OUTPUT);
}

void loop()
{
  // This code will read the positions of the button and switch,
  // then use the "if" command to make LEDs follow these states.

  // Create variables to store the button and switch input values:

  int buttonState;
  int switchState;

  // Read and save the states of the button and switch:

  buttonState = digitalRead(buttonPin);
  switchState = digitalRead(switchPin);

  // The if-else statement lets you do different things based on different inputs:

  // The button will read as LOW when it's pressed

  if (buttonState == LOW) // Check to see if buttonState is LOW (pressed)
  {
    digitalWrite(buttonLED,HIGH); // If buttonState is LOW (pressed), turn on the LED
  }
  else
  {
    digitalWrite(buttonLED,LOW); // If buttonState is HIGH (unpressed), turn off the LED
  }

  if (switchState == LOW) // Check to see if switchState is LOW (switch is on)
  {
    digitalWrite(switchLED,HIGH); // If switchState is LOW (on), turn on the LED
  }
  else
  {
    digitalWrite(switchLED,LOW); // If switchState is HIGH (off), turn off the LED
  }
}

What You Should See

When you press the LilyPad Button, the yellow pair of LEDs will turn on. When the button is released, they will turn off. When you slide the LilyPad Slide Switch to the ON position, the blue pair of LEDs will turn on and remain on until the switch is set to the OFF position.

 

Understanding Your Program

Program Overview

1.Check to see if the button is pressed.
a.If it is, turn buttonLED ON.
b.If it isn’t, turn buttonLED OFF.

2.Check to see if the switch is set to ON.
a.If it is, turn switchLED ON.
b.If it isn’t, turn switchLED OFF.

Code to Note

Code/Description

Code/Description

Coding Challenges

  • Can you adapt the code so that the opposite actions happen (when the button is pressed it turns the LEDs off and when the switch is off it sets the LEDs on)?
  • Try creating a light pattern that displays on the row of LilyPad LEDs when the switch is set to ON.
  • Can you adapt the Play a Tune example to include an on/off switch to control whether the song plays or not?

7: Sensing Light

This activity will also use inputs, this time to sense ambient light in the room and use that reading to light up LEDs. The light sensor is an analog sensor which provides a range of values instead of the digital ON/OFF of the buttons and switches example.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad Light Sensor
  • Red LilyPad LEDs
  • Green LilyPad LEDs
  • Blue LilyPad LEDs

Activity 7: Sensing Light

What is a light sensor

New Concepts Introduced in This Activity

Analog Input: Analog to Digital Conversion

In this activity, we’ll explore reading input from a sensor in a new way using analog input. Notice that certain sew tabs on the LilyPad USB Plus include an ‘A’ in front of the number - this indicates the pins on the controller and tabs that are connected have an Analog to Digital Converter (ADC). These pins can "sample" an analog signal being read by the controller and translate it to a digital signal that the controller can interpret.

In the last activity, we used digital inputs that read only two states. The LilyPad Light Sensor is an analog sensor, meaning it can read a wide range of values. For analog inputs, the values range from 0 (0V) to 1023 (3.3V).

Serial Monitor and Serial Commands

When using the button and switch, it was pretty easy to tie the ON/OFF to an LED turning ON/OFF. For sensors reading a range of values, it is more useful to actually see those numbers and make decisions using them. The Serial Monitor and Serial Commands are useful tools for displaying information from variables or other debugging tools for your code.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_07_Light

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 7: Sensing Light
SparkFun Electronics
https://www.sparkfun.com/products/14346

Explore analog input from the light sensor

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#7-sensing-light

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// Create variables for the pins we'll use:

int sensorPin = A2;

int redLED = 6;
int greenLED = A7;
int blueLED = A8;

void setup()
{
  // Initialize the sensor pin as an input, but without a pullup
  // (Pullups are only used for switch inputs)

  pinMode(sensorPin, INPUT);

  // Initialize the output pins:

  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);

  // Initialize the serial monitor:

  Serial.begin(9600);
}

void loop()
{
  int sensorValue;

  // Read the sensor value (will be 0 to 1023):

  sensorValue = analogRead(sensorPin);

  // Print out the sensor reading to the serial monitor:

  Serial.print("sensor value: ");
  Serial.println(sensorValue);

  // Since the sensor value is 0 to 1023,
  // and analogWrite needs a value from 0 to 255,
  // we'll divide the sensor value by four to scale it down:

  analogWrite(redLED,sensorValue / 4);
  analogWrite(greenLED,sensorValue / 4);
  analogWrite(blueLED,sensorValue / 4);
}

What You Should See

Hold your hand over the light sensor to change the amount of light it is exposed to and observe the red, green, and blue LilyPad LEDs. As the light sensor reads less light, the LEDs will reflect the light levels with their brightness levels. You can also use a flashlight to shine more light on the sensor and observe how it affects the LEDs.

 

Understanding Your Program

Program Overview

1.Store the light level in the variable sensorValue.
2.Print the reading to the Serial Monitor.
3.Set the brightness level of the red, green, and blue LEDs to the number stored in the sensorValue variable divided by 4.
4.Repeat.

using the serial monitor

Using the Serial Monitor

Using the Serial Monitor

Code to Note

Code/Description

Code/Description

Coding Challenges

  • Can you change the code so that the built-in RGB LED displays a brighter or dimmer white when the light levels change?
  • Can you change the code so that two colors mix on the RGB LED when the light levels change?
  • Can you create a blink pattern where the speed of the blink is determined by the light sensor readings?

8: LED Bar Graph

The LilyPad USB Plus includes six white LEDs. You can control them individually like any of the other LEDs on the ProtoSnap, but because they’re in a row they’re perfect for creating a LED bar graphs. In this activity, we’ll experiment with graphing the readings from the light sensor onto the row of white LEDs on the LilyPad USB Plus.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad USB Plus’s built-in row of white LEDs (bar graph)
  • LilyPad Light Sensor

Activity 8: LED Bar Graph

LED bar graph

New Concepts Introduced in This Activity

Using Arrays

Arrays are a handy way to store many variables in one structure. Here we’ll store the pin / sew tab numbers of the white LEDs, making them easier to use as a group.

Creating Custom Functions

So far we’ve been using Arduino’s built-in functions, but you can also create your own. Functions are great for bits of code you want to run repeatedly, or even reuse in other programs.

Anatomy of a function

Parameters

Scope

Incrementing Shortcuts

Many times in programming you’ll want to add or subtract one from a number, such as in a for() loop. In earlier activities, we did this with the pattern x = x + 1. But there are some handy shortcuts you can use:

The Long Way/Shortcut

Learn more about compound operators for shorcuts and their use at the Arduino Reference site.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_08_BarGraph

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 8: LED Bar Graph
SparkFun Electronics
https://www.sparkfun.com/products/14346

Play with the six LEDs on the LilyPad ProtoSnap Plus

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#8-led-bar-graph

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// Create a variable for the light sensor input:

int sensorPin = A2;

// The six white LEDs on the LilyPad USB Plus are numbered 15 through 20.
// To make them easier to use, we'll put those numbers into an array.
// The initial [6] defines the size of the array (six elements).
// We're filling the array with predefined values, but you could do this
// in your code as well.

int bargraphLED[6] = {15,16,17,18,19,20};

// The array is indexed from 0 to 5; for example bargraphLED[2] = 17

void setup()
{
  int x;

  // Initialize the sensor pin as an input, but without a pullup
  // (Pullups are only used for switch inputs)

  pinMode(sensorPin, INPUT);

  // Initialize the bargraph LED pins as outputs
  // We'll use the matrix we defined above,
  // where the LEDs are indexed from 0 to 5

  for (x = 0; x <= 5; x++)
  {
    pinMode(bargraphLED[x], OUTPUT);
  }

  // Initialize the serial monitor

  Serial.begin(9600);
}

void loop()
{
  int sensorValue;

  // Read the sensor value (will be 0 to 1023):

  sensorValue = analogRead(sensorPin);

  // Print out the sensor reading:

  Serial.print("sensor value: ");
  Serial.println(sensorValue);

  // Display the sensor reading on the bar graph LEDs.
  // This is a new function that we created ourselves (see below).

  barGraph(sensorValue);
}

// Here we're making our own command called barGraph:
// The first "void" means we don't return anything from this command
// The "int value" is what we'll pass to the command (it must be an integer,
// and it will be called "value" in the command.

void barGraph(int value)
{
  // Create a LED bargraph using value as an input.
  // Value should be in the range 0 to 1023.

  int x;

  // Step through the bargraph LEDs,
  // Turn them on or off depending on value.

  // Value will be in the range 0 to 1023.
  // There are 6 LEDs in the bargraph.
  // 1023 divided by 6 is 170, so 170 will be our threshold
  // between each LED (0,42,84, etc.)

  for (x=0; x <= 5; x++)
  {
    if (value > (x*170) )
    {
      digitalWrite(bargraphLED[x], HIGH);
    }
    else
    {
      digitalWrite(bargraphLED[x], LOW);
    }   
  }
}

 

What You Should See

After the code loads, the white LED bar graph on the LilyPad USB Plus will show you how much light is hitting the light sensor. Try covering the sensor with your hand, or aiming a flashlight at it to see a larger or smaller response from the bar graph.

 

Understanding Your Program

Program Overview

1.Set up an array with the white LED pins.
2.Configure the pins and serial monitor.
3.Read the light level.
4.Display it on the bar graph.
5.Repeat.

Code to Note

Code/Description

Code/Description

Coding Challenges

  • Alter the function of the bar graph so that all of the LEDs are on, and go out as the value increases.
  • Alter the value of the bar graph so that it fills in from the right rather than from the left. Hint: Can you do this by declaring the array differently?

9: Theremin Project

Now that you’ve explored all the boards on the LilyPad ProtoSnap Plus, it’s time to start combining some of those skills into more interactive projects. The first project we’ll explore is creating a musical ‘instrument’ inspired by a theremin. A theremin is an instrument played without needing physical contact, typically utilizing antennas. In this ‘theremin’, you’ll use readings from the light sensor as a controller for frequency of tones produced by the buzzer. We can further categorize this project an opto-theremin because it is using light as a controller. In addition to the sensor and buzzer, we’ll display the light readings on the bar graph and add the button as an on/off trigger.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad USB Plus’s built-in LEDs
  • LilyPad Light Sensor
  • LilyPad Buzzer
  • LilyPad Button

Activity 9: Theremin Project

New Concepts Introduced in This Activity

Using the Map() Function

The map() function is a handy function that translates one range of numbers into another range.

For example, let’s say you wanted to use the light sensor (read by analogRead()) to control the brightness of a LED (written by analogWrite()), as we did back in activity 7. But the range of analogRead() (0 to 1023) doesn’t match the range of analogWrite() (0 to 255).

This particular example is easy to solve in that you can simply divide the light sensor value by 4, as we did in activity 7. But it would take a bit more work to solve for arbitrary ranges that may not start at 0, as we’ll be doing in this activity.

The map() function does this for you. The parameters it needs are:

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

Where fromLow to fromHigh is the range of the original value, and toLow to toHigh is the range we want to translate that value into.

For example, here’s how we’d set up map() for our earlier example:

LEDbrightness = map(lightSensorValue,0,1023,0,255);

It’s worth mentioning that if value isn’t within the original range, map() will still work; but it will return a result outside the target range. If your result must be within the target range, an additional function called constrain() can be used to ensure that:

result = constrain(value,low,high);

If value is already within the range of low to high, the result will be the same as value. But if value is outside that range, it will be set to low or high, whichever is closest. Our complete example would then look like:

LEDbrightness = map(lightSensorValue,0,1023,0,255);
LEDbrightness = constrain(LEDbrightness,0,255);

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_09_Theremin

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 9: Theremin
SparkFun Electronics
https://www.sparkfun.com/products/14346

A Theremin is an electronic musical instrument that is played by
moving your hands over it. In this activity we'll create a Theremin
using the light sensor and the buzzer.

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#9-theremin-project

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// Create variables for the pins we'll be using

int sensorPin = A2;
int buttonPin = A4;
int buzzer = A3;
int bargraphLED[6] = {15,16,17,18,19,20};

// Set the highest and lowest frequencies
// (Change these and see what happens)

int highestFrequency = 1047; // C6
int lowestFrequency = 523; // C5

void setup()
{
  int x;

  // Initialize the pins we'll be using

  pinMode(sensorPin, INPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  for (x = 0; x <= 5; x++)
  {
    pinMode(bargraphLED[x],OUTPUT);
  }

  // Initialize the serial monitor

  Serial.begin(9600);
}

void loop()
{
  int sensorValue;
  int frequency;

  // Read the sensor value (will be 0 to 255):

  sensorValue = analogRead(sensorPin);

  // Print out the sensor reading:

  Serial.print("sensor value: ");
  Serial.println(sensorValue);

  // Display the sensor reading on the bar graph LEDs:

  barGraph(sensorValue);

  // Play a tone based on the light level:

  // The light sensor will return a value from 0 to 1023,
  // but we want to map this to a specific range of frequencies.
  // We'll use a built-in fuction called "map" that transforms one range
  // of values (0 to 1023) to another (lowestFrequency to highestFrequency):

  frequency = map(sensorValue,0,1023,lowestFrequency,highestFrequency);

  if (digitalRead(buttonPin) == LOW) // If the button is pressed:
  {
    tone(buzzer,frequency);
  }
  else
  {
    noTone(buzzer);
  }
}

void barGraph(int value)
{
  // Create a LED bargraph using value as an input.
  // Value should be in the range 0 to 1023.

  int x;

  // Step through the bargraph LEDs,
  // Turn them on or off depending on value.

  // Value will be in the range 0 to 1023.
  // There are 6 LEDs in the bargraph.
  // 1023 divided by 6 is 170, so 170 will be our threshold
  // between each LED (0,42,84, etc.)

  for (x=0; x <= 5; x++)
  {
    if (value > (x*170) )
    {
      digitalWrite(bargraphLED[x], HIGH);
    }
    else
    {
      digitalWrite(bargraphLED[x], LOW);
    }   
  }
}

 

What You Should See

To play the theremin, press and hold the button with one hand and cover the light sensor with the other. As the light sensor reads different light levels, the frequency on the buzzer will change and the bar graph LEDs will illuminate to show the different tones. Release the button to stop the sounds. You can also use a flashlight to shine more light on the sensor and get a large range of tones.

 

Understanding Your Program

Program Overview

1.Create variables to store.
2.Read the value from the light sensor and store in sensorValue.
3.Print the light sensor reading to the serial monitor.
4.Display the sensor reading on the bar graph using a custom barGraph() function.
5.Map the values from the light sensor to the set range of frequencies (set in lowestFrequency and highestFrequency)
6.Check to see if the button is pressed. a.If it is, send a tone() command to the buzzer using the frequency value. b.If it is not, turn the buzzer off using noTone() command.
7.Repeat.

Code to Note

Code/Description

Coding Challenges

  • Adjust lowestFrequency and highestFrequency to use different ranges for the tones the theremin creates.
  • Try adding additional sound controls by adding another if/else statement using the switch. Suggestions: Turning a light pattern on/off that coordinates with the sound or switching between different frequency ranges.

10: Twinkling Night-Light Project

In this activity, we’ll pull together elements from earlier activities to create an entire project: a night-light that randomly twinkles LEDs when it gets dark. You could use this as the starting point for a project based around twinkling stars, fireflies, lightning clouds or something else entirely.

LilyPad Boards Used in This Activity

  • LilyPad USB Plus
  • LilyPad USB Plus’s built-in RGB LED
  • LilyPad Light Sensor
  • Red LilyPad LEDs
  • Green LilyPad LEDs
  • Blue LilyPad LEDs

Activity 10: Twinkling Night Light

New Concepts Introduced in This Activity

Random

Computers are generally very predictable. Usually this is exactly what we want, but sometimes, especially when creating artistic projects, we want a bit of randomness to make things more surprising and natural. In this activity, we’ll introduce the random() command, which will help you do exactly that.

The random() function is a fun command that will return a random? number. You can use it to randomize which LEDs are lit, how long to pause, what tone to play, etc. The random() function takes one parameter, the number of possibilites to choose from. For example, if you wanted to simulate a six-sided die, you would call random(6). The function will then return a number between 0 and 5.

How random is random

Setting a Threshold

To determine when it’s dark enough to begin twinkling, we’ll define a threshold value. If the ambient light level is below that value, we’ll begin twinkling. To help you fine-tune this value, we also use the serial monitor to print out the current light level.

Example Code

To open the code, go to:

File > Examples > LilyPadProtoSnapPlus > LPP_10_NightLight

You can also copy and paste the following code into the Arduino IDE. Hit upload, and see what happens!

Copy Code
/*
LilyPad ProtoSnap Plus Activity 10: Twinkling Night-Light
SparkFun Electronics
https://www.sparkfun.com/products/14346

Create a twinkling night-light that turns on when it gets dark.

Follow the tutorial at:
https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide#10-twinkling-night-light-project

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// Create variables for the pins we'll be using:

int lightSensor = A2;

// Array of all the LEDs we'll be twinkling. You can set these to the sewtabs
// you'll be using in your project. Remember to only choose outputs that
// have the "~" symbol that are compatible with analogWrite.

int numLEDs = 3;
int LED[3] = {6,A7,A8};

int blueLED = 14;

// Threshold for light level (when it's darker than this, twinkle LEDs)

int threshold = 50;

void setup()
{
  int x;

  // Initialize the pins we'll be using

  pinMode(lightSensor, INPUT);

  for (x = 0; x <= numLEDs; x++)
  {
    pinMode(LED[x],OUTPUT);
  }

  pinMode(blueLED,OUTPUT);

  // Initialize the serial monitor

  Serial.begin(9600);
}

void loop()
{
  int x,lightLevel,brightness;

  // Read the sensor value (will be 0 to 255):

  lightLevel = analogRead(lightSensor);

  // Print out the sensor reading:

  Serial.print("light level: ");
  Serial.print(lightLevel);
  Serial.print(" threshold: ");
  Serial.print(threshold);
  Serial.print(" twinkle: ");

  // If the light level is below the threshold, twinkle LEDs:

  if (lightLevel < threshold)
  {
    Serial.println("ON");
    digitalWrite(blueLED,HIGH);

    // Pick a random LED:

    x = random(numLEDs);

    // Quickly ramp up the brightness of the LED from off to on:

    for (brightness = 0; brightness <= 255; brightness++)
    {
      analogWrite(LED[x],brightness);
      delay(1);
    }

    // Quickly ramp down the brightness of the LED from on to off:

    for (brightness = 255; brightness >= 0; brightness--)
    {
      analogWrite(LED[x],brightness);
      delay(1);
    }

    // Wait a random amount of time (up to 2 seconds)

    delay(random(2000));
  }
  else
  {
    Serial.println("off");
    digitalWrite(blueLED,LOW);
  }
}

 

What You Should See

Cover the light sensor with your hand. When the sensor’s readings drop below the set threshold, the built-in blue LED in the RGB will light up indicating it is ‘dark’. Then the red, green, and blue pairs of LEDs along the bottom of the ProtoSnap will twinkle in a random pattern.

 

Understanding Your Program

Program Overview

1.Set up our array with the LEDs we want to twinkle.
2.Set up our input and output pins.
3.Read the light sensor value; if it’s low, turn on the built-in blue LED and begin twinkling.
4.To twinkle, choose a random LED from the array, then rapidly brighten and dim it.
5.Wait a random amount of time between twinkles.
6.Repeat.

Code to Note

Code/Description

Code/Description

Coding Challenges

  • Try making the LEDs twinkle faster or slower, or have a shorter or longer pause between twinkles.
  • Instead of twinkling, can you simulate a heartbeat or other pattern?
  • Can you modify the code so that it twinkles when it’s bright out?
  • Can you add sounds to the twinkling?

Troubleshooting

As you begin to edit the example code and write your own programs, you may experience some error messages. This section highlights a few common issues and solutions as you work on your Arduino code.

At the bottom of the Arduino IDE is section with a black background. This is the Debug Window - if something unexpected or incorrect happens and Arduino can’t communicate to your LilyPad USB Plus or run the code you’ve written, an error message will display here. The top of the section will turn orange and a "Copy Error Messages" button will display.

Example Arduino Error
An example of an error displaying in the debug window

Common Error Messages
Error: "Couldn’t find a Board on the selected port"

  • Check that you have the correct port selected.
  • Check that LilyPad USB Plus is selected in the board menu, NOT LilyPad Arduino or LilyPad Arduino USB.
  • Try pressing the board’s reset button after initiating the upload.
  • Check that the LilyPad USB Plus is switched to ON.
  • Check that the USB cable is correctly connected to your computer and LilyPad USB Plus.
  • Check that the USB cable is not a ‘power only’ cable.

Error: "Expected ‘;’ before"

This error happens when there is a missing ; at the end of a statement. Arduino will highlight the line in red in the code window and print a line number in the code around where the error occurred to help you identify where you need to fix something. You can turn on line numbering in Arduino > Preferences.

Example Arduino Error
In this example, a missing ; after digitalWrite(A5, HIGH) caused the error.

Error: "‘variable’ was not declared in this scope"

Scope errors can happen for a variety of reasons, here are some common things to check:

  • Variable mismatch (spelling, capitalization, spacing differences) when trying to use a variable you have declared in another part of your program
  • Variable was not declared with a type before use.
  • Variable was declared within a function and not globally and is trying to be used outside of that function.

Example Arduino Error
This error happened because the variable blueLED was mistyped as BlueLED. Arduino did not recognize BlueLED, while it may look similar enough to you, Arduino is case sensitive.

Error: "Expected ‘}’ at end of input"

As you copy and paste to move pieces of your code around or work with nested functions, your code will accumulate a lot of curly brackets. To keep track of nested functions in the example code, we use indented formatting. Each new nested layer of function is indented an addition time to visually organize the code. If one of the opening { or closing } is accidentally deleted or not added, you will get an error.

Example Arduino Error
This error in Activity 4 happened because the closing bracket for the for() loop is missing. This can be initially misleading, as Arduino highlighted a closing bracket - this one belongs to the loop. The space above it is where Arduino expected a match for the opening bracket of the for() loop - highlighted in blue.

Keeping Track of Brackets

Arduino has a handy feature built in that highlights the matching curly bracket if you place your cursor after one. You can use this to quickly check that there are no brackets left behind.

Bracket Highlighting
Placing the cursor next to the closing bracket of the for () loop in Activity 4 highlights its matching opening bracket with a blue outline.

Depending on the Arduino IDE version that you have installed, you may also be able to view the function that was associated with the bracket if it is out of frame. In this example, we were using Arduino IDE v1.8.3.

Bracket Highlighting
Placing the cursor next to the closing bracket of the loop() function highlights the function and bracket when it is out of frame.

Semantics Error and Debugging

Why is my code not working even though it compiles?

This sounds like a pretty general question, but it’s likely a semantic error. While the code is able to compile and is free from syntax errors, the code might not be written to do what you intended. Assuming the hardware connections and boards are good, it is possible that:

  • A pin or variable was not initialized correctly.
  • A variable was not calculated and saved correctly.
  • The wrong variable is printing to the Serial Monitor.
  • You are using values outside of an array[].
  • There is a baud rate mismatch.
  • A delay() function is preventing a certain line from executing fast enough.
  • The sequence of code is not executed properly.

The list of reasons why this may be happening can go on depending on the complexity of the project. The simplest method of debugging can be turning on an LED when we reach a certain part of the code. However, the best method of troubleshooting Arduino code is to try to step through using the serial.print() function to debug. If used correctly, the function is more flexible and can indicate that we have entered a line of code.

Maybe you want to print "I entered this function" to the Serial Monitor after pressing a button or when a sensor reaches a certain value. The serial.print() function can also be used to inspect variables in order to know what to expect from a sensor’s output range. The function can also be used to verify calculations. Other environments allow you to step through the code to simulate what may happen without the need for serial.print().

TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum