Serial Communication

Libraries
A library is a collection of procedures, where all the procedures are related. If you, say, want to control a motor, you may want to find a Motor Control Library: a collection of procedures that have already been written that you can use without having to learn the nuances of motors.

The Serial Library allows the Arduino to send data back to the computer. It includes the following funtions:

What is Serial?

The word serial means one after the other. For example, a serial killer doesn't stop with one murder, but stabs many people one after the other. Serial data transfer is when we transfer data one bit at a time, one right after the other.

Information is passed back and forth between the computer and Arduino by setting a pin high or low. One side sets the pin and the other reads it. It's a little like Morse code, where you can use dits and dahs to send messages by telegram. In this case, instead of a long cable, its only a few feet.


Serial communication with the laptop allowing for greater design flexibility.

Measuring Data



When you Compile/Verify what you're really doing is turning the sketch into binary data (ones and zeros). When you Upload it to the Arduino, the bits are shoved out one at a time through the USB cable to the Arduino where they are stored in the main chip.

Next time you upload a sketch, look carefully at the two LEDs near the USB connector, they'll blink when data is being transmitted. One blinks when the Arduino is receiving data (RX) and one blinks when the Arduino is transmitting data (TX)

Step 1

Wire the board to go with this code:
/*
* Code for cross-fading 3 LEDs, red, green and blue, or one tri-color LED, using PWM
* The program cross-fades slowly from red to green, green to blue, and blue to red
* Clay Shirky <clay.shirky@nyu.edu>
*/

// Output
int redPin   = 9;   // Red LED,   connected to digital pin 9
int greenPin = 10;  // Green LED, connected to digital pin 10
int bluePin  = 11;  // Blue LED,  connected to digital pin 11

// Program variables
int redVal   = 255; // Variables to store the values to send to the pins
int greenVal = 1;   // Initial values are Red full, Green and Blue off
int blueVal  = 1;

int i = 0;     // Loop counter    
int wait = 50; // 50ms (.05 second) delay; shorten for faster fades
int DEBUG = 0; // DEBUG counter; if set to 1, will write values back via serial

void setup()
{
  pinMode(redPin,   OUTPUT);   // sets the pins as output
  pinMode(greenPin, OUTPUT);   
  pinMode(bluePin,  OUTPUT); 
  if (DEBUG) {           // If we want to see the pin values for debugging...
    Serial.begin(9600);  // ...set up the serial ouput on 0004 style
  }
}

// Main program
void loop()
{
  i += 1;      // Increment counter
  if (i <255){ // First phase of fades
    redVal   -= 1; // Red down
    greenVal += 1; // Green up
    blueVal   = 1; // Blue low
  }
  else if (i < 509){ // Second phase of fades
  
    redVal    = 1; // Red low
    greenVal -= 1; // Green down
    blueVal  += 1; // Blue up
  } 
  else if (i < 763){ // Third phase of fades
  
    redVal  += 1; // Red up
    greenVal = 1; // Green low
    blueVal -= 1; // Blue down
  }
  else{ // Re-set the counter, and start the fades again
  
    i = 1;
  }  

  analogWrite(redPin,   redVal);   // Write current values to LED pins
  analogWrite(greenPin, greenVal); 
  analogWrite(bluePin,  blueVal);  

  if (DEBUG) { // If we want to read the output
    DEBUG += 1;     // Increment the DEBUG counter
    if (DEBUG > 10){ // Print every 10 loops
    
      DEBUG = 1;     // Reset the counter

      Serial.print(i);       // Serial commands in 0004 style
      Serial.print("\t");    // Print a tab
      Serial.print("R:");    // Indicate that output is red value
      Serial.print(redVal);  // Print red value
      Serial.print("\t");    // Print a tab
      Serial.print("G:");    // Repeat for green and blue...
      Serial.print(greenVal);
      Serial.print("\t");    
      Serial.print("B:");    
      Serial.println(blueVal); // println, to end with a carriage return
    }
  }
  delay(wait); // Pause for 'wait' milliseconds before resuming the loop
}

Before you run the program describe what it will do.


Exercise 2

Complete the code below and upload it to the board.

/* 
 * Serial RGB LED
 * ---------------
 * Serial commands control the brightness of R,G,B LEDs 
 *
 * Command structure is "<colorCode><colorVal>", where "colorCode" is
 * one of "r","g",or "b" and "colorVal" is a number 0 to 255.
 * E.g. "r0"   turns the red LED off.  
 *      "g127" turns the green LED to half brightness
 *      "b64"  turns the blue LED to 1/4 brightness
 *
 * Created 18 October 2006
 * copyleft 2006 Tod E. Kurt <tod@todbot.com
 * http://todbot.com/
 */

char serInString[100];  // array that will hold the different bytes of the 	
        //string. 100=100characters;
        // -> you must state how long the array will be else it won't work properly
char colorCode;
int colorVal;

