Introduction: June 2014 Bulid Night: LittleBits Slider Blink

This Instructable is going to be simpler than the other littleBits builds from H3 Labs for this Build Night. I decided to highlight the Arduino programming aspect rather than the physical project.

It only requires a few parts:

  • Computer (to load the sketch to the Arduino)
  • USB cable
  • LittleBits Arduino module (w6)
  • Slide Dimmer module (i5)
  • Power module (p1)
  • Power cable
  • 9v battery
  • RGB LED module (o3)

If you don't have an RGB LED module, several others will work. Try an EL Wire or Buzzer module.

Note: the color the RGB LED shows cannot be changed by your sketch; you'll still have to change it manually on the module.

Step 1: LittleBits Assembly

Plug the battery into the power cable, and the power cable into the power module.

Position the Slide Dimmer module at pin a0 on the Arduino module (the middle spot on the left side).

Position the RGB LED module at pin d5 on the Arduino module (the middle spot on the right side).

Position the Power module on either of the remaining open spots on the Arduino module's left side (or on the open side of the Slide Dimmer module).

Step 2: Prepare to Load the Sketch

Open the Arduino IDE on your computer.

Plug the USB cable into the Arduino module and your computer.

Turn on the Power module. You computer should then acknowledge that the Arduino is connected.

In the Arduino IDE menu, choose Tools -> Board -> Arduino Leonardo, then Tools -> Serial Port -> and whichever port the Arduino module is.

Step 3: The Sketch

Copy the code below into the Arduino IDE window.

/*
littleBits Arduino Module
Marty Vance
20 June 2014
 
Slider_Blink

What is supposed to happen:
A slide dimmer on pin A0 changes the blink rate of an RGB LED on pin 5.

This sketch includs the following commands:
pinMode( pin, mode ); // pin = a digital pin, mode = OUTPUT or INPUT
digitalWrite( pin, value ); // pin = a digital pin that has been set to OUTPUT, value = HIGH or LOW
delay( time ); // time = time of delay in milliseconds
*/

/*
Variable initialization
In most sketches, you'll want to initialize some variables before anything
else happens.  This way they are already available when setup() runs.

We create variables for the pins we'll be using and a few more that will
be needed as the sketch runs.
*/

uint8_t led_pin = 5; // pin for the LED
uint8_t sldr_pin = A0; // pin for the slide dimmer
int sldr_val = 512; // the blink rate initial value
int blink_val = 0; // the blink duration
int t = 0; // used to store the current time during each execution of loop()
int l = 0; // used to store the time of the previous loop()
boolean o = false; // whether to turn the LED on or off
int min_rate = 50; // fastest blink rate in milliseconds
int max_rate = 1000; // slowest blink rate in milliseconds

/*
setup - This is where we initialize the sketch
Setup includes commands that set the stage for the rest of the sketch.
The commands inside of setup are only executed once.
After all the commands in setup have been executed, the sketch moves to loop.
*/

void setup(){ // this is the beginning of setup

    // Since we are going to use pin 5 to control an output module
    // we need to set the pinMode of pin 5 to OUTPUT,
    // this means voltage will flow out of the pin.
    pinMode( led_pin, OUTPUT ); // set pin 5 to OUTPUT mode
    pinMode( sldr_pin, INPUT ); // set pin A0 to INPUT mode

    sldr_val = analogRead(sldr_pin); // read the slide dimmer right away

} // this is the end of setup

/*
loop - This is the main part of every arduino sketch.
Loop is a series of commands that executed one after another in order of top to bottom.
When all the commands have been executed, loop begins again from the top.
This goes on for as long as there is power running the Arduino.
*/

void loop(){ // This is the beginning of loop, each command below is executed in order of top to bottom
    t = millis(); // get the current time
    
    /*
        This loop runs without calling delay(): it continuously reads the slider value, but only
        changes the blink rate when enough time has passed, which is determined by the if statement.
        
        See the Blink Without Delay example sketch.
    */

    sldr_val = analogRead(sldr_pin);

    if (t - l >= blink_val) {
        Serial.print("Slider value: ");
        Serial.print(sldr_val);
        blink_val = map(sldr_val, 0, 700, min_rate, max_rate); // convert the possible range of sldr_val to within the bounds of the blink rates
        Serial.print(" => Blink interval: ");
        Serial.println(blink_val);
 
        // watch the serial monitor to see exactly what map() is doing
    
        digitalWrite(led_pin, (o ? HIGH : LOW)); // Turn the LED on or off based on whether o is true or false
        o = !o; // if o is true, make it false; if o is false, make it true
        l = t; // this loop's time is the previous time for the next loop
    }
} // this is the end of loop, now return to the beginning of loop and execute the commands again

