Controlling Solenoids with Random Timings

Hi guys,

So I have a set of eight solenoids that I would like to control simultaneously at random speeds that are also constantly changing within a range of numbers. The code I have so far sets the solenoids to their high and low state at a random time, but this time is not constantly changing as I would like. Here is the code (which is based on the Several Things At Once code demonstration):

//========================================
//Interval: is the overall speed of the solenoids. Lower is faster. (Try between 1000 and 10000 first. Do not run below 100)
//Duration: is how long the plunger stays in for (Always set below 500.  Setting below 150 may not trigger solenoid.)

// -------- CONSTANTS (CHANGE THESE VALUES) ---------------
int random_interval_one[2] = {100, 10000};
int random_duration_one[2] = {150, 500};

int random_interval_two[2] = {100, 10000};
int random_duration_two[2] = {150, 500};

int random_interval_three[2] = {100, 10000};
int random_duration_three[2] = {150, 500};


int random_interval_four[2] = {100, 10000};
int random_duration_four[2] = {150, 500};

int random_interval_five[2] = {100, 10000};
int random_duration_five[2] = {150, 500};

int random_interval_six[2] = {100, 10000};
int random_duration_six[2] = {150, 500};

int random_interval_seven[2] = {100, 10000};
int random_duration_seven[2] = {150, 500};

int random_interval_eight[2] = {100, 10000};
int random_duration_eight[2] = {150, 500};


//------------ VARIABLES (DO NOT change these values) ---------------------

unsigned long previousMillis_one = 0;
unsigned long previousMillis_two = 0;
unsigned long previousMillis_three = 0;
unsigned long previousMillis_four = 0;
unsigned long previousMillis_five = 0;
unsigned long previousMillis_six = 0;
unsigned long previousMillis_seven = 0;
unsigned long previousMillis_eight = 0;

byte state_one = LOW;
byte state_two = LOW;
byte state_three = LOW;
byte state_four = LOW;
byte state_five = LOW;
byte state_six = LOW;
byte state_seven = LOW;
byte state_eight = LOW;

unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()

//========================================

void setup() {

  for (int i = 0; i < 9; i++) {
    pinMode(i, OUTPUT);
  }

}

//========================================

void loop() {
  // Only calls the functions below, does no action independently
  // Comment these lines to turn off device
  // by hitting the command key and the front slash key at the same time (hit again to un-comment) and upload

  currentMillis = millis();

              solenoid_random_one();
              solenoid_random_two();
              solenoid_random_three();
              solenoid_random_four();
              solenoid_random_five();
              solenoid_random_six();
              solenoid_random_seven();
              solenoid_random_eight();

              solenoids_on();

}

//========================================

void solenoid_random_one() {
  int i = random(random_interval_one[0], random_interval_one[1]);
  int d = random(random_duration_one[0] , random_duration_one[1]);

  if (state_one == LOW) {
  if (currentMillis - previousMillis_one >= i) {
      state_one = HIGH;
      previousMillis_one += i;
    }
  }
  else {
    if (currentMillis - previousMillis_one >= d) {
      state_one = LOW;
      previousMillis_one += d;
    }
  }
}

//========================================

void solenoid_random_two() {
  int i2 = random(random_interval_two[0], random_interval_two[1]);
  int d2 = random(random_duration_two[0], random_duration_two[1]);

  if (state_two == LOW) {
    if (currentMillis - previousMillis_two >= i2) {
      state_two = HIGH;
      previousMillis_two += i2;
    }
  }
  else {
    if (currentMillis - previousMillis_two >= d2) {
      state_two = LOW;
      previousMillis_two += d2;
    }
  }
}

//========================================

void solenoid_random_three() {

  int i3 = random(random_interval_three[0], random_interval_three[1]);
  int d3 = random(random_duration_three[0], random_duration_three[1]);

  if (state_three == LOW) {
    if (currentMillis - previousMillis_three >= i3) {
      state_three = HIGH;
      previousMillis_three += i3;
    }
  }
  else {
    if (currentMillis - previousMillis_three >= d3) {
      state_three = LOW;
      previousMillis_three += d3;
    }
  }
}

//========================================

