0

Alarm: use a pin for an alarm AND general input (sleep)
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Alarm: use a pin for an alarm AND general input (sleep)

by noorjaber on Sat May 08, 2021 8:33 am

Hello,

I'm working with the feather esp32-s2 and multiple buttons. I'm hoping to take advantage of the deep sleep feature to conserve power. I'd like each button to be used for both general input and to wake the feather up from deep sleep (ie press button 1 -> wakes from deep sleep AND then flashes dotstar green before going back into deep sleep; press button 2 -> wakes from sleep AND then flashes dotstar red....). I'm having difficulty doing so although my programming skills are weak. Is this a programming issue or is it just not possible yet with deep/light sleep? Example code below.

Thanks for your time,
Noor

Code: Select all | TOGGLE FULL SIZE
import alarm #only available on esp32-s2 as of cp6.2
import time
import board
import digitalio
import adafruit_dotstar

led = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)

pin_alarm1 = alarm.pin.PinAlarm(pin=board.D16, value=False, pull=True) #button1
pin_alarm2 = alarm.pin.PinAlarm(pin=board.D19, value=False, pull=True) #button2

if DigitalInOut(board.D16).value:
    print("button1 pressed")
    led[0] = (0,255,0)
    time.sleep(1)
   
if DigitalInOut(board.D19).value:
    print("button2 pressed")
    led[0] = (255,0,0)
    time.sleep(1)
   
alarm.exit_and_deep_sleep_until_alarms(pin_alarm1, pin_alarm2)

noorjaber
 
Posts: 5
Joined: Wed Apr 20, 2016 11:25 am

Re: Alarm: use a pin for an alarm AND general input (sleep)

by mikeysklar on Sun May 09, 2021 7:45 pm

noorjaber,

Your code looks reasonable. What happens when you run the sample you provided? Are you seeing any output on the REPL? It might make sense to add some serial print statements just to confirm that the button press is bringing the controller out of deep sleep.

I took a look at our pinAlarm example with NeoPixels.

Code: Select all | TOGGLE FULL SIZE
import alarm
import board
import digitalio
import neopixel
import time

# On MagTag, enable power to NeoPixels.
# Remove these two lines on boards without board.NEOPIXEL_POWER.
np_power = digitalio.DigitalInOut(board.NEOPIXEL_POWER)
np_power.switch_to_output(value=False)

np = neopixel.NeoPixel(board.NEOPIXEL, 1)

np[0] = (50, 50, 50)
time.sleep(1)
np[0] = (0, 0, 0)

pin_alarm = alarm.pin.PinAlarm(pin=board.D11, value=False, pull=True)

# Exit the program, and then deep sleep until the alarm wakes us.
alarm.exit_and_deep_sleep_until_alarms(pin_alarm)

# Does not return, so we never get here.


If you creae a new program following ours even more closely and only change on the DotStar logic does it work?

mikeysklar
 
Posts: 4624
Joined: Mon Aug 01, 2016 8:10 pm

Re: Alarm: use a pin for an alarm AND general input (sleep)

by noorjaber on Sun May 09, 2021 10:31 pm

Thanks for the quick response mikeysklar.

When I run the sample I provided, pressing either button wakes the device and runs the code. Output after pressing either button:
---
Pretending to deep sleep until alarm, CTRL-C or file write.
Woken up by alarm.
soft reboot
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Code done running.
Press any key to enter the REPL. Use CTRL-D to reload.
Pretending to deep sleep until alarm, CTRL-C or file write.
---
The led state change/print statement never triggers, however. Holding down either button through the cycle makes no difference.

The sample you provided does work (button pin wakes from deep sleep) when neopixel logic changed to dotstar. The issue of not being able to use a single pin for both a pin alarm and general purpose input pin remains (ie in my sample, one pin would trigger a led state change when code is briefly active and would also be able to wake up the device when in deep sleep). Any other tips?

Thanks,
Noor

noorjaber
 
Posts: 5
Joined: Wed Apr 20, 2016 11:25 am

Re: Alarm: use a pin for an alarm AND general input (sleep)

by mikeysklar on Mon May 10, 2021 4:10 pm

@noorjaber,

I am not clear on the issue. It sounds like setting pinAlarm on one pin D11 works fine. Is the problem you are describing in setting pinAlarm on the two pins you have tried D16 / D19 does not work and the code gets stuck?

mikeysklar
 
Posts: 4624
Joined: Mon Aug 01, 2016 8:10 pm

Re: Alarm: use a pin for an alarm AND general input (sleep)

by noorjaber on Tue May 11, 2021 8:24 am

Thanks for the response.

What I'm trying to do is use a single pin to wake up the device from deep sleep and then use the same pin for general input once the device is awake and runs the code. This works with Arduino (avr chips) via attachInterrupt and detachInterrupt. Take a look at the sample below taken from a site and modified slightly.

Within the main loop, a buttonPin is assigned to pin 2 that triggers a led change before the device goes into deep sleep. Within the function instructing the device to sleep(Going_To_Sleep()), the same Pin (2) is then attached as an interrupt before the device sleeps. The same pin (2) wakes the device from sleep and then the pin (2) is immediately detached as an interrupt before running the main loop. That same pin (2) is then used as buttonPin1 within the loop function before the cycle repeats.