Click the Upload button in the Arduino IDE. If everything is right, after a few seconds you should see the yellow LEDs on the Arduino module near the USB connector blink quickly for a few seconds, then your RGB LED should start blinking.

Move the Slide Dimmer to change how fast the LED blinks!

Step 4: What the Sketch Does

The sketch is pretty simple, but it still illustrates several programming concepts.

First, the sketch initializes several variables which are used later in the sketch. Along with the pins we're going to use, we initialize variable for the minimum and maximum blink rates, two to store time values, and one for whether the LED should be on or off.

Because these variables are initialized outside of any function, they are in the global scope. This means they can be used and changed anywhere in the code and the changes will persist. This will become important later.

Next is the setup() function. Here we use pinMode() to set up the pins, one for input (the slider) and one for output (the LED). Then we read the value from the slider... you don't have to wait until loop() to read a value as long as the pin in set up.

After setup(), loop() runs over and over until power is disconnected. We don't initialize any variables here because everything we need is already in the global scope.

First, we get the current time by calling millis() and putting that in t.

Next we read the value of the Slide Dimmer into sldr_val. I should note here that the values we get here should be 0 to 1023, but the Slide Dimmer may not give values this high.

Now we check if we should do anything. We do this by comparing the time elapsed since the previous iteration of loop() to blink_val. When loop() runs the first time, the previous time (l) and blink_val have already been set to 0, so this still works. If enough time has passed, it's time to do something, so we enter the "if" block and start doing things.

We send the value of the Slide Dimmer (which we just read) to the serial monitor.

Next we update the value of blink_val using a bilt in function called map() (read more about it at http://arduino.cc/en/Reference/Map). Map takes a variable and scales it from one range to another range. The first range is what the Slide Dimmer value could be, and the second range is what we want; we already initialized the bounds of this range at the top of the sketch as min_rate and max_rate.

Now we have an updated value for blink_rate to compare with the time passed from this iteration of loop() to later ones.

The next step writes to the pin the LED is on, thereby turning the LED on or off. The syntax used for this is very compact, so I'll explain it.

A call to digitalWrite() takes two arguments: the pin and the value to write. Our first argument here is the variable for the LED pin, led_pin. The second argument is not a value, or even a variable... it's an expression.

Because this pin is in a digital mode, it can only understand two values: true or false. The constants HIGH and LOW are aliases of true and false, so when you use HIGH, you're actually passing true.

Anyway, back to our expression. It's a ternary operator, which is kind of shorthand for if/else code blocks. We've wrapped the ternary operator in parentheses for clarity. Unfortunately these are not documented in the Reference section of the Arduino website, so read on here.

A ternary operator has three parts. The first part is another expression that the ternary operator evaluates. It is followed by a question mark.

The second part is the value returned by the ternary operator if the first part evaluates to true. It is followed by a colon.

The third part is the value returned by the ternary operator if the first part doesn't evaluate to true (in other words, false).

Our first part is our variable o, which is the boolean we defined at the top of the sketch. Our second part is HIGH, and our second part is LOW.

So if o is true, HIGH is written to the pin, otherwise LOW is written.

Other programming veterans will probably say "but you could just pass o directly and not bother with a ternary", and the're right because o is a boolean and it is going to be false (which HIGH is an alias of) or false (which LOW is an alias of). I used it here to illustrate what a ternary operator does.

After that, we prepare for the future. We invert o (true becomes false, false becomes true), then update the previous time l to the value of the current time t.

But there's another thing going on here. By using o this way in combination with the LED, we have created a State Machine for the LED. In electronics, a state machine is

A device that can be in one of a set number of stable conditions depending on its previous condition and on the present values of its inputs.

Our state machine only has two states, on and off.