CS 2000 - Program Design in C
Fall 2011

Lab session - Week 11
November 11

Your last two Arduino projects of the semester will deal with infrared communications.  This lab will prepare you for those projects.  In this lab, you will:

This lab is self-paced, but your instructor will be happy to help you with any questions you have as you complete the lab. 

When you finish this lab, have the TA check your work and mark the roll sheet (to get credit).

Safety:

At the beginning of every hardware lab, please review the safety precautions from lab #2.  Remember, please think carefully about your actions.

Find a partner

Students should again work in pairs for this lab and the next two assignments.  You may choose any partner for lab, and you can switch later.  For the Arduino project assignments, once you choose a partner, you will not be allowed to switch.  I recommend choosing a partner whose understanding of the material is equivalent to your own.  (Don't let your partner do all the work.)

Partners on the last two Arduino projects will have to follow the pair programming rules

Both partners should wire up their boards during this lab.

Lab schematic

Here is the schematic for today's lab.  You may also see my completed Arduino circuit by clicking on this picture.

Step 1: Get the parts you need

Come up to the front and check out an IR LED (for creating infrared light) and an IR receiver (for detecting IR light).  Your TA will mark a list when you pick up the parts.  These parts are yours to keep.  There are a few things you should note about the parts:

Once you have a bit of simple code in place, you can easily send and detect infrared signals using these parts.

Step 2: Set up the Arduino project source code

Download this starting code into an Arduino project.  Save the project in your own personal space.

bool transmitting_IR;
bool receiving_IR;


void turn_off_IR ()
{
  // Instead of just adjusting the output on pin 11, this code also
  //   turns off the timer controlling the PWM output on pin 11
  
  TCCR2A = 0; // Disconnect PWM
  TCCR2B = 0; // Stops the timer
  OCR2A = 0;  // No timer top
  digitalWrite(11, LOW);  // Ensure output is off
  
  transmitting_IR = false;
}


void turn_on_IR ()
{
// Set up Timer2 (which can be connected to pins 3 and 11)
  // For full details, see:
  //   arduino.cc/en/Tutorial/SecretsOfArduinoPWM
  // The syntax here has me baffled, but the patterns of usage
  //   are clear if you look at the ATMega328 diagrams.
  //   _BV appears to stand for 'bit value'
  //   Different bits need to be set to control each timer
  //   Refer to diagrams for clarity

  TCCR2A = _BV(WGM21) | _BV(COM2A0); // This mode toggles output once per timer cycle
  TCCR2B = _BV(CS20);  // Do not scale the clock down - use 16 MHz timer rate.
  OCR2A = 210; // Divide sys. clock by 210, 1/2 cycle = 76 khz, 1 cycle = 38 khz
  
  // Output pin 11 should now be emitting a 38 khz signal.
  
  transmitting_IR = true;
}


bool detect_IR()
{
  // Determine if we are receiving an IR signal.
  //   if pin 12 is false = receiving
  //   if pin 12 is true = not receiving
  
  return receiving_IR = ! digitalRead(12);  
}


void setup ()
{
  Serial.begin(9600);
  
  pinMode (4, INPUT);      // Button
  digitalWrite (4, HIGH);  // Button pull-up resistor
  
  pinMode (11, OUTPUT); // IR LED
  pinMode (12, INPUT);  // IR receiver
  
  turn_off_IR();  // My helper function for controlling the IR LED
  detect_IR();    // Ensure the state is correct.
}

Review this code - the functions help with both transmission and reception of IR signals.  Here are the key ideas:

Note:  The functions and global variables are not the ideal way to send or receive IR signals.  They are a bit 'slow', and the code can be written more compactly if performance or timing is critical.  On the other hand, for teaching reasons I feel this arrangement is ideal.

Step 3: Assemble and test the button

Wire up a button to your Arduino as follows:


Picture of completed button wiring

Note:  Since the left and right side pins of the button are connected through the button, you can connect your wires to either side of the button.  (See above schematic.)

The setup() function that you downloaded already sets up this button.  Here is the code again for review:

  pinMode (4, INPUT);      // Button
  digitalWrite (4, HIGH);  // Button pull-up resistor

The first line sets up pin 4 as an input, and the second line activates the internal pull-up resistor.  The input will be high as long as the button is not pressed.  As soon as the button is pressed, a path to ground is created and the input will become low.

It's time to test the button.  Copy this loop function to the end of your Arduino project:

void loop ()
{
  // Check button state
  //   0 = pressed
  //   1 = not pressed

  delay(100);  // Remove this in the next step
  bool button_pressed = ! digitalRead(4);
  
  if (! button_pressed)
    Serial.write('o');
  
  if (button_pressed)
    Serial.write('x');
}

Download your completed code into your Arduino.  Open up the serial debugging window.  You should be receiving a lot of 'o' characters.  When you press the button, these should change to 'x' characters.  Make sure the button works before proceeding.

Step 4: Assemble the IR transmitter

Because the IR LED emits invisible light, you will wire up a second visible-light LED to the same output.  That way, when the IR LED is on, the second LED will also be on.  (This is possible because the Arduino outputs enough power for both LEDs.)  Wire up the LEDs as shown below:


Picture of infrared LED wiring
Picture of debugging LED wiring

In the pictures above, notice that I put a bend in the leads of my IR LED so that it points horizontally towards the front of the board.  I want the IR light to shine directly on my receiver.

Because you have a debugging LED hooked up to the output pin, you should be able to see when the IR LED is transmitting.  Change your loop() function as follows:

void loop ()
{
  // Check button state
  //   0 = pressed
  //   1 = not pressed
  bool button_pressed = ! digitalRead(4);
  
  if (transmitting_IR && ! button_pressed)
    turn_off_IR();
  
  if (!transmitting_IR && button_pressed)
    turn_on_IR();  
}

The code now uses the button to control the IR LED output.  Try it.  When you press the button, the IR LED and debugging LED should light up.  (You'll only be able to see the debugging LED, and it may appear a bit dim because it is turning on and off 38,000 times each second.)  Make sure the button controls the LEDs before moving on.

Step 5: Assemble the IR receiver

The debugging LED above is very useful.  You'll add one to the IR receiver as well so that you can see when it is receiving an IR signal.  Wire up the IR receiver as follows:


Picture of IR receiver wiring
Picture of second debugging LED wiring

Note:  The second debugging LED is wired up to a resistor and +5 volts, not ground.  The receiver outputs a low signal when it receives data, so I use the low as the ground for the LED.  That way, the LED will illuminate when data is received.  Care is required to orient the LED properly.  In my wiring I was clever about how I connected the LED to +5 volts -- I made use of the +5 volts being supplied to the receiver.

Double-check the wiring, then proceed to step 6.

Step 6: Finish and test the software

A simple way to test the receiver is to simply write some statements to check for reception.  The code below checks for received IR light, and if it is detected, it determines the length of time that the light is received.  Copy this code to the end of your loop() function:

// See if the IR is on.
  
  detect_IR();
  
  // Keep track of the total receiving time in
  //   microseconds.
  
  // If we're not started, but a bit is coming in...
  
  if (!bit_started && receiving_IR)
  {
     // Start keeping track of time.
     
     bit_started = true;
     start_time = micros();
  }
  
  // If we've started, but the bit stopped...
  
  if (bit_started && !receiving_IR)
  {
    // Stop keeping track of time.
    
    bit_started = false;
    end_time = micros();
    unsigned long elapsed_time = end_time - start_time;
    
    // Send the time out the serial port for debugging
    
    Serial.println (elapsed_time);
  }

In addition, add these global variables to the top of your code:

bool bit_started = false;
unsigned long start_time;
unsigned long end_time;

Again download your code to the Arduino and open up the serial debugging window.  Every time your receiver 'sees' a pulse of infrared light, your code will compute the elapsed time and send it out the serial port to the debugging window.  Try the following:

Caution:  A lot of students will be testing their boards.  You may see pulses from their tests.

Step 7: Modify the software

The code only displays the 'on' time for each light pulse.  When you press the button on your project, the IR light is sent and then detected by your receiver.  Your code then computes the total length of time that the light is received.  This is useful, but you need more information to send data.

Adapt the code so that when the 'on' time is sent, it puts a small message in front of it like this (in the debugging window):

  IR signal:  234170

(Use Serial.print("...") to add this additional message to the appropriate part of the code.)

Next, adapt the code so that it also measures the length of time between pulses.  In other words, measure the length of time during which the receiver is not receiving data.  Display a message like this to the debugging window:

  IR Dark:  234170

Once you get this working you have completed the lab.  Find a partner for the next project and begin discussing how you would send characters between Arduino boards using infrared signals.

Check off

Demonstrate your working IR transmitter and receiver for the TA.  Your TA will mark the roll to give you credit for the lab.

If you missed lab...

The lab instructor gave out parts during lab.  Please see Peter Jensen in his office to get the needed parts.  You should complete this lab as it is the basis of the next Arduino project.

Page updated Friday November 11, 2011 at 10:29:36.