Go Down

Topic: Doing multiple things at once with structs (Read 539 times) previous topic - next topic

tomascus

Apr 06, 2019, 03:37 am Last Edit: Apr 06, 2019, 04:09 am by tomascus
Hi guys, apologies if this is the wrong place to post.

I just wanted to demonstrate a program which performs actions on a button, two LEDs and three servos without any blocking.

I know that there are already many tutorials out there but I don't think many have covered the use of structs as these come in handy for those not comfortable with using classes and also eliminates the need to have extra pointless variables specific to each LED etc.

What this code does:
- Toggle LEDs at different ON and OFF times
- Turn the servos between a minimum angle and maximum angle at different rates
- Poll and debounce a button

Please feel free to ask questions or add any critique, thanks.

Code: [Select]

#include <Servo.h>

#define NO_OF_BUTTONS 1
#define NO_OF_LEDS 2
#define NO_OF_SERVOS 3

#define DEBOUNCE_DELAY 50

const int servo0_pin = 3;
const int servo1_pin = 5;
const int servo2_pin = 6;

Servo myServo[NO_OF_SERVOS];

struct servo {
  int servo_no; /* corresponds to myServo array value */
  int min_angle;
  int max_angle;
  int move_rate; /* delay in ms in which to inc/dec position */
  int increment;
  int cur_pos;
  unsigned long prev_millis;
};

/* create an array of servo structs and set parameters */
struct servo servos[NO_OF_SERVOS] = {
/* servo_no, min_angle, max_angle, move_rate, increment */
    {0, 0, 180, 30, 3},
    {1, 0, 135, 40, 1},
    {2, 0, 45, 55, 2}
};

struct button {
  int pin;
  int reading;
  int last_state;
  int button_state;
  unsigned long last_debounce_time;
};

struct button buttons[NO_OF_BUTTONS] = { 11 }; /* Pin number */

struct led {
  int pin;
  int on_time;
  int off_time;
  int state;
  unsigned long prev_millis_low;
  unsigned long prev_millis_high;
};

/* create an array of led structs and set parameters */
struct led leds[NO_OF_LEDS] = {
/* pin, on_time, off_time */
  {13, 250, 250},
  {12, 500, 1000}
};

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

  pinMode(leds[0].pin, OUTPUT);
  pinMode(leds[1].pin, OUTPUT);

  myServo[0].attach(servo0_pin);
  myServo[1].attach(servo1_pin);
  myServo[2].attach(servo2_pin);
}

/*
 * update_led(struct led *pled) function.
 * Flash LEDs at different rates with configured on times and
 * off times.
 */
void update_led(struct led *pled)
{
  switch (pled->state) {
  case LOW:
    if (millis() - pled->prev_millis_low >= pled->off_time) {
      digitalWrite(pled->pin, HIGH);
      pled->state = HIGH;
      pled->prev_millis_high = millis();
    }
    break;
  case HIGH:
    if (millis() - pled->prev_millis_high >= pled->on_time) {
      digitalWrite(pled->pin, LOW);
      pled->state = LOW;
      pled->prev_millis_low = millis();
    }
    break;
  }
}

/*
 * update_servo(struct servo *pservo) function.
 * Rotate servos at different rates and differing max angles
 * as configured.
 */
void update_servo(struct servo *pservo)
{
  if (millis() - pservo->prev_millis >= pservo->move_rate) {
    pservo->prev_millis = millis();
    (pservo->cur_pos) += pservo->increment;
    myServo[pservo->servo_no].write(pservo->cur_pos);
    if (pservo->cur_pos >= pservo->max_angle ||
        pservo->cur_pos <= pservo->min_angle)
      pservo->increment = -(pservo->increment);
  }
}

/*
 * poll_button(struct button *pbutton) function.
 * Simple button debouncing and reading while being polled in the
 *  loop() func.
 * Code copied from Arduino website.
 */
void poll_button(struct button *pbutton)
{
  pbutton->reading = digitalRead(pbutton->pin);

  if (pbutton->reading != pbutton->last_state)
    pbutton->last_debounce_time = millis();

  if ((millis() - pbutton->last_debounce_time) > DEBOUNCE_DELAY) {
    if (pbutton->reading != pbutton->button_state) {
      pbutton->button_state = pbutton->reading;
      if (pbutton->button_state == HIGH)
        Serial.println("Button pressed");
    }
  }

  pbutton->last_state = pbutton->reading;
}

/* Main loop which updates all items */
void loop()
{
  for (int i = 0; i < NO_OF_LEDS; i++)
    update_led(&leds[i]);

  for (int i = 0; i < NO_OF_BUTTONS; i++)
    poll_button(&buttons[i]); 

  for (int i = 0; i < NO_OF_SERVOS; i++)
    update_servo(&servos[i]);
}


EDIT: changed title

Go Up