eloquent – Eloquent Arduino Blog http://eloquentarduino.github.io/ Machine learning on Arduino, programming & electronics Sun, 22 Dec 2019 13:40:10 +0000 en-US hourly 1 https://wordpress.org/?v=5.3.6 Eloquent bounded waiting: the await construct https://eloquentarduino.github.io/2019/12/arduino-bounded-waiting/ Thu, 05 Dec 2019 18:50:59 +0000 https://eloquentarduino.github.io/?p=211 Sometimes you may need to wait for a certain condition to become true, but you don't want to wait forever: it may be awaiting for Serial, for the Wifi to connect to a network, or the response from a SoftwareSerial peripheral. The await construct lets you put an upper bound to the time you're willing […]

L'articolo Eloquent bounded waiting: the await construct proviene da Eloquent Arduino Blog.

]]>
Sometimes you may need to wait for a certain condition to become true, but you don't want to wait forever: it may be awaiting for Serial, for the Wifi to connect to a network, or the response from a SoftwareSerial peripheral. The await construct lets you put an upper bound to the time you're willing to wait.

Most often, you see example code of this kind:

Serial.print("Attempting to connect to WiFi");

while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
}

If the connection doesn't succeed (maybe the AP is out of range or is down), you're stuck in an endless wait. A proper way for handling such situations is with a timeout that gets you out of the loop with an error status so you can handle the failure.
await is exactly this: a construct to await for a condition to become true until a timeout expires, returning true or false as a response.

Definition

#define await(condition, timeout) await_with_interval(condition, timeout, 10)
#define await_with_interval(condition, timeout, interval) \
  ([]() { \
    uint32_t start = millis(); \
    while (millis() - start <= timeout) { \
      if (condition) return true; \
      delay(interval); \
    } \
  return false; })()

How to use

await needs at least two arguments:

  1. the condition to await for
  2. the timeout, in milliseconds
// these are for greater code readability
#define Millis 
#define Second  *1000
#define Seconds *1000
bool wifiConnected = await(WiFi.status() == WL_CONNECTED, 10 Seconds)

The code above will wait 10 seconds for the wifi to connect: on failure, wifiConnected will be false and you can gently fail.

You can use it for any kind of check, like waiting for Serial.

bool serialReady = await(Serial, 5 Seconds)
bool serialHasCharacters = await(Serial.available(), 5 Seconds)

The default interval between checks is 10 milliseconds: if you need a custom delay interval you can use the more verbose await_with_interval:

// await WiFi for 10 seconds, check if connected every 500 millis
bool wifiConnected = await_with_interval(WiFi.status() == WL_CONNECTED, 10 Seconds, 500 Millis)

How it works

The await macro creates an inline function that loops until the timeout expires. At every loop it checks if the condition is true: if that's the case, it returns true. The inline function construct is needed to get a return value, so you can assign it to a variable or embed directly inside an if test. The following code sample gives you an idea of what's happening.

bool wifiConnected = await(WiFi.status() == WL_CONNECTED, 10 Seconds)

// conceptually translates to

bool inline_function() {
    uint32_t start = millis();

    while (millis() - start <= 10000) {
      if (WiFi.status() == WL_CONNECTED)
        return true;

      delay(10);
    }

   return false;
}

bool wifiConnected = inline_function();

L'articolo Eloquent bounded waiting: the await construct proviene da Eloquent Arduino Blog.

]]>
Eloquent non-blocking code: the Every construct https://eloquentarduino.github.io/2019/12/non-blocking-arduino-code/ Thu, 05 Dec 2019 18:42:45 +0000 https://eloquentarduino.github.io/?p=209 The every construct lets you run a piace of code at regular intervals in a fluent way. If you don't need to start, stop, pause your timer, this construct is a valid alternative to more complex timer libraries already available: it only takes a time interval as argument and will execute the code block periodically. […]

L'articolo Eloquent non-blocking code: the Every construct proviene da Eloquent Arduino Blog.

]]>
The every construct lets you run a piace of code at regular intervals in a fluent way. If you don't need to start, stop, pause your timer, this construct is a valid alternative to more complex timer libraries already available: it only takes a time interval as argument and will execute the code block periodically.

Definition

