Hello, recently I wanted to configure a pushbutton on interrupt pin 1 (digital pin 3) on the Arduino Uno that would wake it up. Once the intterupt reads a LOW from intterupt pin 3, Arduino wakes up, starts a timer counting up to ten seconds, runs a loop the entire ten seconds, then go back into 'sleep mode' after the timer reaches ten seconds. This url helped me:
http://playground.arduino.cc/Learning/ArduinoSleepCode
Basically I copied the code to see what would happen. Here is the code:
#include <Servo.h>
#include <avr/sleep.h>
int wakePin = 3;
int sleepStatus = 0;
int count = 0;
const int locked = 0;
const int unlocked = 180;
Servo deadbolt;
void wakeUp() {
deadbolt.attach(9);
deadbolt.write(locked);
}
void setup() {
pinMode(wakePin, INPUT);
Serial.begin(9600);
attachInterrupt(1, wakeUp, LOW);
}
void sleepNow() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(1, wakeUp, LOW);
sleep_mode();
sleep_disable();
detachInterrupt(1);
}
void loop() {
Serial.print("Awake for ");
Serial.print(count);
Serial.println(" seconds");
count++;
delay(1000);
if( Serial.available()) {
int val = Serial.read();
if( val == 'S') {
Serial.println("Serial: Entering Sleep Mode");
delay(100);
count = 0;
sleepNow();
}
if(val == 'A') {
Serial.println("Hola Caracola");
}
}
if ( count >= 10 ) {
Serial.println("Timer: Entering Sleep Mode");
delay(100);
count = 0;
sleepNow();
}
}
Every time I push the button connected to digital pin 3, the timer starts and counts ten seconds and goes into sleep mode. Now that the Arduino goes into 'sleep mode' I tried inserted my other program to run while it was awake for the ten seconds.
Code here:
#include <Wire.h>
#include <Adafruit_NFCShield_I2C.h>
#include <Servo.h>
#include <avr/sleep.h>
int wakePin = 3;
int sleepStatus = 0;
int count = 0;
#define IRQ (2)
#define SS_PIN (6) // Not connected by default on the NFC Shield
Adafruit_NFCShield_I2C nfc(IRQ, SS_PIN);
Servo deadbolt;
const int locked = 0;
const int unlocked = 180;
int pos;
void setup(void) {
attachInterrupt(1, WakeUp, RISING); //1=digitalpin3, WakeUp is the function to call, triggers on a rising edge
Serial.begin(115200);
Serial.println("Looking for PN532...");
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// configure board to read RFID tags
nfc.SAMConfig();
Serial.println("Waiting for an ISO14443A Card ...");
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void WakeUp() {
deadbolt.attach(9);
deadbolt.write(locked);
rfid();
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void rfid() {
Serial.println(count);
pos = deadbolt.read();
byte j_card[4] = { 0xCD, 0xBF, 0xC1, 0x78 };
volatile boolean valid;
uint8_t success; // Flag to check if there was an error with the PN532
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
uint8_t currentblock; // Counter to keep track of which block we're on
bool authenticated = false; // Flag to indicate if the sector is authenticated
uint8_t data[16]; // Array to store block data during reads
// Keyb on NDEF and Mifare Classic should be the same
uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
// 'uid' will be populated with the UID, and uidLength will indicate
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
if (success) {
if ( pos <= 10 ) {
deadbolt.write(unlocked);
delay(1000);
return;
}
else if ( pos >= 10 ) {
deadbolt.write(locked);
delay(1000);
return;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void loop(void) {
pinMode(wakePin, INPUT);
Serial.print(count);
count++;
delay(1000);
if ( count == 10 ) {
delay(100);
count = 0;
sleepNow();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void sleepNow() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(1, WakeUp, LOW);
sleep_mode();
sleep_disable();
detachInterrupt(1);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
PROBLEM
When awake, my rfid(){} is supposed to run. Currently I cannot have the timer running and rfid(){} at the same time. First I tried to put them both in void loop(){}, but the timer would count to ten and shut the Arduino off without running the other code in void loop(){}. I researched interrupts(); and noInterrupts(); and want my current loop to run in the background and void rfid(){} to run in the loop(){}.
QUESTION
How do have a timer run in the background to re initiate 'sleep mode' while void rfid(); runs as the main loop?