Go Down

Topic: Doing multiple things at once with structs (Read 849 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

oswe

Good writing. One question . if u define a new struct u dont need to provide all arguments? I mean in this part u only assign 3 arguments being that it has 5.

struct led leds[NO_OF_LEDS] = {
/* pin, on_time, off_time */

lastchancename

Nice example - maybe a bit over the heads of some early learners - but well worthwhile.
Just curious - Why didn't you put the pins inside the servo struct[] array ?
Experienced responders have a nose for laziness, (they were beginners once)... Sure, there are trolls, chest-beaters, and pretenders - but the help you'll get here is about as good as it gets - if you try to help youself!.

GolamMostafa

Code: [Select]
[quote author=tomascus link=msg=4126025 date=1554514630]
I just wanted to demonstrate a program which performs actions on a button, two LEDs and three servos without any blocking.

/* 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]);
}


You have said 'without any blocking'--codes of the loop() function indicate that you are unable to check the states of the buttons until the 'update_led()' business is over. Is it not some kind of 'blocking'?

AWOL

You have said 'without any blocking'--codes of the loop() function indicate that you are unable to check the states of the buttons until the 'update_led()' business is over. Is it not some kind of 'blocking'?

Only for very large numbers of LEDs.
Which is not the case.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Go Up