#define every(interval) \
    static uint32_t __every__##interval = millis(); \
    if (millis() - __every__##interval >= interval && (__every__##interval = millis()))

How to use

// these are for greater code readability
#define Millis 
#define Second  *1000
#define Seconds *1000
int interval = 1 Second;

void setup() {
    Serial.begin(115200);
}

void loop() {
    every(1000 Millis) {
        Serial.println("This line is printed every 1 second");
    }

    every(2000 Millis) {
        Serial.println("This line is printed every 2 seconds");
    }

    every(interval) {
        interval += 1 Second;
        Serial.print("You can have variable intervals too! ");
        Serial.print("This line will be printed again in ");
        Serial.print(interval / 1000);
        Serial.println(" seconds");
    }
}

Caveats

every is just a macro definition and is not a proper timer, so it has some limitations:

  1. you can't stop, pause or resume it: once set, it will run forever
  2. its argument must be the suffix of a valid identifier
  3. you can't use several every with the exact same argument: you have to put all the code that needs to happen at the same interval in the same block

Caveat #2

The macro works by generating a variable named like __every__##argument

every(1) ==> uint32_t __every__1;
every(2) ==> uint32_t __every__2;
every(a_given_interval) ==> uint32_t __every__a_given_interval;
every(an invalid interval) ==> uint32_t __every__an invalid interval; // Syntax error
every(1 Second) ==> uint32_t __every__1 *1000; // Syntax error

So every integer literal and any variable are all valid arguments. Any expression is forbidden.

Caveat #3

If you use two every with the exact same argument, two variables with the exact same name will be created and it will rise a compile-time error.

If you can live with this limitations, every only needs the space of an uint32_t to work.

L'articolo Eloquent non-blocking code: the Every construct proviene da Eloquent Arduino Blog.

]]>
How to write clean Arduino code: introducing the Eloquent library https://eloquentarduino.github.io/2019/11/how-to-write-clean-arduino-code/ Sun, 03 Nov 2019 16:05:46 +0000 https://eloquentarduino.github.io/?p=164 Eloquent Arduino is an attempt to bring sanity and clarity in Arduino projects. The purpose of this library is to create a wide range of constructs to clearly translate your ideas into meaningful code: stop writing spaghetti code only you can undestand, please! I'll show you how. The problem Arduino sells itself as a platform well […]

L'articolo How to write clean Arduino code: introducing the Eloquent library proviene da Eloquent Arduino Blog.

]]>
Eloquent Arduino is an attempt to bring sanity and clarity in Arduino projects. The purpose of this library is to create a wide range of constructs to clearly translate your ideas into meaningful code: stop writing spaghetti code only you can undestand, please! I'll show you how.

from https://www.wlion.com/blog/5-reasons-you-should-be-writing-clean-code/

The problem

Arduino sells itself as a platform well suited for beginners, and it is for sure; lots of non-tech people are able to bring their ideas to life thanks to this awesome platform.
Nevertheless, I often stumble upon bits of code over the internet that make me question about the quality of the projects people are producing.

Even the Arduino official website is misleading in this sense, in my opinion, since it promotes a code style really straighforward, but suited for toy projects, with little logics and low complexity level.

Here's an example of what I'm talking about, copy-pasted from the Arduino official site (with comments removed):

const int ledPin =  LED_BUILTIN;
int ledState = LOW;
unsigned long previousMillis = 0; 
const long interval = 1000; 

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    digitalWrite(ledPin, ledState);
  }
}

Can you tell what this code does with a minimum mental effort?
I don't think so (you may have recognized the async pattern and it actually blinks a LED in a non-blocking fashion).

THIS is the problem: most Arduino code is not clear at first glance, is not eloquent. By eloquent I mean code that speaks by itself, without the need for comments.


most Arduino code is not clear at first glance, is not eloquent
Click To Tweet


The solution

What about the following?

DigitalOut led(LED_BUILTIN);

void setup() {
    led.begin();
}

void loop() {
    every(1 Second) {
        led.toggle();
    }
}

I swear this is valid code that compiles just fine. Hopefully, it does the exact same thing as above, yet it is far more readable and understandable.

Can you see my point now? Wouldn't it be much easier and reliable to code with the help of a set of such eloquent constructs / interfaces? I strongly believe it is, and this is why I'm writing this library.
Asynchronous programming, pin state managements, animations are bits of code that pop up over and over again in most of the projects, yet every time we start from zero and write the same boilerplate code over and over again.


Boilerplate code is not only tedious, but error-prone. And lengthy. Start writing eloquent code now!
Click To Tweet


Boilerplate code heavily relies on a fixed structure that could be hard to adapt to your specific case. Longer code means more chances to break something and more code to debug, which can waste lots of your valuable time.


I'm starting a series of posts where I'll document some of the classes and constructs the library provides to you. You can find the code on the Github repo.

L'articolo How to write clean Arduino code: introducing the Eloquent library proviene da Eloquent Arduino Blog.

]]>