Golang and Arduino

Small arduino and golang programs

arduino read serial command and parse to variables

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

Golang sync cond example

golang sync cond working example


package main

import (
    "sync"
    "time"
)

var mu = sync.Mutex{}
var sc = sync.NewCond(&mu)

var setME string

func main() {
    go func() {
        for {

        }
    }()

    // start 10 gourintines

    for i := 0; i < 10; i++ {
        go func(i int) {
            println("go routine started")
            sc.L.Lock()
            sc.Wait()
            println(setME, "release", i)
            sc.L.Unlock()

        }(i)
    }
    time.Sleep(1 * time.Second)

    // set variable and
    // signal sync.cond to release 3 random locks
    // from waiting go routines

    for i := 0; i < 3; i++ {
        sc.L.Lock()
        setME = "test signal"
        sc.Signal()
        sc.L.Unlock()
    }
    time.Sleep(2 * time.Second)

    // release all waiting go routines to use global variable
    sc.L.Lock()
    setME = "test broadcast"
    sc.Broadcast()
    sc.L.Unlock()

    time.Sleep(3 * time.Second)
}

Protothreads on tinkercad

using arduino protothreads in tinkercad

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