Feather 32u4 Lora and sleep with Reed sensor interrupt

I'm building a mailbox sensor and Arduino sleep code part keeps failing. This is my first attempt to put board to sleep with Reed sensor interrupt awake. I found peaces of code from net and this forum and tried to combine them without success.

I tested first Adafruit_SleepyDog.h -library but it doesn't support interrupts or does it?

My board: adafruit-feather-32u4

Board has 4 interrupts. Do I need to add pullup resistor to reed sensor?
I tested Reed sensor on all interrupts and it behaves the same(Not working right...) I want board to sleep when magnet is connected.

#0 / RX - GPIO #0, also receive (input) pin for Serial1 and Interrupt #2
#1 / TX - GPIO #1, also transmit (output) pin for Serial1 and Interrupt #3
#2 / SDA - GPIO #2, also the I2C (Wire) data pin. There's no pull up on this pin by default so when using with I2C, you may need a 2.2K-10K pullup. Also Interrupt #1
#3 / SCL - GPIO #3, also the I2C (Wire) clock pin. There's no pull up on this pin by default so when using with I2C, you may need a 2.2K-10K pullup. Can also do PWM output and act as Interrupt #0.

Code has attachInterrupt(digitalPinToInterrupt(interruptPin), ReedInterrupt, HIGH); -part. Is the HIGH-mode correct here?

// LORA
#include <LoRa.h>

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

// Define the pins used by the LoRa module
const int csPin = 8;      // LoRa radio chip select
const int resetPin = 4;   // LoRa radio reset
const int irqPin = 7;     // Must be a hardware interrupt pin

// Reed switch and led
const byte ledPin = 5;
const byte interruptPin = 3;

void setup() {
  Serial.begin(115200);


  pinMode(interruptPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH); // Debugging LED is on while board is not sleeping
  delay(2000);

  // Setup LoRa module
  LoRa.setPins(csPin, resetPin, irqPin);

  // Start LoRa module at local frequency
  // 433E6 for Asia
  // 866E6 for Europe
  // 915E6 for North America

  if (!LoRa.begin(866E6)) {
    Serial.println("Starting LoRa failed!");
    while (1)
      ;
  }
  else {
    Serial.println("Starting LoRa OK!");
  }
}

void ReedInterrupt(void) {
  // Wake up section
  detachInterrupt(digitalPinToInterrupt(interruptPin));
}

void enterSleep(void){
  /*
    attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) (recommended)
    attachInterrupt(interrupt, ISR, mode) (not recommended)
    attachInterrupt(pin, ISR, mode) (Not recommended. Additionally, this syntax only works on Arduino SAMD Boards, Uno WiFi Rev2, Due, and 101.)
    
    interrupt: the number of the interrupt. Allowed data types: int.
    pin: the Arduino pin number.
    ISR: the ISR to call when the interrupt occurs; this function must take no parameters and return nothing. This function is sometimes referred to as an interrupt service routine.
    mode: defines when the interrupt should be triggered. Four constants are predefined as valid values:

    LOW to trigger the interrupt whenever the pin is low,
    CHANGE to trigger the interrupt whenever the pin changes value
    RISING to trigger when the pin goes from low to high,
    FALLING for when the pin goes from high to low.
    The Due, Zero and MKR1000 boards allow also:
    HIGH to trigger the interrupt whenever the pin is high.
  */
  attachInterrupt(digitalPinToInterrupt(interruptPin), ReedInterrupt, HIGH);

  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  LoRa.sleep(); // put the radio to sleep
  digitalWrite(ledPin, LOW);
  delay(2000);
  sleep_enable();

	if (digitalRead(interruptPin)){
	sleep_mode();
	}

  // Function continues from here after sleep
  sleep_disable();
  digitalWrite(ledPin, HIGH);
}

void loop() {

//  <Some LORA related stuff here>

  delay(5000);
  enterSleep();
}

have seen Adafruit 32u4 LoRa power management?

Yes, first thing I did was to read all the documents I could find about that board but there was no help for my interrupt problem. I'm using lipo-battery and it's working fine with that power measurement part.

#define VBATPIN A9
   
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2;    // we divided by 2, so multiply back
measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
Serial.print("VBat: " ); Serial.println(measuredvbat);

I tested first Adafruit_SleepyDog.h -library but it doesn't support interrupts or does it?

The watchdog wakeup example in the Adafruit Sleepydog library is an example of an interrupt.

So yes, the library does support wake from interrupts. However, when the processor is sleeping, native USB connections are dropped by the host computer, so Serial.print stops working.

With a new library, always start with the library examples and test them to make sure everything is working, and that you completely understand the actions, before implementing it in your actual application.

Note: if you check the processor data sheet, you will find that wake on RISING or FALLING is supported on the 32U4 only by the four external interrupts, INT0 to INT3.

Is the HIGH-mode correct here?

That depends on how you have the switch wired, which you forgot to mention.

I tried to google sleepydog&interrupt example but couldn't find it anywhere. Arduino examples are only sleep and basicusage which aren't using interrupts. If you found it somewhere, please provide a link.

My reed sensor is very simple, other end is grounded and other is in one of the interrupt compatible ports. I earlier speculated about pullup resistor, but haven't tested it yet.

I think RISING might be the correct interrupt mode.

I'm quite new with arduino ide, so I don't know how to write that piece of code myself.

