Coder Social home page Coder Social logo

end2endzone / softtimers Goto Github PK

View Code? Open in Web Editor NEW
14.0 3.0 0.0 573 KB

A collection of software timers that allows one to properly time multiple events and know when each "timer" expires meaning that an action is required. The library aims at greatly simplifying multitask complexity.

License: MIT License

Batchfile 30.55% PowerShell 1.32% C++ 34.19% CMake 4.78% Shell 21.36% Python 7.80%
arduino non-blocking timing timers

softtimers's Introduction

SoftTimers logo

License: MIT Github Releases

SoftTimers

The SoftTimers arduino library is a collection of software timers. It allows one to properly time multiple events and know when each "timer" expires meaning that an action is required. SoftTimers can also be used to compute the elapsed time since an event occured. The library aims at greatly simplifying multitask complexity.

Library features:

  • Provides the non-blocking equivalent to delay() function.
  • Each timers encapsulate its own expiration (timeout) time.
  • Provides elapsed time, remaining time and progress (in percentage) APIs.
  • Supports milliseconds, microseconds or any other arbitrary time with external time counting function.
  • Provides expiration loop count API (as if timer never expire and automatically reset()) to easily implement toggling, and time based state machines.
  • Automatically handles micros() and millis() overflows / wrap around special cases.
  • Provides multitasking abilities to sketches.

Status

Build:

Service/Platform Build Tests
AppVeyor Build status Tests status
Windows Server 2019 Build on Windows Tests on Windows
Ubuntu 22.04 Build on Linux Tests on Linux

Statistics:

AppVeyor GitHub
Statistics Statistics

Purpose

Consider the arduino Blick tutorial. It uses the delay() function to know when to toggle a LED on and off. This approach is bad since it breaks the "realtime" property of the software to react to other event. If I want to make the LED instantly turn off when pressing a button, I had to wait for the delay to complete before processing the button.

Another issue is extensibility. Making 3 LEDs blink at different time interval is much harder with delays. How about 40 LEDs? Impossible?

The SoftTimers allows one to properly time multiple events and know when each "timer" expires meaning that an action is required. In this example above, a SoftTimer expires when it is time to toggle a LED.

SoftTimers also provide the elapsed time since an event occurred. In case of an interruption, the elapsed time can be used as debugging information. It can also be used as a countdown information displayed to the user.

The library regroups basic timer functionalities into a single class. The usual way to get the same functionality is to create multiple variables for each single timer. This method is hard to maintain when you need multiple timers to run at the same time.

SoftTimer classes are designed to be keep "simple and stupid". No software interrupts. Non-blocking. Each timer must be polled within the loop() to know their status.

Usage

The following instructions show how to use the library.

General

To use a SoftTimers, create a variable of type SoftTimer in the global scope of the program.

SoftTimer myRefreshTimer;

In setup(), call setTimeOutTime() to setup the non-blocking SoftTimer then call reset() to initialize the internal counter.

void setup() {
  myRefreshTimer.setTimeOutTime(30000); // every 30 seconds.
  myRefreshTimer.reset();
}

Within the loop(), call hasTimedOut() to know if the timer has expired.

void loop() {
  if (myRefreshTimer.hasTimedOut())
  {
    //TODO: refresh the input pins
    
    myRefreshTimer.reset(); //next refresh in 30 seconds
  }
}

At any moment, call getElapsedTime() or getRemainingTime() to get the absolute elapsed/remaining time since the last reset().

void loop() {
  if (!myRefreshTimer.hasTimedOut())
  {
    static uint32_t count = 0;
    count++;
    if (count == 1000) //print remaining time 1/1000 of loops
    {
      //show user how much time left in milliseconds
      uint32_t remaining = countdown.getRemainingTime();
      Serial.print(remaining);
      Serial.println(" ms...");
    }
  }
}

Fade a LED

Fading a LED like in arduino's Fade Example is trivial using SoftTimers. The library helps in defining the constant speed at which the LED will fade by defining the total length of the process and by easily mapping the timer "progress" to the amount of fade (PWM) used with the output pin. All of this in a non-blocking manner.

The following example increases the intensity of a LED from OFF to ON in 1 second and then decreases the intensity of the LED back to OFF in 1 second.

#include <SoftTimers.h>
 
#define LED_PIN 9
 