//these leds will fade on and off
int redPin   = _;   // Red LED,   connected to digital pin 9
int greenPin = _;  // Green LED, connected to digital pin 10
int bluePin  = _;  // Blue LED,  connected to digital pin 11

void setup() {
// set the pins as output
 _____________________
 _____________________
 _____________________
 
 //set up serial at a baudrate 9600
  _____________________
  
 //turn each light on half way (255 is all the way on)
  _____________________
  _____________________
  _____________________
  
  
 //Give user directions to program
 Serial.println("enter color command (e.g. 'r43') :");  
}

void loop () {
  //read the serial port and create a string out of what you read
  readSerialString(serInString);
    
 //set color code to the first element in the array (r,g or b)
 colorCode = serInString[__];
 
 //make sure you've got a light
  if( colorCode == 'r' || colorCode == 'g' || colorCode == 'b' ) {
  
  //The C function atoi() takes a string in decimal and returns an integer 
    colorVal = atoi(serInString+1);
    
    Serial.print("setting color ");
    Serial.print(colorCode);
    Serial.print(" to ");
    Serial.print(colorVal);
    Serial.println();
    
    //To indicate you've used this string
    //set the first element in the array   serInString to 0
   ________________________ 
    
    
    //update lights
    if(colorCode == 'r') 
      analogWrite(redPin, colorVal);
    else if(_________________)
      _________________________
    _________________________
      _________________________
  }
  
  delay(100);  // wait a bit, for serial data
}

//read a string from the serial and store it in an array
//you must supply the array variable

void readSerialString (char *strArray) {
  int i = 0;
  if(!Serial.available()) {
    return;
  }
  while (Serial.available()) {
    strArray[i] = Serial.read();
    i++;
  }
}

Exercise 3

Change the code below so that you can control the RGB values with multiple key presses. For example, pressing 'r' 5 times will set the brightness to 50% (or brightness = 127) and pressing 'r' 10 times will set it to 100% (or brightness = 255).

Here is a useful string comparison function that compares two strings to see if they are equal.
stringsEqual("hello","hello",5) => true
stringsEqual("hello","helaabbnn",3) => true
stringsEqual("hello","helaa",5) => false
To use this function you must include these lines before setup():
stringsEqual()
#include <stdio.h>
#include <string.h>

/* 
 * Serial RGB LED
 * ---------------
 * Serial commands control the brightness of R,G,B LEDs 
 *
 * Command structure is "", where "colorCode" is
 * one of "r","g",or "b" and "colorVal" is a number 0 to 255.
 *      "r0"   turns the red LED off.  
 *      "g127" turns the green LED to half brightness
 *      "b64"  turns the blue LED to 1/4 brightness
 *
 * Alternate command structure is "*", where "colorCode" is
 * one of "r","g", or "b".
 *      "r"    increases the red LED brightness by 10
 *      "rrr"  increases the red LED brightness by 30
 *      "ggb"  increases the green LED brightness by 20 and the blue by 10
 *
 * Created 18 October 2006
 * copyleft 2006 Tod E. Kurt <tod@todbot.com
 * http://todbot.com/
 *
 * Adapted 5 September 2007
 * copylefter 2007 Ryan Aipperspach <ryanaip@alumni.rice.edu>
 *
 */
 
//include support for manipulating strings.
___________________
___________________
___________________

char serInString[100];  // array that will hold the different bytes of the string. 
char colorCode;
int colorVal;

//these leds will fade on and off
int redPin   = _;   // Red LED,   connected to digital pin 9
int greenPin = _;  // Green LED, connected to digital pin 10
int bluePin  = _;  // Blue LED,  connected to digital pin 11

//create separate variables to hold your pin values
//set them to halfway on
int redValue = ___
___________________
___________________

void setup() {
  // set the pins as output
     _____________________
     _____________________
     _____________________

//set up serial at a baudrate 9600
  _____________________
  
 //turn each light on use the pin values to turn them on halfway
  _____________________
  _____________________
  _____________________
  
  //Give user directions to program
  Serial.println("enter color command (e.g. 'r43 or rrrrrrrrbbbb') :");  
}

void loop () {
  //read the serial port and create a string out of what you read
  readSerialString(serInString, 100);

  
    
  //INCLUDE A FUNCTION CALL HERE OR NOTHING WILL HAPPEN
  //WHAT FUNCTION? LOOK BELOW AND PICK ONE OR WRITE YOUR OWN
  
  
  //Erase anything left in the serial string, preparing it for the 
  //next loop
  resetSerialString(serInString, 100);  

  delay(100);  // wait a bit, for serial data
}

void resetSerialString (char *strArray, int length) {
  for (int i = 0; i < length; i++) {
    strArray[i] = '\0';
  }
}

//read a string from the serial and store it in an array
//you must supply the array variable
void readSerialString (char *strArray, int maxLength) {
  int i = 0;

  if(!Serial.available()) {
    return;
  }
  while (Serial.available() && i < maxLength) {
    strArray[i] = Serial.read();
    i++;
  }
}


