Wednesday, 28 April 2010

Sleeping Arduino - Part 3 Wake Up Via the UART

Overview
In the third part of this "Sleeping Arduino" series, we will be covering how to wake the Arduino via the USB UART (serial interface over USB). When the Arduino's ATMEGA microcontroller is not receiving any communications from the PC via the serial link, it will enter a sleep mode (the very efficient 
SLEEP_MODE_PWR_DOWN, see here for more info on the power modes). Once serial data is sent from the PC to the Arduino board, it will wake for a period and re-enter sleep mode when no data is being received from the PC.

To wake the ATMEGA, we will be using the external interrupt INT0 on digital Pin 2 of the ATMEGA (as covered in Part 2 of this series), connected to the digital Pin 0 (which is the ATMEGA's UART receive line).

To do this we will use the following hardware:
  • Arduino Diecimila with usb cable (or a Freeduino, which is 100% Arduino Diecimila compatible)
  • One 220 Ohm Resistor

If you don't want to use a resistor, you can use a less efficient power mode mode and wake the Arduino using the UART interrupt as specified in Ruben's blog entry here.

USB UART
The following schematics show two of the devices on the Arduino Board. The first is the ATMEGA8 (could also be ATMEGA168) microcontroller, the other is the FT232RL, which is the USB UART interface device.
Note the TXD and RXD pins of the FT232RL are connected to the RXD and TXD of the ATMEGA respectively. These pins are exposed on J1 as digital pins 0 and 1.




When there is no data being transmitted on the serial TX and RX lines, they are pulled high at 5volts. Once data is transmitted the lines will change state with the data. We will use the initial state change to low to fire our external interrupt and wake the ATMEGA.

Circuit
The circuit for this entry is very basic. On your Arduino board just connect one leg of the 220 Ohm resistor into digital pin 0 (RX) and the second leg into digital pin 2 (INT0) on connector J1.

Source Code
The source code for this is exactly the same as the source code for Part 2 of this series.


#include <avr/sleep.h>
#include <avr/power.h>


int pin2 = 2;


/***************************************************
 *  Name:        pin2Interrupt
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Service routine for pin2 interrupt  
 *
 ***************************************************/
void pin2Interrupt(void)
{
  /* This will bring us back from sleep. */
  
  /* We detach the interrupt to stop it from 
   * continuously firing while the interrupt pin
   * is low.
   */
  detachInterrupt(0);
}


/***************************************************
 *  Name:        enterSleep
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Enters the arduino into sleep mode.
 *
 ***************************************************/
void enterSleep(void)
{
  
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(0, pin2Interrupt, LOW);
  delay(100);
  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  
  sleep_enable();
  
  sleep_mode();
  
  /* The program will continue from here. */
  
  /* First thing to do is disable sleep. */
  sleep_disable(); 
}


/***************************************************
 *  Name:        setup
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Setup for the Arduino.           
 *
 ***************************************************/
void setup()
{
  Serial.begin(9600);
  
  /* Setup the pin direction. */
  pinMode(pin2, INPUT);
  
  Serial.println("Initialisation complete.");
}



/***************************************************
 *  Name:        loop
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Main application loop.
 *
 ***************************************************/
int seconds=0;
void loop()
{
  delay(1000);
  seconds++;
  
  Serial.print("Awake for ");
  Serial.print(seconds, DEC);
  Serial.println(" second");
  
  if(seconds == 3)
  {
    Serial.println("Entering sleep");
    delay(200);
    seconds = 0;
    enterSleep();
  }
}


This source code can be downloaded here.


All parts of this series:

2 comments:

  1. thanks a bunch for these sleeping arduino tutorials, they have been very helpful.

    i hope you start writing again!

    ReplyDelete
  2. I have tried this code, and this is works ! mm but If I want to awake arduino with serial data which I choose (ex: just send character "A" and then arduino wake up ) /not receiving any serial data ? I really2 confuse,, I start depressed because that, can you help me ?? plis T___T

    ReplyDelete