Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.
/ React_Generic Public archive

Asynchronous programming library for the generic microcontrollers compatible with the Arduino framework. Currently supporting ESP32, ESP8266, SAMD21/SAMD51, RP2040, STM32, nRF52, Teensy 4.x

License

Notifications You must be signed in to change notification settings

khoih-prog/React_Generic

Repository files navigation

React_Generic Library

arduino-library-badge GitHub release contributions welcome GitHub issues C++ license: MIT

Donate to my libraries using BuyMeACoffee



Table of Contents



Why do we need this React_Generic library

Features

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.

Currently supported Boards

This React_Generic library currently supports these following boards:

  1. ESP32

  2. ESP8266

  3. WT32_ETH01 (ESP32 + LAN8720A)

  4. 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
  1. 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-

  1. SAMD21/SAMD51

  2. 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.

  3. Teensy 4.1 using QNEthernet Library

  4. RASPBERRY_PI_PICO using arduino-pico core v2.5.2+



Prerequisites

  1. Arduino IDE 1.8.19+ for Arduino. GitHub release
  2. ESP32 Core 2.0.45 for ESP32-based boards. Latest release
  3. ESP8266 Core 3.0.2+ for ESP8266-based boards. Latest release.
  4. 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. GitHub release
  5. Teensy core v1.57+ for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0) boards.
  6. 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. GitHub release
  7. 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. GitHub release
  8. Arduino SAM DUE core v1.6.12+ for SAM DUE ARM Cortex-M3 boards.
  9. Arduino SAMD core 1.8.13+ for SAMD ARM Cortex-M0+ boards. GitHub release
  10. Adafruit SAMD core 1.7.11+ for SAMD ARM Cortex-M0+ and M4 boards (Nano 33 IoT, etc.). GitHub release
  11. Seeeduino SAMD core 1.8.3+ for SAMD21/SAMD51 boards (XIAO M0, Wio Terminal, etc.). Latest release


Installation

Use Arduino Library Manager

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 arduino-library-badge for more detailed instructions.

Manual Install

  1. Navigate to React_Generic page.
  2. Download the latest release React_Generic-main.zip.
  3. Extract the zip file to React_Generic-main directory
  4. Copy the whole React_Generic-main folder to Arduino libraries' directory such as ~/Arduino/libraries/.

VS Code & PlatformIO:

  1. Install VS Code
  2. Install PlatformIO
  3. Install React_Generic library by using Library Manager. Search for React_Generic in Platform.io Author's Libraries
  4. 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


HOWTO Use

Blink

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.


Why Bother?

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();
}

Advanced callback support

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]++;
  });
}


API

Namespace use

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;

Event Registration Functions

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.

Management functions

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



Examples:

Original Examples

  1. minimal: A minimal example with two timers switching the LED state.
  2. 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 changing NUM_TIMERS to 200. Program performance will be practically unchanged!

multiFileProject Examples



Issues

Submit issues to: React_Generic issues


TO DO

  1. Bug Searching and Killing
  2. Support more types of boards

DONE

  1. Add support to Arduino SAMD21 (ZERO, MKR, NANO_33_IOT, etc.)
  2. Add support to Adafruit SAMD21 (Itsy-Bitsy M0, Metro M0, Feather M0 Express, etc.).
  3. Add support to Adafruit SAMD51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.).
  4. 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..
  5. Add support to RP2040-based boards such as RASPBERRY_PI_PICO, using Arduino-mbed RP2040 core
  6. Add support to RP2040-based boards such as RASPBERRY_PI_PICO, using Earle Philhower's arduino-pico core
  7. Add support to Teensy
  8. Add astyle using allman style. Restyle the library


Contributions and Thanks

Many thanks for everyone for bug reporting, new feature suggesting, testing and contributing to the development of this library.

  1. Based on and modified from Andrew Carter's Reactduino
  2. Based on and modified from Matti Airas' ReactESP
AndrewCarterUK
⭐️ Andrew Carter

mairas
⭐️ Matti Airas


Contributing

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


License

  • The library is licensed under MIT

Copyright

  • Copyright (c) 2017- Andrew Carter
  • Copyright (c) 2019- Matti Airas
  • Copyright (c) 2022- Khoi Hoang