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

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
noorjaber
 
Posts: 6
Joined: Wed Apr 20, 2016 11:25 am

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

Post by noorjaber »

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

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)

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

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

Post by mikeysklar »

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

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?

User avatar
noorjaber
 
Posts: 6
Joined: Wed Apr 20, 2016 11:25 am

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

Post by noorjaber »

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

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

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

Post by mikeysklar »

@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?

User avatar
noorjaber
 
Posts: 6
Joined: Wed Apr 20, 2016 11:25 am

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

Post by noorjaber »

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

/**
 * 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);  
 }

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

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

Post by mikeysklar »

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

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

Code: Select all

deinit(self) → None
Turn off the DigitalInOut and release the pin for other use.

User avatar
noorjaber
 
Posts: 6
Joined: Wed Apr 20, 2016 11:25 am

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

Post by noorjaber »

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

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)

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

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

Post by mikeysklar »

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

User avatar
noorjaber
 
Posts: 6
Joined: Wed Apr 20, 2016 11:25 am

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

Post by noorjaber »

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

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”