Adruino - Sleep ModeSleep.
How to let your Arduino go to sleep and wake up on an external event.
Preface
Sleep is commonly used to save power on Arduino boards. For some Arduino variants, however, there is not much benefit. For example, the Arduino serial and USB boards use a 7805 type of power regulator, which needs 10mA when the Atmega IC is in idle mode. Putting these boards to sleep will cut a few mA off the total power consumption however it will still be high.
If you bypass the inefficient regulator with your own power supply circuit, or use a board with a fairly efficient power supply, such as an Arduino Pro, then sleep can be very beneficial for reducing power and extending battery life. The regulator can even be removed altogether when using some Li-ion batteries.
Figure 1: a 220 Ohm resistor connects RX to pin 2
Global Principle
Sleep is assisted by interrupts. without them, only a reset can wake the Arduino up again. Fortunately interrupts are incorporated since the 0007 version of the Arduino IDE.
On the hardware front, the Arduino is equipped with two interrupt ports: digital pin 2 and 3. So the Arduino can sense those pins for an event to wake up and resume execution of code. It is even possible to execute special code depending on which pin triggered the wake up (the interrupt).
Events on the USART (the serial port) will also wake up the Arduino. In order for this to work, the Arduino must be in POWER_MODE_IDLE, the only power mode that doesn't disable the USART. Although this mode doesn't give great power savings you can use the functions provided in avr/power.h ( power_adc_disable(),power_spi_disable(),power_timer0_disable(), power_timer1_disable(),power_timer2_disable(),power_twi_disable()) to disable other hardware modules to achieve greater power savings. See this link for example code.
Because of the dominant way an interrupt breaks in in the execution of the main code, it is wise to make the code executed by an interrupt as short as possible. Maybe even just set a variable which will be handled in the main program. As long as the code for the interrupt runs, internal timers are waiting.
Level Interrupts
When the arduino is in SLEEP_MODE_PWR_DOWN the only way to wake it is with either a watchdog timer interrupt or a level interrupt on pins 2 or 3.
A level interrupt means that the pin has to be held in that state for a certain amount of time before the interrupt is triggered. In the interrupt service routine (ISR) for a level interrupt, the interrupt must be detached otherwise the interrupt will keep happening and the ISR will be repeatedly called until the pin changes state.
void pin2_isr()
{
detachInterrupt(0);
pin2_interrupt_flag = 1;
}
[Get Code]
As a consequence, the interrupt must be re-enabled in the code once the pin has gone back to a normal state, i.e. for a low level interrupt, check that the pin has gone high before attaching the interrupt again.
Warning Code like this, which is a typical example of sleep code, can cause a problem if you are relying on the interrupt to wake you from sleep:
attachInterrupt(0, pin2_isr, LOW);
/* 0, 1, or many lines of code here */
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_enable();
sleep_bod_disable();
sei();
sleep_cpu();
/* wake up here */
sleep_disable();
[Get Code]
The problem is if the interrupt occurs after attachInterrupt but before sleep_cpu(). The ISR will run, the interrupt will be detached, and then the CPU will enter sleep mode with no interrupt enabled. The MCU will never wake up this way. Fortunately there is a solution. The sleep enable bit can be cleared during the ISR and thus the MCU will not go to sleep. The sleep_enable() command also goes above the attachInterrupts function. e.g.
sleep_enable();
attachInterrupt(0, pin2_isr, LOW);
/* 0, 1, or many lines of code here */
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_bod_disable();
sei();
sleep_cpu();
/* wake up here */
sleep_disable();
[Get Code]
void pin2_isr()
{
sleep_disable();
detachInterrupt(0);
pin2_interrupt_flag = 1;
}
[Get Code]
Example
This code makes use of the Serial port to receive commands. In parallel to that it will count 10 seconds before going into sleep mode. The 220 Ohm resistor keeps pin 2 HIGH (because RX is internally pulled-up to 5V when used as Serial port) until there is serial information coming in.
Note to the author: there is no need for a resistor between RX and pin 2 and the above statement is rather confusing. In fact RX and pin 2 can be connected directly as RX is already connected to the output of the USB to serial converter and a serial line when in idle state is at logic HIGH (in TTL that means 5V). So pin 2 is effectively already pulled up at a HIGH state. A resistor may only be useful to limit contention between two outputs if one programs pin 2 as output by mistake (pins are input by default anyway), though current is already internally limited to 40mA.
Note to the author #2: The attachInterrupt function is being called in the setup routine (line 68) and the sleepNow function (line 118). From the comments in the sleepNow function, I suspect that the call in the setup routine should be removed.
#include <avr/sleep.h>
/* Sleep Demo Serial
* -----------------
* Example code to demonstrate the sleep functions in an Arduino.
*
* use a resistor between RX and pin2. By default RX is pulled up to 5V
* therefore, we can use a sequence of Serial data forcing RX to 0, what
* will make pin2 go LOW activating INT0 external interrupt, bringing
* the MCU back to life
*
* there is also a time counter that will put the MCU to sleep after 10 secs
*
* NOTE: when coming back from POWER-DOWN mode, it takes a bit
* until the system is functional at 100%!! (typically <1sec)
*
* Copyright (C) 2006 MacSimski 2006-12-30
* Copyright (C) 2007 D. Cuartielles 2007-07-08 - Mexico DF
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
int wakePin = 2; // pin used for waking up
int sleepStatus = 0; // variable to store a request for sleep
int count = 0; // counter
void wakeUpNow() // here the interrupt is handled after wakeup
{
// execute code here after wake-up before returning to the loop() function
// timers and code using timers (serial.print and more...) will not work here.
// we don't really need to execute any special functions here, since we
// just want the thing to wake up
}
void setup()
{
pinMode(wakePin, INPUT);
Serial.begin(9600);
/* Now it is time to enable an interrupt. In the function call
* attachInterrupt(A, B, C)
* A can be either 0 or 1 for interrupts on pin 2 or 3.
*
* B Name of a function you want to execute while in interrupt A.
*
* C Trigger mode of the interrupt pin. can be:
* LOW a low level trigger
* CHANGE a change in level trigger
* RISING a rising edge of a level trigger
* FALLING a falling edge of a level trigger
*
* In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
// wakeUpNow when pin 2 gets LOW
}
void sleepNow() // here we put the arduino to sleep
{
/* Now is the time to set the sleep mode. In the Atmega8 datasheet
*
http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
* there is a list of sleep modes which explains which clocks and
* wake up sources are available in which sleep mode.
*
* In the avr/sleep.h file, the call names of these sleep modes are to be found:
*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*
* For now, we want as much power savings as possible, so we
* choose the according
* sleep mode: SLEEP_MODE_PWR_DOWN
*
*/
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable(); // enables the sleep bit in the mcucr register
// so sleep is possible. just a safety pin
/* Now it is time to enable an interrupt. We do it here so an
* accidentally pushed interrupt button doesn't interrupt
* our running program. if you want to be able to run
* interrupt code besides the sleep function, place it in
* setup() for example.
*
* In the function call attachInterrupt(A, B, C)
* A can be either 0 or 1 for interrupts on pin 2 or 3.
*
* B Name of a function you want to execute at interrupt for A.
*
* C Trigger mode of the interrupt pin. can be:
* LOW a low level triggers
* CHANGE a change in level triggers
* RISING a rising edge of a level triggers
* FALLING a falling edge of a level triggers
*
* In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
// wakeUpNow when pin 2 gets LOW
sleep_mode(); // here the device is actually put to sleep!!
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
sleep_disable(); // first thing after waking from sleep:
// disable sleep...
detachInterrupt(0); // disables interrupt 0 on pin 2 so the
// wakeUpNow code will not be executed
// during normal running time.
}
void loop()
{
// display information about the counter
Serial.print("Awake for ");
Serial.print(count);
Serial.println("sec");
count++;
delay(1000); // waits for a second
// compute the serial input
if (Serial.available()) {
int val = Serial.read();
if (val == 'S') {
Serial.println("Serial: Entering Sleep mode");
delay(100); // this delay is needed, the sleep
//function will provoke a Serial error otherwise!!
count = 0;
sleepNow(); // sleep function called here
}
if (val == 'A') {
Serial.println("Hola Caracola"); // classic dummy message
}
}
// check if it should go to sleep because of time
if (count >= 10) {
Serial.println("Timer: Entering Sleep mode");
delay(100); // this delay is needed, the sleep
//function will provoke a Serial error otherwise!!
count = 0;
sleepNow(); // sleep function called here
}
}
[Get Code]
OLD: example code for 0007
This code assumes Arduino-0007. It uses calls to the included interrupts.c file in the distribution. If you find a way to make it run in older versions of the IDE, please attach the needed alterations underneath this page.
#include <avr/interrupt.h>
#include <avr/sleep.h>
/* Sleep Demo
* ------------
* Example code to demonstrate the sleep functions in a Arduino.
*
* use a pull up resistor on pin 2 and 12 to 5V.
* attach a led with resistor to gnd on pin 10.
* ground pin 12 momentary to put the Arduino to sleep
* and ground pin 2 momentary to wake it up again.
*
* When awake, the arduino will run the led_blink code
* from the example sketchbook, Created 1 June 2005
* by DojoDave <http://www.0j0.org>
*
http://arduino.berlios.de * who based it on an orginal by H. Barragan for the Wiring i/o board
*
* Hacked together by MacSimski 30-12-2006.
*/
int ledPin = 13; // LED connected to digital pin 13
int sleepPin = 12; // active LOW, ground this pin momentary to sleep
int interruptPin = 10; // LED to show the action of a interrupt
int wakePin = 2; // active LOW, ground this pin momentary to wake up
int sleepStatus = 0; // variable to store a request for sleep
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
pinMode(interruptPin, OUTPUT); //
pinMode(sleepPin, INPUT); // sets the digital pin as input
pinMode(wakePin, INPUT);
/* Now is time to enable a interrupt. In the function call
* attachInterrupt(A, B, C)
* A can be either 0 or 1 for interrupts on pin 2 or 3.
*
* B Name of a function you want to execute while in interrupt A.
*
* C Trigger mode of the interrupt pin. can be:
* LOW a low level trigger
* CHANGE a change in level trigger
* RISING a rising edge of a level trigger
* FALLING a falling edge of a level trigger
*
* In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
// wakeUpNow when pin 2 gets LOW
}
void sleepNow() // here we put the arduino to sleep
{
/* Now is the time to set the sleep mode. In the Atmega8 datasheet
*
http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
* there is a list of sleep modes which explains which clocks and
* wake up sources are available in which sleep modus.
*
* In the avr/sleep.h file, the call names of these sleep modus are to be found:
*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*
* For now, we want as much power savings as possible,
* so we choose the according sleep modus: SLEEP_MODE_PWR_DOWN
*
*/
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable(); // enables the sleep bit in the mcucr register
// so sleep is possible. just a safety pin
/* Now is time to enable a interrupt. we do it here so an
* accidentally pushed interrupt button doesn't interrupt
* our running program. if you want to be able to run
* interrupt code besides the sleep function, place it in
* setup() for example.
*
* In the function call attachInterrupt(A, B, C)
* A can be either 0 or 1 for interrupts on pin 2 or 3.
*
* B Name of a function you want to execute at interrupt for A.
*
* C Trigger mode of the interrupt pin. can be:
* LOW a low level triggers
* CHANGE a change in level triggers
* RISING a rising edge of a level triggers
* FALLING a falling edge of a level triggers
*
* In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
// wakeUpNow when pin 2 gets LOW
sleep_mode(); // here the device is actually put to sleep!!
//
sleep_disable(); // first thing after waking from sleep:
// disable sleep...
detachInterrupt(0); // disables interrupt 0 on pin 2 so the
// wakeUpNow code will not be executed
// during normal running time.
delay(1000); // wat 2 sec. so humans can notice the
// interrupt.
// LED to show the interrupt is handled
digitalWrite (interruptPin, LOW); // turn off the interrupt LED
}
void wakeUpNow() // here the interrupt is handled after wakeup
{
//execute code here after wake-up before returning to the loop() function
// timers and code using timers (serial.print and more...) will not work here.
digitalWrite(interruptPin, HIGH);
}
void loop()
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
sleepStatus = digitalRead(sleepPin); // read sleep pin here. only active
//when blink led is off.
if (sleepStatus == LOW) { // start to put the device in sleep
sleepNow(); // sleep function called here
}
}
[Get Code]
مرسلة بواسطة Ahmed Mohamed في 7:20 ص ليست هناك تعليقات:
إرسال بالبريد الإلكتروني
كتابة مدونة حول هذه المشاركة
المشاركة في Twitter
المشاركة في Facebook
الجمعة، 12 أكتوبر، 2012
مكتبة صوت جاهزة للوحات Arduino
بسم الله الرحمن الرحيم
اود اليوم ان اشارككم بمكتبة صوتية جاهزة يمكن استخدامها مع لوحات Arduino بستخدام جملة tone مثل
tone(pinNumber, toneName)
حيث PinNumber هى رقم البن الخاص بالسماعة و الطرف الاخر منها هو الارضى او السالب و ToneName هو اسم المتغير الخاص فى المكتبة لان كل متغير يحمل تردد صوت معين يمكن تنفيذة
ولالغاء العملية نقوم بكتابة noTone فقط
اما بالنسبة للمكتبة هذة هى:
/*************************************************
* Public Constants
*************************************************/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
قم بارفاقها مع مشروعك عن طريق كتابتها فى تاب جديد مع المشروع باسم pitches.h
او قم بتحميلها مجانا من هنا
https://docs.google.com/open?id=0B5rozy-sWHsBOFJvZWF2M0h5ZzQ