/**************************************************
 *Fade a LED as the Fade basic example:
 *Increse the intensity of a LED from OFF to ON in 1 seconds
 *then ON to OFF in 1 seconds
 **************************************************/
SoftTimer fadeTimer; //millisecond timer
 
void setup() {
  pinMode(LED_PIN, OUTPUT);
 
  Serial.begin(115200);
  
  //update timers
  fadeTimer.setTimeOutTime(1000); // every 1 second.
 
  //start counting
  fadeTimer.reset();
}
 
void loop() {
  //determine the direction of brightness
  int direction = fadeTimer.getLoopCount() % 2; //returns 0 or 1
  bool increasing = (direction == 0); //assign increasing brightness with direction 0
 
  //get progress
  double progress = fadeTimer.getLoopProgress();
 
  //correct progress based on direction
  if (!increasing)
  {
    progress = 1.0 - progress;
  }
 
  //map progress to a 0-255 brightness intensity.
  uint16_t brightness = progress*255;
  
  //update the LED
  analogWrite(LED_PIN, brightness);
}

Countdown or Elapsed time

Any program that need to display a countdown or compute the elapsed time between two events can also benefit from SoftTimers.

The following example runs a countdown of 5 seconds and then turns a LED on.

#include <SoftTimers.h>

#define LED_PIN 13

/**************************************************
 * Run a countdown from 5 second to 0 and turn LED on
 **************************************************/
SoftTimer countdown; //millisecond timer

void setup() {
  pinMode(LED_PIN, OUTPUT);

  Serial.begin(115200);
  
  //update timers
  countdown.setTimeOutTime(5000); // 5 seconds
  
  //start counting now
  countdown.reset();
}

void loop() {
  if (!countdown.hasTimedOut())
  {
    //show user how much time left in milliseconds
    uint32_t remaining = countdown.getRemainingTime();
    Serial.print(remaining);
    Serial.println(" ms...");
  }
  else
  {
    //turn ON the LED
    digitalWrite(LED_PIN, HIGH);
  }
}

Timed repetitive cycles

SoftTimer library also help reducing repetitive timed cycles to their simplest non-blocking form. SoftTimer library automatically computes current cycle index. Any toggling or cycle scenarios can be implemented with very few lines of code.

The following example implements a system where a single HIGH pin must be cycled every second within multiple pins as defined by the following loop:

  • set pin 8, 9 and 13 to LOW, LOW and HIGH respectively and then wait 1 second.
  • set pin 8, 9 and 13 to HIGH, LOW and LOW respectively and then wait 1 second.
  • set pin 8, 9 and 13 to LOW, HIGH and LOW respectively and then wait 1 second.
  • repeat the cycle forever...
#include <SoftTimers.h>

#define LED_PIN_0 13
#define LED_PIN_1  8
#define LED_PIN_2  9

/**************************************************
 *Every second, cycle the HIGH pin within pins 13,8,9
 **************************************************/
SoftTimer cyclePinTimer; //millisecond timer

void setup() {
  pinMode(LED_PIN_0, OUTPUT);
  pinMode(LED_PIN_1, OUTPUT);
  pinMode(LED_PIN_2, OUTPUT);

  Serial.begin(115200);
  
  //update timers
  cyclePinTimer.setTimeOutTime(1000); // every 1 second.

  //start counting
  cyclePinTimer.reset();
}

void loop() {
  uint32_t loopCount = cyclePinTimer.getLoopCount();
  uint32_t pinHighNumber = (loopCount % 3); //from 0 to 2
  
  if (pinHighNumber == 0)
  {
    //turn ON the LED 0, turn OFF all other
    digitalWrite(LED_PIN_0, HIGH);
    digitalWrite(LED_PIN_1,  LOW);
    digitalWrite(LED_PIN_2,  LOW);
  }
  else if (pinHighNumber == 1)
  {
    //turn ON the LED 1, turn OFF all other
    digitalWrite(LED_PIN_0,  LOW);
    digitalWrite(LED_PIN_1, HIGH);
    digitalWrite(LED_PIN_2,  LOW);
  }
  else //if (pinHighNumber == 2)
  {
    //turn ON the LED 2, turn OFF all other
    digitalWrite(LED_PIN_0,  LOW);
    digitalWrite(LED_PIN_1,  LOW);
    digitalWrite(LED_PIN_2, HIGH);
  }
}

Timed restricted state machines