//go through the string, and increase the red value for each 'r',
//the green value for each 'g', and the blue value for each 'b'.
//For example "rrrg" increases red by 30 and green by 10.
void processRepeatKeyCommands(char *strArray, int maxLength) {
  int i = 0;
  
  //loop through the string (strArray)
  //i = the current position in the string
  //Stop when either (a) i reaches the end of the string or
  //                 (b) there is an empty character '\0' in the string
  while (i < maxLength && strArray[i] != '\0') {
    //Read in the character at position i in the string
    colorCode = serInString[i];
    
    //If the character is r (red)...
    if (colorCode == 'r') {
      //Increase the current red value by 10, and if you reach 255 go back to 0
      redValue = (redValue + 10) % 255;
      analogWrite(redPin, redValue);
      Serial.print("setting color r to ");
      Serial.println(redValue);
      
    //If the character is g (green)...
    } _________________________
      _________________________
      _________________________
      _________________________
      _________________________
    
    //If the character is b (blue)...
    } _________________________
      _________________________
      _________________________
      _________________________
      _________________________
    }
    
    //Move on to the next character in the string
    //From here, the code continues executing from the "while" line above...
    i++;
  }
}

//change the value of the red, green, or blue LED according to the command received.
//for example, r240 sets the red LED to the value 240 (out of 255)
void processNumericalCommands(char *strArray) {
  //read in the first character in the string
  colorCode = serInString[0];
  
  //if the first character is r (red), g (green) or b (blue), do the following...
  if( colorCode == 'r' || colorCode == 'g' || colorCode == 'b' ) {
    //convert the string to an integer
    //(start at the second character, or the beginning of the string '+1')
    
    colorVal = atoi(serInString+1);
    Serial.print("setting color ");
    Serial.print(colorCode);
    Serial.print(" to ");
    Serial.print(colorVal);
    Serial.println();

    if(colorCode == 'r') 
      _________________________
    else if(colorCode == 'g')
      _________________________
    else if(colorCode == 'b')
      _________________________
  }
}

boolean stringsEqual(char *string1, char *string2, int numCharacters) {
  if (strncmp(string1, string2, numCharacters) == 0) {
    return true;
  } else {
    return false;
  }
}

Another version of your light

Come up with other ways of controlling the colors of the LEDs using the keyboard. Here's your chance to be creative and show off. Example: Read colors and set the appropriate RGB values like "orange" might set r=70%, g=50%, and b=0%.

Control 3 leds with three pots.

Put 220 Ohm resistors in line with pots, to prevent circuit from grounding out when the pots are at zero.
/*
* "Coffee-cup" Color Mixer:
* Code for mixing and reporting PWM-mediated color
* 
* Control 3 LEDs with 3 potentiometers
* If the LEDs are different colors, and are directed at diffusing surface 
* (placed in a paper coffee cup with a cut-out bottom), the colors will mix together.
*
* When you mix a color you like, stop adjusting the pots.
* The mix values that create that color will be reported in the  serial monitor.
*
* Standard colors for light mixing are Red, Green, and Blue, though you can mix 
*   with any three colors; Red + Blue + White would let you mix shades of red, 
*   blue, and purple (though no yellow, orange, green, or blue-green.)
*
* 
*/

// Analog pin settings with Potentiometers connected to analog pins 0, 1, and 2
__________________
__________________
__________________

// Digital pin settings—LEDs use PWM
__________________
__________________
__________________

// Create variables to store the values of the pots
__________________
__________________
__________________  

// Variables for comparing values between loops
int i = 0;            // Loop counter

//set the delay for 1 second
int wait = __________________


//create a variable to hold the sum of the pot values
__________________

//create a variable to hold the previous sum of pot values
__________________

//create a variable  to hold the sensitivity threshold
//this will prevent smal changes in pot values from triggering
//false reporting.
//set this variable to 3
__________________




void setup(){
// set the led pins as output
     _____________________
     _____________________
     _____________________

 //set up serial at a baudrate 9600
  _____________________
}

void loop(){
//increment loop counter by 1
________________________

// read input pins, convert to 0-255 scale
________________________
________________________
________________________


// Send new values to LEDs
________________________
________________________
________________________

//check if enough time has passed 
//you can use the mod operator
//(counter%wait==0)
________________________

//set your sum of pot variable to the sum of pot values
   ________________________

//check that this new sum is greater than the previous sum by the sensitivity threshold variable

   ________________________


      // ...then print the values.
        Serial.print("A: ");        
        Serial.print(aVal);         
        Serial.print("\t"); 
        Serial.print("B: ");        
        Serial.print(bVal);
        Serial.print("\t");
        Serial.print("C: ");                
        Serial.println(cVal); 
       
      }
   
   //set the previous sum to the current sum
   ________________________

    
  }
}