So once the device initially starts, it will put itself to sleep. The current draw decreases appropriately. Once I press the button, the device wakes up, prints to serial that the button is pressed and ledPin1 is then high for 1 second. The device then goes back to sleep and the process repeats.

Does the deep sleep library in CircuitPython have a similar detach function? Or is there some other way to achieve the same?

Code: Select all | TOGGLE FULL SIZE
/**
 * Modified from: http://www.thearduinomakerman.info/blog/2018/1/24/guide-to-arduino-sleep-mode
 */

#include <avr/sleep.h>
byte interruptPin1 = 2; //Pin used to wake up the Arduino
const int ledPin1 = 8;

void setup() {
  Serial.begin(115200);//Start Serial Comunication
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(interruptPin1,INPUT_PULLUP); //Probably not necessary...Set pin d2 to input
}

void loop() {
 int buttonPin1 = 2;
 pinMode(buttonPin1, INPUT_PULLUP);
 Serial.println("Pin 2 changed");
 int buttonState1 = 0;
 buttonState1 = digitalRead(buttonPin1);

 if (buttonState1 == LOW)
   {
    // turn LED on:
    Serial.println("Button pressed!");
    digitalWrite(ledPin1, HIGH);
    delay(1000);
    digitalWrite(ledPin1, LOW);
  }
  else {
    // turn LED off:
    digitalWrite(ledPin1, LOW);
    Serial.println("Button not pressed");
  }

 Serial.println("Going to sleep in 2...");
 led_flash();
 Going_To_Sleep();
}

void Going_To_Sleep()
{
    sleep_enable();
    attachInterrupt(0, wakeUp, LOW); //interrupt to pin d2 (Int.0=pin2 on an uno)
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);  //Setting the sleep mode to full sleep
    sleep_cpu(); //activating sleep mode
    Serial.println("just woke up!"); //next line of code executed after the interrupt
    digitalWrite(LED_BUILTIN, HIGH);//turning LED on
  }

void wakeUp(){
  Serial.println("Interrrupt Fired");//Print message to serial monitor
  sleep_disable();//Disable sleep mode
  detachInterrupt(0); //Removes the interrupt (Int.0=pin2 on an uno)
}

void led_flash()
 {
 digitalWrite(LED_BUILTIN, HIGH);
 delay(1000);     
 digitalWrite(LED_BUILTIN, LOW);   
 delay(500);
 digitalWrite(LED_BUILTIN, HIGH);   
 delay(500);         
 digitalWrite(LED_BUILTIN, LOW); 
 }

noorjaber
 
Posts: 5
Joined: Wed Apr 20, 2016 11:25 am

Re: Alarm: use a pin for an alarm AND general input (sleep)

by mikeysklar on Tue May 11, 2021 2:54 pm

There is a deinit() you can experiment within CircuitPython.

https://circuitpython.readthedocs.io/en ... digitalio/

Code: Select all | TOGGLE FULL SIZE
deinit(self) → None
Turn off the DigitalInOut and release the pin for other use.

mikeysklar
 
Posts: 4624
Joined: Mon Aug 01, 2016 8:10 pm

Re: Alarm: use a pin for an alarm AND general input (sleep)

by noorjaber on Sat May 15, 2021 7:41 am

That works, thanks!

For anyone interested, a basic sketch using deinit() and pin alarm in CircuitPython follows. Read the section called "Deep Sleep and Wake-up Sources" here (https://learn.adafruit.com/adafruit-met ... imitations) if you're using deep sleep on the ESP32-S2. It might save you some time.

It's a bit too slow for my project (must hold for 3 seconds to wake up and acknowledge button press for a simple sketch on battery power) so will have to use C++ instead.

Code: Select all | TOGGLE FULL SIZE
import alarm
import board
import digitalio

pin5 = digitalio.DigitalInOut(board.D5)
pin5.switch_to_input(pull=digitalio.Pull.DOWN) #note pull

if button1.value:
    #do something

else:
    #do something

pin5.deinit()
print("pin5 deinitialized")

#assign pin 5 to something else
pin_alarm1 = alarm.pin.PinAlarm(pin=board.D5, value=True, pull=False) #note pull

print("Going to sleep")
alarm.exit_and_deep_sleep_until_alarms(pin_alarm1)

noorjaber
 
Posts: 5
Joined: Wed Apr 20, 2016 11:25 am

Re: Alarm: use a pin for an alarm AND general input (sleep)

by mikeysklar on Mon May 17, 2021 5:54 pm

Good job getting deinit() going. I had not seen it used before. Thank you for sharing the example code.

mikeysklar
 
Posts: 4624
Joined: Mon Aug 01, 2016 8:10 pm

Re: Alarm: use a pin for an alarm AND general input (sleep)

by noorjaber on Fri May 21, 2021 4:09 pm

Happy to help. To anyone using the code above, be sure to change "button1.value" to "pin5.value"

noorjaber
 
Posts: 5
Joined: Wed Apr 20, 2016 11:25 am

Please be positive and constructive with your questions and comments.