From 63b43fc2ec1650398fdc0e104479d85706af844a Mon Sep 17 00:00:00 2001 From: Pol Van Aubel Date: Sat, 4 May 2019 04:29:31 +0200 Subject: [PATCH] Loopless / low power examples. A set of examples that demonstrate basic use of timers, interrupts, and tasks. Based on and tested on the nRF52840, but also compiles on the nRF52832 -- although you'll need an external button there. --- .../Blink2_loopless/Blink2_loopless.ino | 60 +++++++++ .../Blink_loopless/Blink_loopless.ino | 50 +++++++ .../Button_interrupt/Button_interrupt.ino | 67 ++++++++++ .../Button_interrupt_ada_callback.ino | 104 +++++++++++++++ .../Button_interrupt_deferred.ino | 83 ++++++++++++ .../Button_interrupt_direct_to_task.ino | 122 ++++++++++++++++++ .../Fading_loopless_onetimer.ino | 76 +++++++++++ .../Fading_loopless_twotimers.ino | 82 ++++++++++++ 8 files changed, 644 insertions(+) create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Blink2_loopless/Blink2_loopless.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Blink_loopless/Blink_loopless.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt/Button_interrupt.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_ada_callback/Button_interrupt_ada_callback.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_deferred/Button_interrupt_deferred.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_direct_to_task/Button_interrupt_direct_to_task.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_onetimer/Fading_loopless_onetimer.ino create mode 100644 libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_twotimers/Fading_loopless_twotimers.ino diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Blink2_loopless/Blink2_loopless.ino b/libraries/Bluefruit52Lib/examples/LowPower/Blink2_loopless/Blink2_loopless.ino new file mode 100644 index 000000000..293c3bd07 --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Blink2_loopless/Blink2_loopless.ino @@ -0,0 +1,60 @@ +/* + Blink_loopless + + Created 2019-05-03 + by Pol Van Aubel + + Turns on an LED on for one second, then off for one second, repeatedly. + + This example is based on the original Blink sketch. The Adafruit nRF52* boards + are more advanced than "normal" Arduinos, however, and come with freeRTOS + and proper task management. This blink sketch demonstrates the use of two + SoftwareTimers to perform two repetitive delayed tasks at different frequencies + without using the energy that a continuously running loop() function has. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + + Based on the original Blink, the code of which is in the public domain. + */ + +#include + +// Create the two SoftwareTimers we're going to use. +SoftwareTimer bluetimer, redtimer; + +void setup() +{ + // LED_RED & LED_BLUE are already initialized as outputs. + + // Initialize the timers at .75 seconds for blue, and 1 second for red. + bluetimer.begin(750, bluetoggle); + redtimer.begin(1000, redtoggle); + bluetimer.start(); + redtimer.start(); + suspendLoop(); +} + +void loop(void) { } + +/** + * Toggle led1 every 1 second + */ +void redtoggle(TimerHandle_t _handle) +{ + digitalToggle(LED_RED); // Toggle LED +} + +/** + * Toggle led1 every 0.5 second + */ +void bluetoggle(TimerHandle_t _handle) +{ + digitalToggle(LED_BLUE); // Toggle LED +} diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Blink_loopless/Blink_loopless.ino b/libraries/Bluefruit52Lib/examples/LowPower/Blink_loopless/Blink_loopless.ino new file mode 100644 index 000000000..ac6c19484 --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Blink_loopless/Blink_loopless.ino @@ -0,0 +1,50 @@ +/* + Blink_loopless + + Created 2019-05-03 + by Pol Van Aubel + + Turns on an LED on for one second, then off for one second, repeatedly. + + This example is based on the original Blink sketch. The Adafruit nRF52* boards + are more advanced than "normal" Arduinos, however, and come with freeRTOS + and proper task management. This blink sketch demonstrates the use of + SoftwareTimer to perform a repetitive delayed task without using the energy + that a continuously running loop() function has. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + + Based on the original Blink, the code of which is in the public domain. + +*/ + +// Create a SoftwareTimer that will drive our LED. +SoftwareTimer led_timer; + +// the setup function runs once when you press reset or power the board +void setup(void) { + // initialize digital pin LED_BUILTIN as an output. + pinMode(LED_RED, OUTPUT); + + // Set up a repeating timer that fires every half second (500ms) to toggle the LED. + led_timer.begin(500, timer_callback); + led_timer.start(); + + // Since loop() is empty, suspend its task so that the system never runs it + // and can go to sleep properly. + suspendLoop(); +} + +void timer_callback(TimerHandle_t _handle) { + digitalToggle(LED_RED); // toggle the red LED +} + +// the loop function is empty and should never run. +void loop(void) { } diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt/Button_interrupt.ino b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt/Button_interrupt.ino new file mode 100644 index 000000000..a7c85ce6c --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt/Button_interrupt.ino @@ -0,0 +1,67 @@ +/* + Button_interrupt + + Created 2019-05-04 + by Pol Van Aubel + + Uses an interrupt to listen for a button input. On the nRF52840, it can listen + on pin 7 to the UserSW. On other boards, an external switch needs to be provided. + + The Adafruit nRF52* boards are more advanced than "normal" Arduinos and come + with freeRTOS, interrupts available on every pin, and proper task management. + This button sketch demonstrates the use of interrupts to act on an input such + as a switch, without having to poll it in a continuously scanning loop() function. + Even though human button presses are slow, and therefore unlikely to be missed + using a scanning loop, the interrupt technique allows the board to go into sleep + mode while waiting for an input, thereby saving a lot of energy. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + + This code is licensed under CC0, effectively putting it in the Public Domain + where possible. + +*/ + +// On the nRF52840, pin 7 is the UserSW/DFU switch. +int interruptPin = 7; + +// the setup function runs once when you press reset or power the board +void setup(void) { + pinMode(LED_RED, OUTPUT); + pinMode(interruptPin, INPUT_PULLUP); // Configure the switch pin as an input with internal pull-up register enabled. + + // Configure it to call switch_callback if the switch pin transitions from HIGH to LOW, i.e. when it is pressed. + // On the nRF52840, RISING and CHANGE are also valid options. Depending on your platform, LOW may also be available. + attachInterrupt(interruptPin, switch_callback, FALLING); + + // Since loop() is empty, suspend its task so that the system never runs it + // and can go to sleep properly. + suspendLoop(); +} + +// the loop function is empty and should never run. +void loop(void) { } + +// The switch_callback function is the function we attached to the interrupt on line 42. +// This is known as an Interrupt Service Routine, or ISR. +// It gets run every time the interrupt fires, in the interrupt context. Nothing else +// happens while this is running. Therefore, it should be fast and simple. +// In particular, it should never block, nor do Serial communication or use the Bluefruit API. +// There are a few freeRTOS functions specifically designed to be run from an ISR. +// If you need a longer ISR, other examples show how to do this. +void switch_callback(void) { + digitalToggle(LED_RED); // toggle the red LED + + // You may notice that the LED does not reliably turn on on one press of the switch, + // then off on the next. This is likely due to a phenomenon physical switches exhibit called "bounce". + // Effectively this means that the pin goes through multiple transitions of HIGH to LOW, + // back to HIGH, to LOW again, for a single press of the button. + // Some debouncing techniques using interrupts are shown in another example. +} diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_ada_callback/Button_interrupt_ada_callback.ino b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_ada_callback/Button_interrupt_ada_callback.ino new file mode 100644 index 000000000..92b97a522 --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_ada_callback/Button_interrupt_ada_callback.ino @@ -0,0 +1,104 @@ +/* + Button_interrupt_ada_callback + + Created 2019-05-04 + by Pol Van Aubel + + Uses an interrupt to listen for a button input. On the nRF52840, it can listen + on pin 7 to the UserSW. On other boards, an external switch needs to be provided. + + The Adafruit nRF52* boards are more advanced than "normal" Arduinos and come + with freeRTOS, interrupts available on every pin, and proper task management. + This button sketch demonstrates the use of interrupts to act on an input such + as a switch, without having to poll it in a continuously scanning loop() function. + Even though human button presses are slow, and therefore unlikely to be missed + using a scanning loop, the interrupt technique allows the board to go into sleep + mode while waiting for an input, thereby saving a lot of energy. + + However, because interrupts need to be fast, you must not do Serial communication + or long tasks directly in an ISR. This is where deferred ISRs come in. However, + deferred ISRs cannot have a single time-critical component. By using + ada_callback_fromISR, you can run a fast time-critical component in a normal + ISR, and then queue up a callback to process the rest. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + + This code is licensed under CC0, effectively putting it in the Public Domain + where possible. + +*/ + +// On the nRF52840, pin 7 is the UserSW/DFU switch. +int interruptPin = 7; + +// Because this variable is modified inside a non-deferred ISR, and used outside it, +// it must be declared volatile to ensure that the most recently written value is +// always used. +volatile int numinterrupts; + +// the setup function runs once when you press reset or power the board +void setup(void) { + Serial.begin(115200); // Not required on the nRF52840 with native USB. + + while (!Serial) { // Stalls the nRF52840 until the USB serial console has been opened on the host PC. + delay(10); + } + Serial.println("Press the button!"); + Serial.flush(); // Because this sketch does nothing else, it will go to sleep rather than send the + // entire Serial buffer to the host PC. So, use Serial.flush() to make sure it does that + // before allowing it to sleep. + + pinMode(LED_RED, OUTPUT); + pinMode(interruptPin, INPUT_PULLUP); // Configure the switch pin as an input with internal pull-up register enabled. + + // Configure it to call switch_callback if the switch pin transitions from HIGH to LOW, i.e. when it is pressed. + // On the nRF52840, RISING and CHANGE are also valid options. Depending on your platform, LOW may also be available. + attachInterrupt(interruptPin, switch_isr, FALLING); + + // Since loop() is empty, suspend its task so that the system never runs it + // and can go to sleep properly. + suspendLoop(); +} + +// the loop function is empty and should never run. +void loop(void) { } + +// The switch_isr function is the function we attached to the interrupt on line 63. +// This is known as an Interrupt Service Routine, or ISR. +// It gets run every time the interrupt fires, in the interrupt context. Nothing else +// happens while this is running. Therefore, it should be fast and simple. +// In particular, it should never block, nor do Serial communication or use the Bluefruit API. +// There are a few freeRTOS functions specifically designed to be run from an ISR. +void switch_isr(void) { + // Do short time-critical processing (setting flags, queueing up tasks, etc) here. + digitalToggle(LED_RED); + + ++numinterrupts; + ada_callback_fromISR(NULL, 0, switch_isr_callback); // Queue up a task with no extra variables and no arguments. + // Every single interrupt is serviced, because internally, a + // queue is used. +} + + +// The switch_isr_callback function is the function we set up as the ada_callback on line 84. +// It gets run once for every interrupt that switch_isr ran for, but with no guarantees about +// when that happens. However, the advantage is you have the full range of Serial, Bluefruit, +// and freeRTOS API to use now. +// Bear in mind, however, that if this function takes longer to run than the average time between +// interrupts, at some point your ada_callback_queue will overflow. For that scenario, consider +// batch-processing interrupts by using direct-to-task notifications. +void switch_isr_callback(void) { + Serial.println("Interrupt serviced!"); + Serial.print("The number of interrupts received at this point was "); + Serial.println(numinterrupts); + Serial.flush(); // Because this sketch does nothing else, it will go to sleep rather than send the + // entire Serial buffer to the host PC. However, here, Serial.flush() doesn't seem + // to work either. Maybe something to do with the task context? +} diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_deferred/Button_interrupt_deferred.ino b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_deferred/Button_interrupt_deferred.ino new file mode 100644 index 000000000..8fd8ebbda --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_deferred/Button_interrupt_deferred.ino @@ -0,0 +1,83 @@ +/* + Button_interrupt_deferred + + Created 2019-05-04 + by Pol Van Aubel + + Uses an interrupt to listen for a button input. On the nRF52840, it can listen + on pin 7 to the UserSW. On other boards, an external switch needs to be provided. + + The Adafruit nRF52* boards are more advanced than "normal" Arduinos and come + with freeRTOS, interrupts available on every pin, and proper task management. + This button sketch demonstrates the use of interrupts to act on an input such + as a switch, without having to poll it in a continuously scanning loop() function. + Even though human button presses are slow, and therefore unlikely to be missed + using a scanning loop, the interrupt technique allows the board to go into sleep + mode while waiting for an input, thereby saving a lot of energy. + + However, because interrupts need to be fast, you must not do Serial communication + or long tasks directly in an ISR. This is where deferred ISRs come in. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + + This code is licensed under CC0, effectively putting it in the Public Domain + where possible. + +*/ + +// On the nRF52840, pin 7 is the UserSW/DFU switch. +int interruptPin = 7; + +// the setup function runs once when you press reset or power the board +void setup(void) { + Serial.begin(115200); // Not required on the nRF52840 with native USB. + + while (!Serial) { // Stalls the nRF52840 until the USB serial console has been opened on the host PC. + delay(10); + } + Serial.println("Press the button!"); + + pinMode(LED_RED, OUTPUT); + pinMode(interruptPin, INPUT_PULLUP); // Configure the switch pin as an input with internal pull-up register enabled. + + // Configure it to call switch_callback if the switch pin transitions from HIGH to LOW, i.e. when it is pressed. + // On the nRF52840, RISING and CHANGE are also valid options. Depending on your platform, LOW may also be available. + // The ISR_DEFERRED flag ensures that the interrupt is serviced by a scheduled operating system task. + // What this means is that the ISR is allowed to perform slow functionality, including Serial communication, + // using the Bluefruit API, and the entire freeRTOS API rather than just the *FromISR functions. + // Use this if your interrupt servicing is not time-critical. + attachInterrupt(interruptPin, switch_deferred, ISR_DEFERRED | FALLING); + + // Since loop() is empty, suspend its task so that the system never runs it + // and can go to sleep properly. + suspendLoop(); +} + +// the loop function is empty and should never run. +void loop(void) { } + +// The switch_deferred function is the function we attached to the interrupt on line 56. +// This is known as an Interrupt Service Routine, or ISR. +// Because it is a deferred ISR, it is not guaranteed to run immediately after the interrupt +// happens. However, the advantage is you have the full range of Serial, Bluefruit, +// and freeRTOS API to use now. +void switch_deferred(void) { + digitalToggle(LED_RED); + Serial.println("Interrupt serviced!"); + Serial.flush(); // Because this sketch does nothing else, it will go to sleep rather than send the + // entire Serial buffer to the host PC. So, use Serial.flush() to make sure it does that + // before allowing it to sleep. + + // You may notice that you receive multiple messages per press of the switch, + // This is likely due to a phenomenon physical switches exhibit called "bounce". + // Effectively this means that the pin goes through multiple transitions of HIGH to LOW, + // back to HIGH, to LOW again, for a single press of the button. + // Some debouncing techniques using interrupts are shown in another example. +} diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_direct_to_task/Button_interrupt_direct_to_task.ino b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_direct_to_task/Button_interrupt_direct_to_task.ino new file mode 100644 index 000000000..83bb9be0a --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Button_interrupt_direct_to_task/Button_interrupt_direct_to_task.ino @@ -0,0 +1,122 @@ +/* + Button_interrupt_direct_to_task + + Created 2019-05-04 + by Pol Van Aubel + + Uses an interrupt to listen for a button input. On the nRF52840, it can listen + on pin 7 to the UserSW. On other boards, an external switch needs to be provided. + + The Adafruit nRF52* boards are more advanced than "normal" Arduinos and come + with freeRTOS, interrupts available on every pin, and proper task management. + This button sketch demonstrates the use of interrupts to act on an input such + as a switch, without having to poll it in a continuously scanning loop() function. + Even though human button presses are slow, and therefore unlikely to be missed + using a scanning loop, the interrupt technique allows the board to go into sleep + mode while waiting for an input, thereby saving a lot of energy. + + However, because interrupts need to be fast, you must not do Serial communication + or long tasks directly in an ISR. This is where deferred ISRs come in. However, + deferred ISRs cannot have a single time-critical component. ada_callback_fromISR, + queues up a task for every interrupt fired. Sometimes it's okay or even desirable + to service multiple interrupts in a single run of the task. This sketch demonstrates + how to take direct control of this, by using startLoop and the freeRTOS + direct-to-task notification API. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + + This code is licensed under CC0, effectively putting it in the Public Domain + where possible. + +*/ + + +// On the nRF52840, pin 7 is the UserSW/DFU switch. +// Best results for this sketch are achieved with a very bouncy button. +int interruptPin = 6; + +TaskHandle_t switch_isr_task_handle; + + +// the setup function runs once when you press reset or power the board +void setup(void) { + Serial.begin(115200); // Not required on the nRF52840 with native USB. + + while (!Serial) { // Stalls the nRF52840 until the USB serial console has been opened on the host PC. + delay(10); + } + Serial.println("Press the button!"); + Serial.flush(); // Because this sketch does nothing else, it will go to sleep rather than send the + // entire Serial buffer to the host PC. So, use Serial.flush() to make sure it does that + // before allowing it to sleep. + + pinMode(LED_RED, OUTPUT); + pinMode(interruptPin, INPUT_PULLUP); // Configure the switch pin as an input with internal pull-up register enabled. + + // Set up a task to act on the interrupts. + // startLoop is a wrapper around freeRTOS's xTaskCreate that takes care of infinitely + // looping inside the function being called, just like loop(). If you need to do setup + // that should not be repeated, e.g. if you want to keep an incrementing counter inside + // the task, use the freeRTOS API directly. + //Scheduler.startLoop(switch_isr_task); + // TODO Cannot use startLoop because we need the handle for vTaskNotifyGiveFromISR(). + + + // Set up a task to act on the interrupts. We schedule it so it only happens if there + // is absolutely nothing else to do. + if (xTaskCreate(switch_isr_task, "ISRprocessor", SCHEDULER_STACK_SIZE_DFLT, NULL, TASK_PRIO_LOW, &switch_isr_task_handle) != pdPASS) { + Serial.println("Unable to create task for the ISR. This is going to crash!"); + Serial.flush(); + delay(1000); + } + + // Configure it to call switch_callback if the switch pin transitions from HIGH to LOW, i.e. when it is pressed. + // On the nRF52840, RISING and CHANGE are also valid options. Depending on your platform, LOW may also be available. + attachInterrupt(interruptPin, switch_isr, FALLING); + + // Since loop() is empty, suspend its task so that the system never runs it + // and can go to sleep properly. + suspendLoop(); +} + +// the loop function is empty and should never run. +void loop(void) { } // We could actually use the loop task instead of switch_isr_task. + +// The switch_isr function is the function we attached to the interrupt on line 61. +// This is known as an Interrupt Service Routine, or ISR. +// It gets run every time the interrupt fires, in the interrupt context. Nothing else +// happens while this is running. Therefore, it should be fast and simple. +// In particular, it should never block, nor do Serial communication or use the Bluefruit API. +// There are a few freeRTOS functions specifically designed to be run from an ISR. +void switch_isr(void) { + // Do short time-critical processing (setting flags, queueing up tasks, etc) here. + digitalToggle(LED_RED); + + vTaskNotifyGiveFromISR(switch_isr_task_handle, NULL); // Increment the notification value of the task. +} + + +// The switch_isr_task function is the function we set up as the task on line 72. +// It gets run when the scheduler can schedule it, and then processes all interrupts in one go. +// You have the full range of Serial, Bluefruit, and freeRTOS API to use here. +void switch_isr_task(void* ignored) { + uint32_t pulNotificationValue = 0; + static uint32_t clear_mask = 0xFFFFFFFF; + while (1) { + xTaskNotifyWait(0, clear_mask, &pulNotificationValue, DELAY_FOREVER); // Block the task running this function until it gets a notification. + + Serial.println("Interrupt serviced!"); + Serial.print("The number of interrupts serviced by this invocation was "); + Serial.println(pulNotificationValue); + Serial.flush(); // Because this sketch does nothing else, it will go to sleep rather than send the + // entire Serial buffer to the host PC. However, here, Serial.flush() doesn't seem + // to work either. Maybe something to do with the task context? + } +} diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_onetimer/Fading_loopless_onetimer.ino b/libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_onetimer/Fading_loopless_onetimer.ino new file mode 100644 index 000000000..0e06d02dc --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_onetimer/Fading_loopless_onetimer.ino @@ -0,0 +1,76 @@ +/* + Fading_loopless_onetimer + + Fades an LED in from 0 to max intensity, then out back to 0, repeatedly. + + This example is based on the original Fading sketch. The Adafruit nRF52* boards + are more advanced than "normal" Arduinos, however, and come with freeRTOS + and proper task management. This blink sketch demonstrates the use of a single + SoftwareTimer to perform a repetitive delayed task without using the energy + that a continuously running loop() function has. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + Created 2019-05-03 + by Pol Van Aubel + + + Based on: + + + Fading + + This example shows how to fade an LED using the analogWrite() function. + + The circuit: + * LED attached from digital pin 9 to ground. + + Created 1 Nov 2008 + By David A. Mellis + modified 30 Aug 2011 + By Tom Igoe + + http://www.arduino.cc/en/Tutorial/Fading + + This example code is in the public domain. + + */ + +// Create a SoftwareTimer that will resume our loop. +SoftwareTimer fadetimer; + +int ledPin = LED_RED; // Red LED connected to a PWM-capable pin. + +void setup() { + fadetimer.begin(30, fadetimer_callback); // Configure our timer for intervals of 30 ms. + fadetimer.start(); // Start the timer. + + suspendLoop(); // Since loop() is empty, we should not run it to allow for huge powersaving. +} + +void loop() { } // Nothing happens in loop. Don't forget to call suspendLoop()! + +void fadetimer_callback(TimerHandle_t _handle) { + static bool increasing = true; // Variable that remembers the direction over function calls. + static int fadeValue = 0; // Variable that remembers the intensity over function calls. + + if (increasing) { + fadeValue += 5; // Increase intensity by 5. + } else { + fadeValue -= 5; // Decrease intensity by 5. + } + + analogWrite(ledPin, fadeValue); // Do the actual write + + // Be careful: If you change the in/decrements above, make sure you actually still + // hit the following values or change the comparisons. + if (fadeValue == 0 || fadeValue == 255) { // We've reached the end, so flip direction. + increasing = !increasing; // If increasing = true, this makes it false, and vice versa. + } +} diff --git a/libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_twotimers/Fading_loopless_twotimers.ino b/libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_twotimers/Fading_loopless_twotimers.ino new file mode 100644 index 000000000..ec093de1d --- /dev/null +++ b/libraries/Bluefruit52Lib/examples/LowPower/Fading_loopless_twotimers/Fading_loopless_twotimers.ino @@ -0,0 +1,82 @@ +/* + Fading_twotimers + + Fades an LED in fast from 0 to max intensity, then slowly out back to 0, repeatedly. + + This example is based on the original Fading sketch. The Adafruit nRF52* boards + are more advanced than "normal" Arduinos, however, and come with freeRTOS + and proper task management. This blink sketch demonstrates the use of two + SoftwareTimers to perform a repetitive delayed task without using the energy + that a continuously running loop() function has. + + AdaFruit's nRF-boards have multiple on-board LEDs you can control. These are + addressable using the LED_RED, LED_BLUE, LED_BUILTIN and LED_CONN definitions. + These take care to use the correct LED pin regardless of which board is used. + If you want to know what pin the on-board LED is connected to on your model, + check the Technical Specs of your board on https://www.adafruit.com/ or the + board's variant.h at + https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants + + Created 2019-05-03 + by Pol Van Aubel + + + Based on: + Fading + + This example shows how to fade an LED using the analogWrite() function. + + The circuit: + * LED attached from digital pin 9 to ground. + + Created 1 Nov 2008 + By David A. Mellis + modified 30 Aug 2011 + By Tom Igoe + + http://www.arduino.cc/en/Tutorial/Fading + + This example code is in the public domain. + + */ + +// Create SoftwareTimers that will fade our LED. +SoftwareTimer increasetimer, decreasetimer; + +int ledPin = LED_RED; // Red LED connected to a PWM-capable pin. + +static int fadeValue = 0; // Variable that remembers the intensity over function calls. + +void setup() { + increasetimer.begin(10, increasetimer_callback); // Configure our timers for intervals of 10ms for + decreasetimer.begin(50, decreasetimer_callback); // fade in and 50ms for fade out. + increasetimer.start(); // Start the increasing timer. + + suspendLoop(); // Since loop() is empty, we should not run it to allow for huge powersaving. +} + +void loop() { } // Nothing happens in loop. Don't forget to call suspendLoop()! + +void increasetimer_callback(TimerHandle_t _handle) { + fadeValue += 5; // Increase intensity by 5. + analogWrite(ledPin, fadeValue); // Do the actual write + + // Be careful: If you change the increment above, make sure you actually still + // hit the following value or change the comparisons. + if (fadeValue == 255) { // We've reached the end, so flip direction by switching active timers. + increasetimer.stop(); + decreasetimer.start(); + } +} + +void decreasetimer_callback(TimerHandle_t _handle) { + fadeValue -= 5; // Increase intensity by 5. + analogWrite(ledPin, fadeValue); // Do the actual write + + // Be careful: If you change the decrement above, make sure you actually still + // hit the following value or change the comparisons. + if (fadeValue == 0) { // We've reached the end, so flip direction by switching active timers. + decreasetimer.stop(); + increasetimer.start(); + } +}