SoftTimer library allows one to make an easy abstraction of time when dealing with timed restricted state machines.

The following example implement an hypothetical state machine where each state has a maximum duration:

  • State #1 – IDLE (1000 ms)
  • State #2 – LISTENING (200 ms)
  • State #3 – SYNCHRONIZING (500 ms)
  • State #4 – UPDATING (300 ms)
  • State #1 ...
#include <SoftTimers.h>

/**************************************************
 * An hypothetical state machine needs to step from 
 * state to state. Each state has its own maximum 
 * duration:
 * State #1 - IDLE (1000 ms)
 * State #2 - LISTENING (200 ms)
 * State #3 - SYNCHRONIZING (500 ms)
 * State #4 - UPDATING (300 ms)
 * State #1 ...
 **************************************************/
 
SoftTimer nextStateTimer; //millisecond timer

const int STATE_IDLE = 0;
const int STATE_LISTENING = 1;
const int STATE_SYNCHRONIZING = 2;
const int STATE_UPDATING = 3;

int state = STATE_IDLE;

void setup() {
  Serial.begin(115200);
  
  //update timers
  nextStateTimer.setTimeOutTime(1000); // IDLE, 1 second.

  //start counting now
  nextStateTimer.reset();
}

void loop() {
  //show current state
  switch(state)
  {
  case STATE_IDLE:
    Serial.println("IDLE");
    break;
  case STATE_LISTENING:
    Serial.println("LISTENING");
    break;
  case STATE_SYNCHRONIZING:
    Serial.println("SYNCHRONIZING");
    break;
  case STATE_UPDATING:
    Serial.println("UPDATING");
    break;
  default:
    Serial.println("UNKNOWN STATE!");
    break;
  };

  //look for next state...
  if (nextStateTimer.hasTimedOut())
  {
    state++;

    //limit state to known states
    state = state%(STATE_UPDATING+1);

    //reconfugure time based on new state
    switch(state)
    {
    case STATE_IDLE:
      nextStateTimer.setTimeOutTime(1000);
      break;
    case STATE_LISTENING:
      nextStateTimer.setTimeOutTime(200);
      break;
    case STATE_SYNCHRONIZING:
      nextStateTimer.setTimeOutTime(500);
      break;
    case STATE_UPDATING:
      nextStateTimer.setTimeOutTime(300);
      break;
    default:
      Serial.println("UNKNOWN STATE!");
      break;
    };

    //start counting now
    nextStateTimer.reset();
  }

  //hypothetical work...
  //processState()
}

Compute performance of a function or a section of code (a.k.a profiling)

SoftTimer library allows one to easily compute the performance of a function or a section of code.

This feature is usefull for debugging. For example, it can be used to identify a section of code or an algorithm that needs to be optimized.

It is particuly usefull with microcontrollers that are equiped with a Watchdog Timer that resets the microcontroller if the loop() function appears to be blocking. The profiling classes SoftTimerProfiler, SoftTimerProfilerMillis and SoftTimerProfilerMicros provides an easy way to identify "blocking" sections of code that needs to be re-written in a non-blocking way.

The following example uses a SoftTimerProfiler to compute the average time of the following:

  • The function analogRead() with microseconds resolution.
  • An implementation of Bubble Sort algorithm with milliseconds resolution.
#include <SoftTimers.h>

#define ANALOG_PIN A0

/****************************************************************
 * Compute the minimum, maximum and average time of a function or
 * a section of code to execute.
 ****************************************************************/

int loop_count = 0;

