Mã dưới đây đạt được những gì bạn đang yêu cầu:
#include <avr/sleep.h>
#include <avr/power.h>
const byte AWAKE_LED = 8;
const byte GREEN_LED = 9;
const unsigned long WAIT_TIME = 5000;
ISR (PCINT2_vect)
{
// handle pin change interrupt for D0 to D7 here
} // end of PCINT2_vect
void setup()
{
pinMode (GREEN_LED, OUTPUT);
pinMode (AWAKE_LED, OUTPUT);
digitalWrite (AWAKE_LED, HIGH);
Serial.begin (9600);
} // end of setup
unsigned long lastSleep;
void loop()
{
if (millis () - lastSleep >= WAIT_TIME)
{
lastSleep = millis ();
noInterrupts ();
byte old_ADCSRA = ADCSRA;
// disable ADC
ADCSRA = 0;
// pin change interrupt (example for D0)
PCMSK2 |= bit (PCINT16); // want pin 0
PCIFR |= bit (PCIF2); // clear any outstanding interrupts
PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
UCSR0B &= ~bit (RXEN0); // disable receiver
UCSR0B &= ~bit (TXEN0); // disable transmitter
sleep_enable();
digitalWrite (AWAKE_LED, LOW);
interrupts ();
sleep_cpu ();
digitalWrite (AWAKE_LED, HIGH);
sleep_disable();
power_all_enable();
ADCSRA = old_ADCSRA;
PCICR &= ~bit (PCIE2); // disable pin change interrupts for D0 to D7
UCSR0B |= bit (RXEN0); // enable receiver
UCSR0B |= bit (TXEN0); // enable transmitter
} // end of time to sleep
if (Serial.available () > 0)
{
byte flashes = Serial.read () - '0';
if (flashes > 0 && flashes < 10)
{
// flash LED x times
for (byte i = 0; i < flashes; i++)
{
digitalWrite (GREEN_LED, HIGH);
delay (200);
digitalWrite (GREEN_LED, LOW);
delay (200);
}
}
} // end of if
} // end of loop
Tôi đã sử dụng ngắt thay đổi pin trên chân Rx để thông báo khi dữ liệu nối tiếp đến. Trong thử nghiệm này, bo mạch sẽ chuyển sang chế độ ngủ nếu không có hoạt động nào sau 5 giây (đèn LED "tỉnh táo" tắt). Dữ liệu nối tiếp đến làm gián đoạn thay đổi pin để đánh thức bảng. Nó tìm kiếm một số và nhấp nháy đèn LED "xanh" số lần đó.
Đo hiện tại
Chạy ở 5 V, tôi đo được khoảng 120 nA dòng điện khi ngủ (0.120 MartA).
Tin nhắn thức tỉnh
Tuy nhiên, có một vấn đề là byte đến đầu tiên bị mất do phần cứng nối tiếp mong đợi mức giảm trên Rx (bit start) đã đến khi nó hoàn toàn tỉnh táo.
Tôi đề nghị (như trong câu trả lời của geometrikal) trước tiên bạn gửi tin nhắn "tỉnh táo", sau đó tạm dừng trong một thời gian ngắn. Việc tạm dừng là để đảm bảo phần cứng không diễn giải byte tiếp theo như một phần của thông báo tỉnh táo. Sau đó nó sẽ hoạt động tốt.
Vì điều này sử dụng ngắt thay đổi pin, không yêu cầu phần cứng nào khác.
Phiên bản sửa đổi bằng SoftwareSerial
Phiên bản dưới đây xử lý thành công byte đầu tiên nhận được trên serial. Nó thực hiện điều này bằng cách:
Lấy cảm hứng từ FarO trong một bình luận, điều này cho phép bộ xử lý thức dậy trong 6 chu kỳ đồng hồ (750 ns). Với tốc độ 9600 baud mỗi bit thời gian là 1/9600 (104,2 Pha) nên độ trễ thêm không đáng kể.
#include <avr/sleep.h>
#include <avr/power.h>
#include <SoftwareSerial.h>
const byte AWAKE_LED = 8;
const byte GREEN_LED = 9;
const unsigned long WAIT_TIME = 5000;
const byte RX_PIN = 4;
const byte TX_PIN = 5;
SoftwareSerial mySerial(RX_PIN, TX_PIN); // RX, TX
void setup()
{
pinMode (GREEN_LED, OUTPUT);
pinMode (AWAKE_LED, OUTPUT);
digitalWrite (AWAKE_LED, HIGH);
mySerial.begin(9600);
} // end of setup
unsigned long lastSleep;
void loop()
{
if (millis () - lastSleep >= WAIT_TIME)
{
lastSleep = millis ();
noInterrupts ();
byte old_ADCSRA = ADCSRA;
// disable ADC
ADCSRA = 0;
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
sleep_enable();
digitalWrite (AWAKE_LED, LOW);
interrupts ();
sleep_cpu ();
digitalWrite (AWAKE_LED, HIGH);
sleep_disable();
power_all_enable();
ADCSRA = old_ADCSRA;
} // end of time to sleep
if (mySerial.available () > 0)
{
byte flashes = mySerial.read () - '0';
if (flashes > 0 && flashes < 10)
{
// flash LED x times
for (byte i = 0; i < flashes; i++)
{
digitalWrite (GREEN_LED, HIGH);
delay (200);
digitalWrite (GREEN_LED, LOW);
delay (200);
}
}
} // end of if
} // end of loop
Tiêu thụ điện năng khi ngủ được đo là 260 nA (0,260, một) vì vậy mức tiêu thụ rất thấp khi không cần thiết.
Lưu ý rằng với các cầu chì được đặt như vậy, bộ xử lý chạy ở tốc độ 8 MHz. Do đó, bạn cần nói với IDE về điều đó (ví dụ: chọn "Lilypad" làm loại bảng). Bằng cách đó, độ trễ và SoftwareSerial sẽ hoạt động với tốc độ chính xác.