Golang and Arduino

Small arduino and golang programs

arduino state machine with millis instead of delay

#include <Arduino.h>

enum class State :uint8_t {
  noop,
  wait,
  state1,
  state2,
  state3
};

State nextState;
State state;

uint32_t prevTime = millis();
uint32_t currentTime = millis();
uint32_t waitDelay;

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

void nextStateAfter(State ss, uint32_t d) {
  waitDelay = d;
  nextState = ss;
  state = State::wait;
  prevTime = currentTime;
}

void loop() {
  currentTime = millis();

  switch (state) {
    case State::noop:
      //maybe wait for input? (for now just send anything to serial);
      if (Serial.available() > 0) {
        Serial.readString();
        state = State::state1;
      }
      break;
    case State::wait:
      if (currentTime - prevTime > waitDelay) {
        state = nextState;
        prevTime = currentTime;
      }
      break;
    case State::state1:
      nextStateAfter(State::state2, 1000);
      Serial.println("state1");
      break;

    case State::state2:
      nextStateAfter(State::state3, 2000);
      Serial.println("state2");
      break;

    case State::state3:
      nextStateAfter(State::state1, 3000);
      Serial.println("state3");
      break;

  }
}

arduino blink without delay when button is pressed


// led pin 
const int ledPin1 = 13;
// button pin const int buttonPin1 = 2;
// blinking delay const int interval1 = 500; bool ledState1; bool canBlink1; unsigned long previousMillis1; void setup() { pinMode(ledPin1, OUTPUT); // set led pin to output pinMode(2, INPUT_PULLUP); // button pin set to INPUT with internal PULLUP(default state will be HIGH) } void loop() { unsigned long currentMillis = millis(); bool buttonState1 = digitalRead(buttonPin1); if (buttonState1 == LOW) { while (digitalRead(buttonPin1) == LOW); if (digitalRead(buttonPin1) == HIGH) { canBlink1 = !canBlink1; digitalWrite(ledPin1, LOW); } } if (currentMillis - previousMillis1 >= interval1 && canBlink1) { previousMillis1 = currentMillis; ledState1 = !ledState1; digitalWrite(ledPin1, ledState1); } }

arduino parse hex colors to numbers


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() {

}

ansi C unions on arduino

After some time of googling, i found interesting solution, how to get and set pins as bits in arduino


union myunion {
    struct {
        unsigned int b7: 1;
        unsigned int b6: 1;
        unsigned int b5: 1;
        unsigned int b4: 1;
        unsigned int b3: 1;
        unsigned int b2: 1;
        unsigned int b1: 1;
        unsigned int b0: 1;
    };
    unsigned int num;
} mu;

with this union with struct, we can read pins to 1 big number invidual bits and display it on for example - led's in binary.


mu.b0 = digitalRead(2);
mu.b1 = digitalRead(3);
mu.b2 = digitalRead(4);
mu.b3 = digitalRead(5);
mu.b4 = digitalRead(6);
mu.b5 = digitalRead(7);
mu.b6 = digitalRead(8);
mu.b7 = digitalRead(9);

and vuola, now we can get number with "mu.num" depending on HIGH pins 


Serial.println(mu.num);

and in reverse, we can set "mu.num = 127" and write individual bits to pins.


digitalWrite(mu.b0);
digitalWrite(mu.b1);
digitalWrite(mu.b2);
digitalWrite(mu.b3);
digitalWrite(mu.b4);
digitalWrite(mu.b5);
digitalWrite(mu.b6);
digitalWrite(mu.b7);

whole program:


// parallel to serial
// serial to parallel
union mu1 {
    struct {
        unsigned int b7: 1;
        unsigned int b6: 1;
        unsigned int b5: 1;
        unsigned int b4: 1;
        unsigned int b3: 1;
        unsigned int b2: 1;
        unsigned int b1: 1;
        unsigned int b0: 1;
    };
    unsigned int num;
} mu;

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

void loop() {
  mu.b0 = digitalRead(2); // switch 1
  mu.b1 = digitalRead(3); // switch 2
  mu.b2 = digitalRead(4); // switch 3
  mu.b3 = digitalRead(5); // switch 4
  mu.b4 = digitalRead(6); // switch 5
  mu.b5 = digitalRead(7); // switch 6
  mu.b6 = digitalRead(8); // switch 7
  mu.b7 = digitalRead(9); // switch 8

  Serial.println(mu.num);
  delay(5000);
}

thats it. union acts as "shift in" and "shift out" register, if you set mu.num than you can read individual bits(pins) if you set pins you can read mu.num and it works then like shift in register.

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

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