static const int unsorted_values[] PROGMEM = {
179, 211, 219, 307, 495, 462, 485, 396, 286, 189, 361, 122, 312, 398, 218, 487, 287, 452, 86, 297, 147, 196, 298, 158, 265, 136, 229, 301, 412, 160, 300,
168, 489, 407, 34, 303, 443, 2, 149, 391, 131, 228, 360, 128, 343, 271, 294, 186, 69, 267, 164, 10, 340, 223, 63, 140, 132, 508, 258, 496, 457, 266, 44,
43, 115, 313, 447, 57, 247, 123, 296, 7, 499, 399, 112, 198, 126, 374, 213, 163, 220, 335, 474, 473, 451, 161, 420, 475, 18, 37, 212, 104, 144, 245, 28,
410, 143, 60, 446, 356, 127, 162, 224, 365, 510, 170, 109, 54, 137, 392, 155, 16, 330, 389, 302, 225, 467, 89, 153, 317, 275, 436, 184, 107, 388, 56, 230,
319, 270, 174, 488, 156, 280, 347, 30, 497, 148, 409, 38, 8, 454, 382, 427, 358, 461, 441, 274, 251, 135, 181, 440, 387, 263, 23, 311, 422, 426, 509, 468,
345, 173, 460, 90, 76, 39, 332, 385, 1, 484, 432, 419, 310, 64, 53, 390, 242, 222, 491, 324, 221, 283, 444, 237, 350, 134, 70, 45, 470, 395, 171, 29, 48,
209, 116, 429, 207, 438, 273, 328, 289, 423, 479, 459, 210, 430, 252, 259, 11, 167, 406, 185, 244, 142, 425, 35, 25, 450, 206, 78, 367, 12, 238, 309, 77,
264, 133, 415, 85, 208, 66, 493, 9, 180, 404, 351, 187, 483, 49, 91, 32, 166, 339, 394, 130, 94, 333, 243, 169, 58, 241, 165, 232, 22, 299, 276, 393, 82,
354, 103, 192, 88, 418, 84, 5, 119, 500, 6, 42, 190, 59, 341, 414, 110, 379, 463, 282, 151, 195, 480, 503, 150, 348, 377, 239, 346, 75, 19, 372, 3, 125,
417, 413, 323, 336, 506, 73, 261, 424, 95, 256, 15, 408, 201, 98, 233, 384, 327, 355, 260, 124, 14, 284, 326, 46, 17, 191, 72, 79, 363, 397, 51, 511, 437,
453, 386, 472, 102, 501, 357, 93, 215, 369, 183, 117, 177, 269, 381, 492, 308, 154, 456, 486, 305, 466, 316, 105, 272, 13, 67, 254, 157, 315, 121, 108,
375, 442, 203, 97, 338, 400, 376, 52, 36, 33, 490, 290, 27, 20, 113, 494, 26, 81, 4, 321, 401, 325, 47, 65, 458, 295, 481, 74, 465, 250, 193, 50, 279, 24,
380, 433, 235, 383, 285, 364, 306, 145, 505, 362, 507, 448, 268, 434, 111, 202, 138, 370, 322, 455, 236, 101, 471, 139, 129, 405, 334, 234, 291, 141, 371,
342, 159, 477, 99, 329, 314, 359, 21, 100, 257, 172, 352, 318, 320, 199, 176, 61, 246, 204, 240, 504, 502, 214, 416, 41, 449, 227, 178, 293, 92, 366, 182,
435, 253, 469, 331, 118, 96, 152, 55, 402, 498, 194, 445, 248, 353, 205, 421, 231, 226, 431, 344, 114, 277, 31, 464, 278, 216, 262, 40, 80, 106, 120, 68,
439, 476, 304, 87, 71, 175, 403, 349, 146, 83, 249, 373, 197, 288, 411, 428, 200, 281, 378, 292, 62, 368, 188, 337, 255, 217, 482, 478,};
static const size_t unsorted_values_count = sizeof(unsorted_values) / sizeof(unsorted_values[0]);
static const size_t sorted_values_count = unsorted_values_count;
static int sorted_values[sorted_values_count];

void setup() {
  pinMode(ANALOG_PIN, INPUT);

  Serial.begin(115200);
  Serial.println("ready");
}

void profileAnalogRead() {
  SoftTimerProfiler profiler(&micros); // microseconds profiler
  profiler.reset();

  for(int i=0; i<1000; i++) {
    profiler.start();
    int value = analogRead(ANALOG_PIN);
    profiler.stop();
  }

  profiler.end();
  profiler.print("analogRead");
}

void printArray(int array[], size_t count) {
  Serial.println("<values>");
  for(size_t i=0; i<count; i++) {
    Serial.print(array[i]);
    bool is_last = !(i+1<count);
    if (!is_last)
      Serial.print(", ");
  }
  Serial.println();
  Serial.println("</values>");
}

// perform the bubble sort
void bubbleSort(int array[], int size) {

  // loop to access each array element
  for (int step = 0; step < size - 1; ++step) {
      
    // loop to compare array elements
    for (int i = 0; i < size - step - 1; ++i) {
      
      // compare two adjacent elements
      // change > to < to sort in descending order
      if (array[i] > array[i + 1]) {
        
        // swapping occurs if elements
        // are not in the intended order
        int temp = array[i];
        array[i] = array[i + 1];
        array[i + 1] = temp;
      }
    }
  }
}

