0

I made a 3.3V board and I've put both atmega328p (that I pulled off of a 3.3V pro mini), and an atmega168 that I bootloaded (using USBtinyISP whilst selecting board "Arduino Pro or Pro Mini" and "atmega168 (3.3V, 8MHz") .

Everything works perfectly with the atmega328 - code works and interrupts do as well - which function to pull the Arduino out of sleep when INT0 rises.

However on the Atmega168, the interrupt doesn't seem to work. All the normal code works as expected (communications, instructions etc), just not the interrupt. After the Arduino goes to sleep, I can't wake it since the interrupt isn't working.

Basic code below:

#include <avr/sleep.h>//this AVR library contains the methods that controls the sleep modes

byte interruptPin = 2; //Turn board on/off
unsigned long shutDownTimer = 0; // Timer for shutdown


void setup() {
  Serial.begin(57600);
  pinMode(interruptPin, INPUT); //Set pin d2 to input using the buildin pullup resistor
  Serial.println("Starting");

}

void loop() {
  Serial.println("Awake");
  delay(1000);

  // Shutdown control
  if (digitalRead(interruptPin) == LOW ) {
    Serial.println("Shutdown detected");
    shutDownTimer = millis();
    while (digitalRead(interruptPin) == LOW ) {
      if (millis() - shutDownTimer > 1000) {
        Serial.println("sleep mode triggered");
        Going_To_Sleep();
      }
    }
  }
}

void Going_To_Sleep() {
  sleep_enable();//Enabling sleep mode
  delay(1000);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep
  delay(1000); //wait a second to allow the led to be turned off before going to sleep
  attachInterrupt(0, wakeUp, RISING);//attaching a interrupt to pin d2

  Serial.println("Interrrupt attached");//Print message to serial monitor
  sleep_cpu();//activating sleep mode
  Serial.println("just woke up!");//next line of code executed after the interrupt

}

void wakeUp() {
  sleep_disable();//Disable sleep mode
  detachInterrupt(0); //Removes the interrupt from pin 2;
  Serial.println("Interrrupt Fired - wakeup");//Print message to serial monitor

}

Instead of using "attachInterrupt(0, wakeUp, RISING);" Ive also tried the following which also don't work:

attachInterrupt(INT0, wakeUp, RISING);
attachInterrupt(digitalPinToInterrupt(interruptPin), wakeUp, RISING);
attachInterrupt(32, wakeUp, RISING);  //since its the pin of the chip? Hail Mary
attachInterrupt(2, wakeUp, RISING);  //obviously this won't work, Hail Mary 2

I have no idea why the interrupts aren't working. I have an inkling it might be due to something fuse related within the boot loader, but I don't really understand things at that level (Though I'm happy to dive in with some guidance). Any guidance will be appreciated!

1
  • 1
    Your Serial.println inside the ISR is putting you in danger of locking up there. Test using an LED or something instead.
    – timemage
    Jun 17 at 3:38

2 Answers 2

0

According to the datasheet for the Atmega168:

Note that recognition of falling or rising edge interrupts on INT0 or INT1 requires the presence of an I/O clock, described in Section 6.1 “Clock Systems and their Distribution” on page 23. Low level interrupt on INT0 and INT1 is detected asynchronously. This implies that this interrupt can be used for waking the part also from sleep modes other than idle mode. The I/O clock is halted in all sleep modes except idle mode

In other words, only the LOW interrupt wakes it from sleep.

Having said that, the Atmega328P does wake from sleep with a rising or falling interrupt, as I have previously had confirmed by Atmel, however I can't say for sure that this enhancement (over what is stated in the datasheet) applies to the 168.

You could try doing a bit of testing to confirm that. Maybe rejig so that the interrupt occurs when the signal goes low rather than high, and then use a LOW interrupt and not a RISING one.

Also, don't do serial prints inside an ISR. The modern versions of the library handles that better than in the past, but this may still be an issue. As suggested in a comment, try flashing an LED rather than printing something. Or don't print anything, after all you print something when it wakes up. Why print something extra inside the ISR? That is just asking for trouble.

1
  • I didn't see the information in the Atmega328P data sheet stating that it works with rising, and that the Atmega168 does not work with rising. However it is indeed functioning consistently with what you say. I'll just have to use Atmega328's for this application. Thanks.
    – Troy Cados
    Aug 12 at 9:39
1

Depending on what signal you are using to wake the Arduino, you may also find pin change interrupts an alternative to the edge triggered interrupts you are currently using. These are usually more predictable in behaviour and less subject to nuanced interpretations of the data sheets. See https://playground.arduino.cc/Main/PinChangeInterrupt/ for examples of how to use these.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.