Example code is built into almost every library, and the Sleepydog library is no exception. To run those examples from the Arduino IDE, select File>Open, select sketchbook folder>libraries>SleepyDog>Examples>

I'm quite new with arduino ide, so I don't know how to write that piece of code myself.

Then this is way too early in your journey to learn about using interrupts. For beginners, interrupts usually create many more problems than they solve, and the difficulties double with sleep modes.

First, get your application running correctly without using sleep mode and interrupts.

I earlier speculated about pullup resistor, but haven't tested it yet.

The pullup resistor is required to make the default pin state HIGH. Activate it using
pinMode(pin, INPUT_PULLUP); and use FALLING for the interrupt condition.

on the Adafruit 32u4 LoRa the Adafruit Watchdog Library Sleep Example File>Examples>Adafruit_SleepyDog>Sleep does not resume Serial output after sleep
this amended version does

// Adafruit 32u4 Watchdog Library Sleep Example
// File>Examples>Adafruit_SleepyDog>Sleep

// Simple example of how to do low power sleep with the watchdog timer.
//
// Author: Tony DiCola

// to program device if in sleep
// hit upload when "Waiting for upload port..." appears press RST button

#include <Adafruit_SleepyDog.h>

void setup() {
  // For boards with "native" USB support (e.g. not using an FTDI chip or
  // similar serial bridge), Serial connection may be lost on sleep/wake,
  // and you might not see the "I'm awake" messages. Use the onboard LED
  // as an alternate indicator -- the code turns it on when awake, off
  // before going to sleep.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);  // Show we're awake
  delay(3000);
  Serial.begin(115200);
  while (!Serial)
    ;  // wait for Arduino Serial Monitor (native USB boards)
  Serial.println("32u4 Adafruit Watchdog Library Sleep Demo!");
  Serial.println();
}

void loop() {
  Serial.println("Going to sleep in one second...");
  delay(1000);
  // To enter low power sleep mode call Watchdog.sleep() like below
  // and the watchdog will allow low power sleep for as long as possible.
  // The actual amount of time spent in sleep will be returned (in
  // milliseconds).
  digitalWrite(LED_BUILTIN, LOW);  // Show we're asleep
  int sleepMS = Watchdog.sleep();

  // Alternatively you can provide a millisecond value to specify
  // how long you'd like the chip to sleep, but the hardware only
  // supports a limited range of values so the actual sleep time might
  // be smaller.  The time spent in sleep will be returned (in
  // milliseconds).
  // int sleepMS = Watchdog.sleep(1000);  // Sleep for up to 1 second.
  // Code resumes here on wake.
  digitalWrite(LED_BUILTIN, HIGH);  // Show we're awake again
  // Try to reattach USB connection on "native USB" boards (connection is
  // lost on sleep). Host will also need to reattach to the Serial monitor.
  // Seems not entirely reliable, hence the LED indicator fallback.
#if defined(USBCON) && !defined(USE_TINYUSB)
  USBDevice.attach();
#endif
  // *** code added to reopen Serial ****
  delay(1000);
  Serial.begin(115200);
  while (!Serial)
    ;
  Serial.print("\nI'm awake now! I slept for ");
  Serial.print(sleepMS, DEC);
  Serial.println(" milliseconds.");
  Serial.println();
}

Serial monitor output

32u4 Adafruit Watchdog Library Sleep Demo!

Going to sleep in one second...

I'm awake now! I slept for 8000 milliseconds.

Going to sleep in one second...

I'm awake now! I slept for 8000 milliseconds.

Going to sleep in one second...

I'm awake now! I slept for 8000 milliseconds.

However, the recommendation by @jremington of getting the basic system working then adding extra functionality later is a good idea

I think this conversation is going on the wrong tracks. I know how to use examples, my code is working otherwise fine, only interrupt part isn't working. This isn't my first code or even tenth.

All I'm trying to find out, is how to integrate interrupt to my board so that reed sensor would work as it should.

I'm using lora from mailbox to send info about reed status to other lora receiver which is using mqtt to connect to home assistant. I have bme280 as temp-sensor and other stuff which aren't relevant to current problematic code.

Thanks everyone for trying to contribute so far :+1::+1:

It won't, until you add the required pullup resistor. Are you reading these posts?

Getting the interrupt working with a simple test program would be a step in advancing the entire project.

1 Like

this may be a start

// Adafruit Feather 32u4 LoRa blink test with external interrupt

// LED blinks and a  LOW on pin 2 gives interrupt

#define pin 2

// interrupt ISR - set volatile variable true which is read in loop()
volatile bool interrupt = false;
void isr(void) {
  interrupt = true;  // indicate interrupt
}

// the setup function runs once when you press reset or power the board
void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.print(F("\n Adafruit 32u4 blink Starting ..."));
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pin), isr, LOW);
}

void loop() {
  // if interrupt has occured display message
  if (interrupt) {
    Serial.println("\nInterrupt!!");
    interrupt = false;  // clear indicator
  }
  // display * and vlink LED
  Serial.print("*");
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(500);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
  delay(500);                       // wait for a second
}

LED blinks and serial monitor displays "Interrupt!!" when pin 2 taken LOW

Adafruit 32u4 blink Starting ...********************
Interrupt!!
*
Interrupt!!
****
Interrupt!!
*
Interrupt!!
***
Interrupt!!

be interesting to see if it will wake from sleep!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.