void profileBubbleSort() {
  SoftTimerProfilerMillis profiler; // milliseconds profiler
  profiler.reset();

  for(int i=0; i<50; i++) {
    // Copy unsorted values into the array that we will sort.
    // This operation is outside of the scope of the profiler.
    memcpy_P(&sorted_values, unsorted_values, sizeof(sorted_values));
    //printArray(sorted_values, sorted_values_count);

    profiler.start();
    bubbleSort(sorted_values, sorted_values_count);
    profiler.stop();
  }

  profiler.end();
  profiler.print("bubbleSort");
}

void loop() {
  if (loop_count%2 == 0)
    profileAnalogRead();
  else
    profileBubbleSort();

  loop_count++;
}

The above sketch outputs the following to the serial port:

analogRead {
  count:1000
  total:97009
  avg:  97.01
  min:  94
  max:  111
}
bubbleSort {
  count:50
  total:1063
  avg:  21.26
  min:  21
  max:  22

On average, the function analogRead() executes in 97.01 microseconds. The fastest call took 94 us and a worst call took 111 us.

The Bubble Sort algorithm executes on average in 21.26 milliseconds on this particular unsorted array of integers. Since the minimum and maximum times are almost identical, the algorithm does not seems to be affected by external factors.

Other

More SoftTimer examples are also available:

Building

Please refer to file INSTALL.md for details on how installing/building the application.

Platforms

SoftTimers has been tested with the following platform:

  • Linux x86/x64
  • Windows x86/x64

Versioning

We use Semantic Versioning 2.0.0 for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE file for details

softtimers's People

Contributors

end2endzone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

softtimers's Issues

Refactor build process to use Arduino CLI instead of Arduino IDE

Latest version of Arduino IDE does not include the command line build tool. This change is breaking continuous integration scripts on AppVeyor and Github Actions.

The solution is to use Arduino CLI instead and continue building this library from the command line.

error: invalid conversion from 'long unsigned int (*)()' to 'SoftTimer::CounterFunctionPointer {aka unsigned int (*)()}' [-fpermissive]

I got this error running a slightly modified version of one of your examples running it on an 8266. Hard to see how my small mods could have caused this. Here's more of the compiler ouput <D:\David\MyDocuments\Arduino\libraries\SoftTimers\src/SoftTimers.h: In constructor 'SoftTimerMillis::SoftTimerMillis()':

D:\David\MyDocuments\Arduino\libraries\SoftTimers\src/SoftTimers.h:122:40: error: invalid conversion from 'long unsigned int ()()' to 'SoftTimer::CounterFunctionPointer {aka unsigned int ()()}' [-fpermissive]

SoftTimerMillis() : SoftTimer(&millis)

                                    ^

D:\David\MyDocuments\Arduino\libraries\SoftTimers\src/SoftTimers.h:36:3: error: initializing argument 1 of 'SoftTimer::SoftTimer(SoftTimer::CounterFunctionPointer)' [-fpermissive]

SoftTimer(CounterFunctionPointer iCntFuncPtr);

^
D:\David\MyDocuments\Arduino\libraries\SoftTimers\src/SoftTimers.h: In constructor 'SoftTimerMicros::SoftTimerMicros()':

D:\David\MyDocuments\Arduino\libraries\SoftTimers\src/SoftTimers.h:131:40: error: invalid conversion from 'long unsigned int ()()' to 'SoftTimer::CounterFunctionPointer {aka unsigned int ()()}' [-fpermissive]

SoftTimerMicros() : SoftTimer(&micros)

D:\David\MyDocuments\Arduino\libraries\SoftTimers\src/SoftTimers.h:36:3: error: initializing argument 1 of 'SoftTimer::SoftTimer(SoftTimer::CounterFunctionPointer)' [-fpermissive]

SoftTimer(CounterFunctionPointer iCntFuncPtr);>

Here's the code
<#include <SoftTimers.h>
#include "Arduino_DebugUtils.h"

// My libraries
#include "boardconfig.h"

/**************************************************

  • Wait 1 second, turn on a LED for 0.3 second.
    **************************************************/
    SoftTimer delayTimer; //millisecond timer
    SoftTimer ledTimer; //millisecond timer

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

Serial.begin(115200);

//update timers
delayTimer.setTimeOutTime(1000); // 1 second.
ledTimer.setTimeOutTime(2000); // 2 second.

//start counting now
delayTimer.reset();
ledTimer.reset();
}