void solenoid_random_four() {

  int i4 = random(random_interval_four[0], random_interval_four[1]);
  int d4 = random(random_duration_four[0], random_duration_four[1]);

  if (state_four == LOW) {
    if (currentMillis - previousMillis_four >= i4) {
      state_four = HIGH;
      previousMillis_four += i4;
    }
  }
  else {
    if (currentMillis - previousMillis_four >= d4) {
      state_four = LOW;
      previousMillis_four += d4;
    }
  }
}

//========================================

void solenoid_random_five() {
  int i5 = random(random_interval_five[0], random_interval_five[1]);
  int d5 = random(random_duration_five[0], random_duration_five[1]);

  if (state_five == LOW) {
    if (currentMillis - previousMillis_five >= i5) {
      state_five = HIGH;
      previousMillis_five += i5;
    }
  }
  else {
    if (currentMillis - previousMillis_five >= d5) {
      state_five = LOW;
      previousMillis_five += d5;
    }
  }
}

//========================================

void solenoid_random_six() {
  int i6 = random(random_interval_six[0], random_interval_six[1]);
  int d6 = random(random_duration_six[0], random_duration_six[1]);

  if (state_six == LOW) {
    if (currentMillis - previousMillis_six >= i6) {
      state_six = HIGH;
      previousMillis_six += i6;
    }
  }
  else {
    if (currentMillis - previousMillis_six >= d6) {
      state_six = LOW;
      previousMillis_six += d6;
    }
  }
}

//========================================

void solenoid_random_seven() {

  int i7 = random(random_interval_seven[0], random_interval_seven[1]);
  int d7 = random(random_duration_seven[0] , random_duration_seven[1]);

  if (state_seven == LOW) {
    if (currentMillis - previousMillis_seven >= i7) {
      state_seven = HIGH;
      previousMillis_seven += i7;
    }
  }
  else {
    if (currentMillis - previousMillis_seven >= d7) {
      state_seven = LOW;
      previousMillis_seven += d7;
    }
  }
}

//========================================

void solenoid_random_eight() {

  int i8 = random(random_interval_eight[0], random_interval_eight[1]);
  int d8 = random(random_duration_eight[0] , random_duration_eight[1]);

  if (state_eight == LOW) {
    if (currentMillis - previousMillis_eight >= i8) {
      state_eight = HIGH;
      previousMillis_eight += i8;
    }
  }
  else {
    if (currentMillis - previousMillis_eight >= d8) {
      state_eight = LOW;
      previousMillis_eight += d8;
    }
  }
}

//========================================

void solenoids_on() {
  digitalWrite(1, state_one);
  digitalWrite(2, state_two);
  digitalWrite(3, state_three);
  digitalWrite(4, state_four);
  digitalWrite(5, state_five);
  digitalWrite(6, state_six);
  digitalWrite(7, state_seven);
  digitalWrite(8, state_eight);

}

//========================================  END

Any help would be great, thanks~!

The first thing that I notice is the large amount of duplicated code. It looks like you could use a struct to hold data for each solenoid and then create an array of that struct to allow you to iterate through it to read, save or compare data. This would eliminate the duplicated code.

A small example of using an array of structs to hold data

typedef struct
{
  const byte ledPin;
  unsigned long startTime;
  unsigned long period;
}
data;

data ledData[4] =
{
  {10, 0, 0},
  {11, 0, 0},
  {12, 0, 0},
  {13, 0, 0},
};


const byte NUMBER_OF_LEDS = sizeof(ledData) / sizeof(ledData[0]);

void setup()
{
  Serial.begin(115200);
  Serial.println(NUMBER_OF_LEDS);
  for (int led = 0; led < NUMBER_OF_LEDS; led++)
  {
    pinMode(ledData[led].ledPin, OUTPUT);
  }
}

void loop()
{
  unsigned long currentTime = millis();
  for (int led = 0; led < NUMBER_OF_LEDS; led++)
  {
    if (currentTime - ledData[led].startTime >= ledData[led].period)
    {
      digitalWrite(ledData[led].ledPin, !digitalRead(ledData[led].ledPin));
      ledData[led].startTime = currentTime;
      ledData[led].period = random(100, 2000);
    }
  }
}

Can I suggest that you tidy up your existing code first before adding further complexity to it.

I have the code organized this way because this is the way it is best understood by the person I'm working with. This system is not for me, but for someone I'm working with who has very little experience with programming and as such prefers it written and organized this way so that they can understand the repetition and alter what they need.