- Why do we need this React_Generic library
- Changelog
- Prerequisites
- Installation
- HOWTO Use
- API
- Examples
- Issues
- TO DO
- DONE
- Contributions and Thanks
- Contributing
- License
- Copyright
Why do we need this React_Generic library
By
An asynchronous programming library for the generic microcontrollers using the Arduino framework. Currently supporting ESP32, ESP8266, SAMD21/SAMD51, RP2040, STM32, nRF52, Teensy 4.x
The library is at the core of the SensESP project but is completely generic and can be used for standalone projects without issues.
This library gets much of its inspiration (and some code) from Reactduino
. React_Generic
, however, has been internally re-implemented for maintainability and readability, and has significantly better performance when there are lots of defined reactions. It also supports arbitrary callables as callbacks, allowing parametric creation of callback functions.
This React_Generic library currently supports these following boards:
-
ESP32
-
ESP8266
-
WT32_ETH01 (ESP32 + LAN8720A)
-
STM32F/L/H/G/WB/MP1 boards with built-in Ethernet LAN8742A such as :
- Nucleo-144 (F429ZI, F767ZI)
- Discovery (STM32F746G-DISCOVERY)
- All STM32 boards (STM32F/L/H/G/WB/MP1) with 32K+ Flash, with Built-in Ethernet
- STM32F4/F7 boards using Ethernet LAN8720 such as :
- Nucleo-144 (F429ZI, NUCLEO_F746NG, NUCLEO_F746ZG, NUCLEO_F756ZG)
- Discovery (DISCO_F746NG)
- STM32F4 boards (BLACK_F407VE, BLACK_F407VG, BLACK_F407ZE, BLACK_F407ZG, BLACK_F407VE_Mini, DIYMORE_F407VGT, FK407M1)
Note: Must use with STM32 core v2.2.0-
-
SAMD21/SAMD51
-
nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, NINA_B112_ublox, etc.
-
Teensy 4.1 using QNEthernet Library
-
RASPBERRY_PI_PICO using arduino-pico core v2.5.2+
Arduino IDE 1.8.19+
for Arduino.ESP32 Core 2.0.45
for ESP32-based boards.ESP8266 Core 3.0.2+
for ESP8266-based boards. .Adafruit nRF52 v1.3.0+
for nRF52 boards such as Adafruit NRF52840_FEATHER, NRF52832_FEATHER, NRF52840_FEATHER_SENSE, NRF52840_ITSYBITSY, NRF52840_CIRCUITPLAY, NRF52840_CLUE, NRF52840_METRO, NRF52840_PCA10056, PARTICLE_XENON, NINA_B302_ublox, etc.Teensy core v1.57+
for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0) boards.ArduinoCore-mbed mbed_rp2040, mbed_nano, mbed_portenta core 3.4.1+
for Arduino (Use Arduino Board Manager) Portenta_H7, RP2040-based boards, such as Nano_RP2040_Connect, RASPBERRY_PI_PICO.Earle Philhower's arduino-pico core v2.6.3+
for RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040, etc.Arduino SAM DUE core v1.6.12+
for SAM DUE ARM Cortex-M3 boards.Arduino SAMD core 1.8.13+
for SAMD ARM Cortex-M0+ boards.Adafruit SAMD core 1.7.11+
for SAMD ARM Cortex-M0+ and M4 boards (Nano 33 IoT, etc.).Seeeduino SAMD core 1.8.3+
for SAMD21/SAMD51 boards (XIAO M0, Wio Terminal, etc.).
The best and easiest way is to use Arduino Library Manager
. Search for React_Generic
, then select / install the latest version.
You can also use this link for more detailed instructions.
- Navigate to React_Generic page.
- Download the latest release
React_Generic-main.zip
. - Extract the zip file to
React_Generic-main
directory - Copy the whole
React_Generic-main
folder to Arduino libraries' directory such as~/Arduino/libraries/
.
- Install VS Code
- Install PlatformIO
- Install React_Generic library by using Library Manager. Search for React_Generic in Platform.io Author's Libraries
- Use included platformio.ini file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at Project Configuration File
If you have worked with the Arduino framework before, it is likely that you will have come across the blink sketch. This is a simple program that flashes an LED every second, and it looks something like this:
#include <Arduino.h>
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
Using React_Generic, the sketch can be rewritten to the following:
#include <React_Generic.h>
using namespace react_generic;
React_Generic app;
setup()
{
pinMode(LED_BUILTIN, OUTPUT);
app.onRepeat(1000, [] ()
{
static bool state = false;
digitalWrite(LED_BUILTIN, state = !state);
});
}
void loop()
{
app.tick();
}
Instead of directly defining the program logic in the loop()
function, reactions are defined in the setup()
function. A reaction is a function that is executed when a certain event happens. In this case, the event is that the function should repeat every second, as defined by the onRepeat()
method call. The second argument to the onRepeat()
method is a lambda function that is executed every time the reaction is triggered. If the syntax feels weird, you can also use regular named functions instead of lambdas.
The app.tick()
call in the loop()
function is the main loop of the program. It is responsible for calling the reactions that have been defined. You can also add additional code to the loop()
function, any delays or other long-executing code should be avoided.
Charlie wants to make a simple program which echoes data on the Serial
port. Their Arduino sketch will looks like this:
#include <Arduino.h>
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available() > 0)
{
Serial.write(Serial.read());
}
yield();
}
This works, but Charlie decides that they would like to blink the built-in LED every time it processes data. Now, their sketch looks like this:
#include <Arduino.h>
void setup()
{
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
if (Serial.available() > 0)
{
Serial.write(Serial.read());
digitalWrite(LED_BUILTIN, HIGH);
delay(20);
digitalWrite(LED_BUILTIN, LOW);
}
yield();
}
The problem with this sketch is that whilst the LED is blinking, Charlie's program is not relaying data from the Serial port. The longer Charlie blinks the LED for, the slower the rate of transfer.
To solve this problem, Charlie refactors their code to look something like this:
#include <Arduino.h>
uint32_t start;
bool blink = false;
void setup()
{
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
if (Serial.available() > 0)
{
Serial.write(Serial.read());
blink = true;
start = millis();
digitalWrite(LED_BUILTIN, HIGH);
}
if (blink && millis() - start > 1000)
{
blink = false;
digitalWrite(LED_BUILTIN, LOW);
}
yield();
}
This solves Charlie's problem, but it's quite verbose. Using React_Generic, Charlie can write the same script like this:
#include <React_Generic.h>
using namespace react_generic;
React_Generic app;
void setup()
{
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
app.onAvailable(&Serial, [] ()
{
Serial.write(Serial.read());
digitalWrite(LED_BUILTIN, HIGH);
app.onDelay(1000, [] () { digitalWrite(LED_BUILTIN, LOW); });
});
}
void loop()
{
app.tick();
}
Callbacks can be not just void pointers but any callable supported by std::function
. This means they can use lambda captures or argument binding using std::bind
. For example, the following code creates 20 different repeating reactions updating different fields of an array:
static int timer_ticks[20];
for (int i=0; i<20; i++)
{
timer_ticks[i] = 0;
int delay = (i+1)*(i+1);
app.onRepeat(delay, [i]()
{
timer_ticks[i]++;
});
}
Note that beginning of React_Generic v2.0.0
, the React_Generic library has been wrapped in a React_Generic
namespace.
This is to avoid name conflicts with other libraries.
The impact to the user is that they need to define the namespace when using the library.
This can be done either globally by placing the following statement in the source code right after the #include
statements:
using namespace react_generic;
or by using the react_generic::
prefix when using the library:
react_generic::React_Generic app;
All of the registration functions return a Reaction
object pointer. This can be used to store and manipulate
the reaction. react_callback
is a typedef for std::function<void()>
and can therefore be any callable supported by the C++ standard template library.
DelayReaction app.onDelay(uint32_t t, react_callback cb);
Delay the execution of a callback by t
milliseconds.
RepeatReaction app.onRepeat(uint32_t t, react_callback cb);
Repeatedly execute a callback every t
milliseconds.
StreamReaction app.onAvailable(Stream *stream, react_callback cb);
Execute a callback when there is data available to read on an input stream (such as &Serial
).
ISRReaction app.onInterrupt(uint8_t pin_number, int mode, react_callback cb);
Execute a callback when an interrupt number fires. This uses the same API as the attachInterrupt()
Arduino function.
TickReaction app.onTick(react_callback cb);
Execute a callback on every tick of the event loop.
void Reaction::remove();
Remove the reaction from the execution queue.
Note: Calling remove()
for DelayReaction
objects is only safe if the reaction has not been triggered yet. Upon triggering, the DelayReaction
object is deleted and any pointers to it will be invalidated
minimal
: A minimal example with two timers switching the LED state.torture_test
: A stress test of twenty simultaneous repeat reactions as well as a couple of interrupts, a stream, and a tick reaction. For kicks, try changingNUM_TIMERS
to 200. Program performance will be practically unchanged!
Submit issues to: React_Generic issues
- Bug Searching and Killing
- Support more types of boards
- Add support to Arduino SAMD21 (ZERO, MKR, NANO_33_IOT, etc.)
- Add support to Adafruit SAMD21 (Itsy-Bitsy M0, Metro M0, Feather M0 Express, etc.).
- Add support to Adafruit SAMD51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.).
- Add support to Adafruit nRF52 ( Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, NINA_B112_ublox, etc..
- Add support to RP2040-based boards such as RASPBERRY_PI_PICO, using Arduino-mbed RP2040 core
- Add support to RP2040-based boards such as RASPBERRY_PI_PICO, using Earle Philhower's arduino-pico core
- Add support to Teensy
- Add astyle using
allman
style. Restyle the library
Many thanks for everyone for bug reporting, new feature suggesting, testing and contributing to the development of this library.
- Based on and modified from Andrew Carter's Reactduino
- Based on and modified from Matti Airas' ReactESP
⭐️ Andrew Carter |
⭐️ Matti Airas |
If you want to contribute to this project:
- Report bugs and errors
- Ask for enhancements
- Create issues and pull requests
- Tell other people about this library
- The library is licensed under MIT
- Copyright (c) 2017- Andrew Carter
- Copyright (c) 2019- Matti Airas
- Copyright (c) 2022- Khoi Hoang