void loop() {
if (!delayTimer.hasTimedOut())
{
Serial.println("waiting...");

//reset LED timer so that is does not time out before delayTimer
ledTimer.reset();

}

//did we waited long enough ?
else if (delayTimer.hasTimedOut() && !ledTimer.hasTimedOut())
{
Serial.println("turning LED ON...");

//turn ON the LED
digitalWrite(ledPin, HIGH);

}

//should the LED be turned OFF ?
else if (delayTimer.hasTimedOut() && ledTimer.hasTimedOut())
{
Serial.println("turning LED OFF...");

//turn OFF the LED
digitalWrite(ledPin, LOW);

//restart both timers
delayTimer.reset();
ledTimer.reset();

}
}>
and
</*

  • Board config library
    */
    #ifndef BOARDCONFIG_H
    #define BD_VER 1 // set to board version being targetted
    #ifndef D5
    #if defined(ESP8266)
    #define D0 (16)
    #define D1 (5)
    #define D2 (4)
    #define D3 (0)
    #define D4 (2)
    #define D5 (14)
    #define D6 (12)
    #define D7 (13)
    #define D8 (15)
    #define TX (1)
    #define RX (3)
    #elif defined(ESP32)
    #define D5 (18)
    #define D6 (19)
    #define D7 (23)
    #define D8 (5)
    #define TX (1)
    #endif
    #endif

if BD_VER == 1

const int sclPin = D1;
const int sdaPin = D2;
const int fanPin = D3;
const int ledPin = D4;
const int piezoPin = D5;
const int thPin = D6;
const int h2oPin = D7;
const int adcPin = A0;

elif BD_VER == 2

const int sclPin = D1;
const int sdaPin = D2;
const int fanPin = D3;
const int ledPin = D4;
const int swrxPin = D5;
const int swtxPin = D6;
const int openPin = D7;
const int dirPin = D8;
const int adcPin = A0;

else

const int ledPin = D0;
const int sclPin = D1;
const int sdaPin = D2;
const int fanPin = D3;
const int fanspdPin = D4;
const int swrxPin = D5;
const int swtxPin = D6;
const int openPin = D7;
const int dirPin = D8;
const int adcPin = A0; //Connected to fault output of switch to fan
#endif //BD_VER logic
#endif BOARDCONFIG_H>

compile error - basic example

getting a compile error:

Invalid conversion from 'void ()(uint8_t, unsigned int, long unsigned int)' {aka 'void ()(unsigned char, unsigned int, long unsigned int)'} to 'anyrtttl::ToneFuncPtr' {aka 'void (*)(unsigned char, short unsigned int, unsigned int)'} [-fpermissive]
ToneFuncPtr _tone = &tone;

when trying to compile the basic example, pulled latest from arduino ide, v 2.2.0

Running unit tests on 64 bit Linux

When running unit test on a 64 bit Linux platform, the following unit tests is failing and shows the following output:

[ RUN      ] TestSoftTimers.testMicrosOverflow
/home/runner/work/SoftTimers/SoftTimers/test/TestSoftTimers.cpp:100: Failure
Value of: t.hasTimedOut()
  Actual: true
Expected: false
Unexpected timeout! getElapsedTime() returns 18446744069414584627. micros() returns 53
[  FAILED  ] TestSoftTimers.testMicrosOverflow (0 ms)

This is because unsigned long is 64 bit on Linux 64 bit. The win32Arduino unit test library used to define the return type of millis and micros functions as uint32_t which was forcing 32 bits even on 64 bit systems. Following the correction for #5, both functions return type is now unsigned long (which is matching the official Arduino.h definition) but this creates issues with unit tests.

Unit tests must be corrected to run without errors in both 32 bit and 64 platforms.

Related to issue #5.

Build on GitHub Actions

The library CI build service should be migrated to GitHub Actions now that Travis CI is not free anymore.

Add new example: limit the quantity of printed messages

Create a new example to show that the class can be used to limit the number of printed messages per time.

The example should be a sketch that prints the state of a button. The state should be printed at every loop. However, the code should also verify if the time has timed out to know if the message can actually be printed. Timer should be reset each time a new message is printed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.