After some googling, i decided to try to write and arduino library to simplify use of "millis" trick to schedule jobs with 'clean api'.
Here is some code of blink:
#include "SimpleScheduler.h"
void ledOn();
void ledOff();
void ledOn() {
digitalWrite(LED_BUILTIN, HIGH);
schedule(500, ledOff);
}
void ledOff() {
digitalWrite(LED_BUILTIN, LOW);
schedule(500, ledOn);
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
ledOn();
}
void loop() {
scheduler_run();
}
you can find library at github arduino SimpleScheduler
void setup() {
Serial.begin(9600);
// get data from Serial.readStringUntil('\n'); to memory
String data="FFFFFFFF 00FFFFFF 0000FFFF 000000FF";
// store length of data
int iend = data.length() - 1;
// current begin index
int index=0;
// next index
int next_index;
do{
next_index=data.indexOf(' ',index);
String hexcode=data.substring(index, next_index);
index=next_index+1;
unsigned long bigNumber = (unsigned long)strtoul(hexcode.c_str(), 0, 16);
// add number to array
Serial.println(bigNumber);
}while((next_index!=-1)&&(next_index<iend));
}
void loop() {
}
You can send command without any libraries to arduino. in this example "message" ( protocol) is "2 chars + number + number" -> "GO 123 -512"
void setup() {
Serial.begin(9600);
}
void loop() {
// check if something on Serial
if(Serial.available()) {
// define variables
long number1, number2;
char cmd[2];
memset(cmd, 0, 2);
// read data from Serial
String s = Serial.readStringUntil('\n');
char buff[64];
memset(buff, 0, 64);
// convert string to char array
s.toCharArray(buff, 64);
// parse cmd to variables
sscanf(buff, "%2c %ld %ld",cmd, &number1, &number2);
char pr[128];
memset(pr, 0, 128);
// print template to buffer
sprintf(pr, "got 2 numbers from serial: %ld and %ld and command %s", number1, number2, cmd);
// print buffer back to Serial
Serial.println(pr);
}
}
Just copy following lines to begin of tinkercad code
#define LC_INIT(lc)
struct pt { unsigned short lc; };
#define PT_THREAD(name_args) char name_args
#define PT_BEGIN(pt) switch(pt->lc) { case 0:
#define PT_WAIT_UNTIL(pt, c) pt->lc = __LINE__; case __LINE__: \
if(!(c)) return 0
#define PT_END(pt) } pt->lc = 0; return 2
#define PT_INIT(pt) LC_INIT((pt)->lc)
Simple program with 2 different delays
#define LC_INIT(lc)
struct pt { unsigned short lc; };
#define PT_THREAD(name_args) char name_args
#define PT_BEGIN(pt) switch(pt->lc) { case 0:
#define PT_WAIT_UNTIL(pt, c) pt->lc = __LINE__; case __LINE__: \
if(!(c)) return 0
#define PT_END(pt) } pt->lc = 0; return 2
#define PT_INIT(pt) LC_INIT((pt)->lc)
struct pt pt1;
struct pt pt2;
void setup() {
Serial.begin(9600);
while(!Serial);
PT_INIT(&pt1);
PT_INIT(&pt2);
}
void loop() {
test(&pt1);
test2(&pt2);
}
unsigned long timeNow = 0;
PT_THREAD(test(struct pt *pt)) {
PT_BEGIN(pt);
timeNow = millis();
PT_WAIT_UNTIL(pt, millis() - timeNow > 5000);
Serial.println("print test1");
PT_END(pt);
}
unsigned long timeNow2 = 0;
PT_THREAD(test2(struct pt *pt)) {
PT_BEGIN(pt);
timeNow2 = millis();
PT_WAIT_UNTIL(pt, millis() - timeNow2 > 1000);
Serial.println("print test2");
PT_END(pt);
}
Thats it! Now you have pretty syntax instead of arduino millis() trick to delay tasks.
You can read more about protothreads http://dunkels.com/adam/pt/expansion.html