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 new way


typedef void (*myFunction)() ;

class RepeatEvery {
  private:
    unsigned long currentMillis = millis();
    unsigned long prevMillis = currentMillis;
    bool prevCanRun = false;
    unsigned long lwait;
    myFunction lf;
  public:
    RepeatEvery(myFunction f, unsigned long wait) {
      lwait = wait;
      lf = f;
    }

    void handle() {
      bool r = true;
      handle(r);
    }

    void handle(bool& canRun, bool reset = true) {
      currentMillis = millis();
      if (prevCanRun != canRun) {
        prevCanRun = canRun;
        if (reset == true)
          prevMillis = currentMillis;
        else
          prevMillis = currentMillis - lwait - 1;
      }
      if (currentMillis - prevMillis >= lwait && prevCanRun == true ) {
        prevMillis = currentMillis;
        lf();
      }
    }
};

bool runOnce = true;
bool canRun = true;

// function which depends on external variable
// blink LED_BUILTIN sveral times
RepeatEvery fn([] {
  Serial.println("Blink Blink");
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}, 1000);

// function which turns on or of function named "fn"
// disables blinking after 5s and sets LED_BUILDIN to LOW
RepeatEvery repeatAlways([] {
  runOnce = false; // stop repeatAlways
  canRun = false; // stop fn
  digitalWrite(LED_BUILTIN, LOW);
  Serial.println("disable blinking");
}, 5000);

void setup() {

  Serial.begin(9600);
  while (!Serial);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  repeatAlways.handle(runOnce);
  fn.handle(canRun, true);
}

arduino millis() trick with state machine

This sketch waits until button is pressed ( pin 2 connected with ground ) and if button was pressed -  blinks LED 3 times.

#include <Arduino.h>

const int LED_PIN = LED_BUILTIN;
const int BUTTON_PIN = 2;

const long blingTimes = 3;

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

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

enum {
  turn_on,
  turn_off,
  wait,
};

byte state = wait;
unsigned long prevMillis1 = 0;
const unsigned long delay1 = 1000;
const unsigned long delay2 = 500;
long iteration = 0;

void loop() {

  unsigned long currentTime = millis();

  if(state == wait) {
    if(digitalRead(BUTTON_PIN) == LOW) {
      state = turn_on;
      iteration=0;
    }
  }

  if (state == turn_on) {
    if (millis() - prevMillis1 >= delay1) {
      prevMillis1 = currentTime;
      digitalWrite(LED_PIN, HIGH);
      state = turn_off;
    }
  }
  if (state == turn_off) {
    if (millis() - prevMillis1 >= delay2) {
      prevMillis1 = currentTime;
      digitalWrite(LED_PIN, LOW);
      state = turn_on;
      iteration++;
      if (iteration > blinkTimes) {
        state = wait;
      }
    }
  }
}

how to control several servo motors with arduino

The class


#include <Arduino.h>
#include <Servo.h>

class AsyncServo
{
  Servo servo;   
  int pos;       
  int increment; 
  int incrementBy = 1;
  int updateInterval = 10;       
  unsigned long lastUpdate; 
  bool done = false;

public:
  AsyncServo(int interval =10, int i = 1)
  {
    updateInterval = interval;
    increment = i;
    incrementBy = i;
  }

  // Attach pin to servo
  void Attach(int pin)
  {
    servo.attach(pin);
  }

  // Detach from servo
  void Detach()
  {
    servo.detach();
  }

  // Rotate servo to "Home" ( pos = 0);
  void Home()
  {
    if (pos >= 180)
    {
      done = false;
      increment = -incrementBy;
    }
  }

  // Rotate servo to "End" ( pos = 180 );
  void End()
  {
    if (pos <= 0)
    {
      done = false;
      increment = incrementBy;
    }
  }

  // just set servo to some position between 0 and 180;
  void setPosition(uint8_t p) {
    done = true;
    // pos = p; ????
    servo.write(pos);
  }

  // check if servo done its movement
  bool Done()
  {
    return done;
  }

  // check if servo is at home position: pos = 0;
  bool AtHome()
  {
    return pos <= 0;
  }

  // asynchroniuosly rotate motor
  void Run()
  {
    if (done)
      return;

    if ((millis() - lastUpdate) > updateInterval) 
    {
      lastUpdate = millis();
      pos += increment;
      servo.write(pos);
      Serial.println(pos);
      if ((pos >= 180) || (pos <= 0))
      {
        done = true;
        return;
      }
    }
  }
};

class usage on arduino UNO / mega ( for others - check for PWM pins )



AsyncServo s1(100, 10); // slow movement
AsyncServo s2(10, 10);  // fast movement

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  s.Attach(9); 
s.Attach(10);

  s1.Home();
s2.Home();
}

void loop()
{
  s1.Run(); // servo 1 step
 s2.Run(); // servo 2 step 
  if (s1.Done()) // if servo motor stopped
  {
    if (s1.AtHome()) //check if its position is Home ( 0 ) 
    {
      s1.End(); // tell servo motor to rotate to max ( 180 )
    }
    else
    {
      s1.Home(); // tell servo motor to rate back to home ( 0 );
    }
  }
  if (s2.Done()) // if servo motor stopped
  {
    if (s2.AtHome()) //check if its position is Home ( 0 ) 
    {
      s2.End(); // tell servo motor to rotate to max ( 180 )
    }
    else
    {
      s1.Home(); // tell servo motor to rate back to home ( 0 );
    }
  }
} 

arduino updated eeprom: writeanything.h

#include <EEPROM.h>   // We need this library
#include <Arduino.h>  // for type definitions

//We create two fucntions for writing and reading data from the EEPROM
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
    const byte* p = (const byte*)(const void*)&value;
    unsigned int i;
    for (i = 0; i < sizeof(value); i++)
          EEPROM.write(ee++, *p++);
    EEPROM.commit(); // comment out on some boards / older versions.
    return i;
}

template <class T> int EEPROM_readAnything(int ee, T& value)
{
    byte* p = (byte*)(void*)&value;
    unsigned int i;
    for (i = 0; i < sizeof(value); i++)
          *p++ = EEPROM.read(ee++);
    return i;
}

Usage


struct {
  char ssid[20];
  char passwd[20];
} wifiConfig;

void setup() {
  // write struct to eeprom
  EEPROM_writeAnything(0, wifiConfig);
  // read from eeprom to struct
  EEPROM_readAnything(0, wifiConfig);
}

Happy using ;)

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