Choose unique random number from array

Background: The code below is being used to control 2 motors, 2 LED's, and in conjunction with Gobetwino, 2 programs on the computer. Alarms are setup 8 times a day to randomly run 1 of 3 functions at a given alarm time.

Problem: I want to ensure each randomly called function runs exactly 4 times per day. At the moment there is no guarantee that a function will A.) run at least once everyday and B.) not be randomly chosen to run all 12 times a day.

I searched the forum and came across one proposed method to get this done using an array, which would contain 12 elements, in my case:
A for loop to process each element in the array.
A while loop inside it to process the current element repeatedly until a unique random number had been found
A for loop inside that to compare the currently proposed random number against all the preceding elements in the array

Could somebody please explain to me how to "process" and "compare" the elements or suggest a different way to get this done? Any help would be greatly appreciated. Thank you!

#include <Time.h>
#include <TimeAlarms.h>

int randNumber;

int dirpin = 11; //small motor
int steppin = 12;

int dirpinb = 8; //big motor
int steppinb = 9;

int redled = 4; //red LED
int greenled = 5; //green LED

void setup()
{
  Serial.begin(9600); //initialize communication with chip
  setTime(14,44,30,2,24,14); //set time
  Alarm.alarmRepeat(14,45,0, AlarmF); //set first alarm time
  Alarm.alarmRepeat(14,47,0, AlarmF); //set second alarm time
  Alarm.alarmRepeat(14,49,0, AlarmF); //set third alarm time
  Alarm.alarmRepeat(14,51,0, AlarmF); //set fourth alarm time
  Alarm.alarmRepeat(14,53,0, AlarmF); //set fifth alarm time
  Alarm.alarmRepeat(14,55,0, AlarmF); //set sixth alarm time
  Alarm.alarmRepeat(14,57,0, AlarmF); //set seventh alarm time
  Alarm.alarmRepeat(14,59,0, AlarmF); //set eighth alarm time
  
  pinMode(redled, OUTPUT);
  pinMode(greenled, OUTPUT);  
  pinMode(dirpin, OUTPUT);
  pinMode(steppin, OUTPUT);
  pinMode(dirpinb, OUTPUT);
  pinMode(steppinb, OUTPUT);
  randomSeed(analogRead(0)); //generate different random number
}

void loop()
{
  Alarm.delay(0);
}

void AlarmF()
{
  int randNumbers;
  
  randNumbers = random(1, 13); //generate a random number between 1 and 12
  
  if (randNumbers == 1 || randNumbers == 2 || randNumbers == 3 || randNumbers == 4)
  {
    void UpwardsFM();
  }
  else if (randNumbers == 5 || randNumbers == 6 || randNumbers == 7 || randNumbers == 8)
  {
    void DownwardsFM();
  }
  else if (randNumbers == 9 || randNumbers == 10 || randNumbers == 11 || randNumbers == 12)
  {
    void Sham();
  }
}

void UpwardsFM()
{  
  int i;
  
  Serial.print("#S|OPENVID|["); //gobetwino opens video capture software
  Serial.println("]#");
  delay(15000); //wait 15 seconds
  
  Serial.println("#S|SENDK|[0&{F5}]#"); //gobetwino hits F5 to start recording
  delay(10000); //wait 10 seconds
  
    digitalWrite(redled, HIGH);  //turn on red LED
    digitalWrite(greenled, HIGH); //turn on green LED
    
    Serial.print("#S|AUDIO1|["); //gobetwino opens audio1
    Serial.println("]#");
    
    delay(5000); //wait 5 seconds
    
    digitalWrite(dirpinb, HIGH); //set the big motor to rotate clockwise
    digitalWrite(dirpin, LOW); //set the small motor to rotate clockwise
    
    for (i = 0; i<50; i++) //rotate the big motor 50 steps
    {
     digitalWrite(steppinb, LOW);
     digitalWrite(steppinb, HIGH);
     delayMicroseconds(8000);
    }
    
    delay(1000); //wait 1 second
  
    for (i = 0; i<200; i++) //feed the fish AKA rotate the small motor 200 steps
    {
    digitalWrite(steppin, LOW);
    digitalWrite(steppin, HIGH);
    delayMicroseconds(8000);
    }
      
  delay(1000); //wait 2 seconds
  
  digitalWrite(dirpinb, LOW); //change the direction of the big motor to counterclockwise
  
  for (i=0; i<50; i++) //return the big motor to its starting position
  {
    digitalWrite(steppinb, LOW);
    digitalWrite(steppinb, HIGH);
    delayMicroseconds(8000);
  }
  
    Serial.println("#S|SENDK|[1&^q]#"); //gobetwino quits VLC
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);  
  
  delay(10000); //wait 10 seconds
  Serial.println("#S|SENDK|[0&%{F4}~]#"); //gobetwino hits ALT+F4 to quit video capture software
}

void DownwardsFM()
{
  int i;
  
  Serial.print("#S|OPENVID|["); //gobetwino opens video capture software
  Serial.println("]#");
  delay(15000); //wait 15 seconds
  
  Serial.println("#S|SENDK|[0&{F5}]#"); //gobetwino hits F5 to start recording
  delay(10000); //wait 10 seconds
    
    digitalWrite(redled, HIGH);  //turn on red LED
    digitalWrite(greenled, HIGH); //turn on green LED
    
    Serial.print("#S|AUDIO2|["); //gobetwino opens audio2
    Serial.println("]#");
    
    delay(5000); //wait 5 seconds
    
    digitalWrite(dirpinb, LOW); //set the big motor to rotate counterclockwise
    digitalWrite(dirpin, LOW); //set the small motor to rotate clockwise
    
    for (i = 0; i<50; i++) //rotate the big motor 50 steps
    {
     digitalWrite(steppinb, LOW);
     digitalWrite(steppinb, HIGH);
     delayMicroseconds(8000);
    }
    
    delay(1000); //wait 1 second
  
    for (i = 0; i<200; i++) //feed the fish AKA rotate the small motor 200 steps
    {
    digitalWrite(steppin, LOW);
    digitalWrite(steppin, HIGH);
    delayMicroseconds(8000);
    }
      
  delay(1000); //wait 1 seconds
  
  digitalWrite(dirpinb, HIGH); //change the direction of the big motor to counterclockwise
  
  for (i=0; i<50; i++) //return the big motor to its starting position
  {
    digitalWrite(steppinb, LOW);
    digitalWrite(steppinb, HIGH);
    delayMicroseconds(8000);
  }
  
    Serial.println("#S|SENDK|[1&^q]#"); //gobetwino quits VLC
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);  
  
  delay(10000); //wait 10 seconds
  Serial.println("#S|SENDK|[0&%{F4}~]#"); //gobetwino hits ALT+F4 to quit video capture software
} 

void Sham()
{
  int i;
  
  randNumber = random(1, 3); //generate a random number: 1 or 2
  
  if (randNumber == 1)
  {
    digitalWrite(dirpinb, HIGH); //set the big motor to rotate clockwise
    digitalWrite(dirpin, LOW); //set the small motor to rotate clockwise
    
    Serial.print("#S|OPENVID|["); //gobetwino opens video capture software
    Serial.println("]#");
    delay(15000); //wait 15 seconds
  
    Serial.println("#S|SENDK|[0&{F5}]#"); //gobetwino hits F5 to start recording
    delay(10000); //wait 10 seconds
    
    digitalWrite(redled, HIGH);  //turn on red LED
    digitalWrite(greenled, HIGH); //turn on green LED
    
    Serial.print("#S|AUDIO3|["); //gobetwino opens audio3
    Serial.println("]#");
    
    delay(5000);  //wait 5 seconds
    
    for (i = 0; i<50; i++) //rotate the big motor 50 steps
    {
     digitalWrite(steppinb, LOW);
     digitalWrite(steppinb, HIGH);
     delayMicroseconds(8000);
    }
    
    delay(10000); //wait 10 seconds
    
    Serial.println("#S|SENDK|[1&^q]#"); //gobetwino quits VLC
    digitalWrite(redled, LOW);  //turn off red LED
    digitalWrite(greenled, LOW); //turn off green LED
    
    digitalWrite(dirpinb, LOW); //set the big motor to rotate counterclockwise
    
    for (i = 0; i<50; i++) //rotate the big motor 50 steps to return to rest position
    {
     digitalWrite(steppinb, LOW);
     digitalWrite(steppinb, HIGH);
     delayMicroseconds(8000);
    }    
    
    delay(10000); //wait 10 seconds
    Serial.println("#S|SENDK|[0&%{F4}~]#"); //gobetwino hits ALT+F4 to quit video capture software    
  }
  else if (randNumber == 2)
  {
    digitalWrite(dirpinb, LOW); //set the big motor to rotate clockwise
    digitalWrite(dirpin, LOW); //set the small motor to rotate clockwise
    
    Serial.print("#S|OPENVID|["); //gobetwino opens video capture software
    Serial.println("]#");
    delay(15000); //wait 15 seconds
  
    Serial.println("#S|SENDK|[0&{F5}]#"); //gobetwino hits F5 to start recording
    delay(15000); //wait 15 seconds
    
    digitalWrite(redled, HIGH);  //turn on red LED
    digitalWrite(greenled, HIGH); //turn on green LED
    
    Serial.print("#S|AUDIO3|["); //gobetwino opens audio3
    Serial.println("]#");
    
    delay(5000); //wait 5 seconds
    
    for (i = 0; i<50; i++) //rotate the big motor 50 steps
    {
     digitalWrite(steppinb, LOW);
     digitalWrite(steppinb, HIGH);
     delayMicroseconds(8000);
    }
    
    delay(10000); //wait 10 seconds    
    
    Serial.println("#S|SENDK|[1&^q]#"); //gobetwino quits VLC
    digitalWrite(redled, LOW);  //turn off red LED
    digitalWrite(greenled, LOW); //turn off green LED
    
    digitalWrite(dirpinb, HIGH); //set the big motor to rotate counterclockwise
    
    for (i = 0; i<50; i++) //rotate the big motor 50 steps to return to rest position
    {
     digitalWrite(steppinb, LOW);
     digitalWrite(steppinb, HIGH);
     delayMicroseconds(8000);
    }    
    
    delay(10000); //wait 10 seconds
    Serial.println("#S|SENDK|[0&%{F4}~]#"); //gobetwino hits ALT+F4 to quit video capture software    
  }
}

This seems like an unusual and arbitrary set of requirements, and even mutually contradictory. If there are 8 alarms and only one function runs during each alarm, how can 3 functions each be run 4 times every day? You have 12 function calls to fit into 8 slots.

In any case, you might begin with something like this:
An alarm array contains 8 elements, initially containing zeros.
Each element will contain a number, 1, 2 or 3, pointing to a function that will be run at that alarm time.
At the beginning of each day, zero out the alarm array and then, using a random number generator, distribute four each of 1s, 2s and 3s into those elements until the array is full.

If you want to randomly choose one of 3 functions, and assure that each function gets called 4 times, you need to keep track of only 12 values. Populate an array of 12 elements, with the values 1, 2, and 3, where each occurs 4 times. The order does not matter.

Then, populate another array of 12 booleans, with all false. Randomly choose a value from 0 to 11. If the value in the boolean array at that location is false, set it to true and use the value in the other array (at the same position) to determine which function to run. Set the position in the boolean array to true when the function has been executed.

Use a while loop to keep getting random numbers until you get one where the bool array contains false at that index location. Break out of the while loop when the index points to a false location.

"random" and "4 times a day" are opposite to each other.

I don't understand what you describe, but perhaps it is the same of what I think.

Suppose you don't want the same sequence, but a random sequence and still with those limitations.
As soon as one of the functions has been choosen, the random has to select between the remaining options.
I prefer not to search for a valid option, but to directly choose an available option. That means that some sorting has to be done.

You have three options: 0, 1 and 2. Those are the functions. Do you know how to use pointers to functions ?
Set those pointers in an array : void (*fn[])(void) = { UpwardsFM, DownwardsFM, Sham };
You need to run them 4 times a day, so 4 times '0', 4 times '1' and 4 times '2'.
Let's fill an array with that: int selection[] = { 0,0,0,0, 1,1,1,1, 2,2,2,2 }
Use also a variable that keeps track of how many are still valid, it starts with 12.
Choose randomly a number from that array, and call the appropriate function.
To remove the selected item from the list, replace it with the last one, and reduce the number of valid items in the list.

While I was typing and thinking about this problem, two new replies are added, I think they have the same idea with a little variation. So the basic idea must be good if three of us have it.

If you want to randomly call one of three functions but ensure that each function gets called no more than four times per day, one way to do that is to maintain a counter for each function which records how many times it has been called today, and when you need to call a function keep picking one at random until you find one that has been called less than four times. It's not the most efficient or elegant solution but has the advantage of simplicity.

Correction: I should have created 4 functions, each to run 2 times a day. That would fill up 8 slots more easily than 12 functions would! Sorry about the confusion.

The relevant code would look something more like this:

void AlarmF()
{
  int randNumbers;
  
  randNumbers = random(1, 13); //generate a random number between 1 and 12
  
  if (randNumbers == 1 || randNumbers == 2 || randNumbers == 3)
  {
    void UpwardsFM();
  }
  else if (randNumbers == 4 || randNumbers == 5 || randNumbers == 6)
  {
    void DownwardsFM();
  }
  else if (randNumbers == 7 || randNumbers == 8 || randNumbers == 9)
  {
    void UpwardsSham();
  }
else if (randNumbers == 10 || randNumbers == 11 || randNumbers == 12)
  {
    void DownwardsSham();
  }
}

Thank you for the replies.

Caltoa, jremington and PaulS, I'm relatively new to programming and not familiar with using pointers. Since there is little information about pointers on the Reference page, could you please guide me on how to set them up?

PeterH, I tried searching for example sketches using counters but couldn't find any. Your solution sounds like something I can implement without the use of Pointers. Can you please point me to an example sketch that incorporates the use of a counter?

'unique' 'random' 'choose' and 'array' are all problematical concepts here.

Gtown:
Can you please point me to an example sketch that incorporates the use of a counter?

Here you go:

int counter = 0; // declare an integer variable named counter

...

counter++; // increment counter

...

if(counter < 2) // do stuff if the counter is less than two
{
   stuff
}

Thanks, PeterH!

I incorporated what you said into my code, but for some reason, the functions were called more than 2 times each when I tested the program today. Just for clarification, I now have 4 functions which I want to call randomly, exactly 2 times per day, using 8 alarms.

What am I doing wrong?

#include <Time.h>
#include <TimeAlarms.h>

int randNumbers;

int dirpin = 11; //small motor
int steppin = 12;

int dirpinb = 8; //big motor
int steppinb = 9;

int redled = 4; //red LED
int greenled = 5; //green LED

void setup()
{
  Serial.begin(9600); //initialize communication with chip
  setTime(14,44,30,2,24,14); //set time
  Alarm.alarmRepeat(14,45,0, AlarmF); //set first alarm time
  Alarm.alarmRepeat(14,47,0, AlarmF); //set second alarm time
  Alarm.alarmRepeat(14,49,0, AlarmF); //set third alarm time
  Alarm.alarmRepeat(14,51,0, AlarmF); //set fourth alarm time
  Alarm.alarmRepeat(14,53,0, AlarmF); //set fifth alarm time
  Alarm.alarmRepeat(14,55,0, AlarmF); //set sixth alarm time
  Alarm.alarmRepeat(14,57,0, AlarmF); //set seventh alarm time
  Alarm.alarmRepeat(14,59,0, AlarmF); //set eighth alarm time

  pinMode(redled, OUTPUT);
  pinMode(greenled, OUTPUT);  
  pinMode(dirpin, OUTPUT);
  pinMode(steppin, OUTPUT);
  pinMode(dirpinb, OUTPUT);
  pinMode(steppinb, OUTPUT);
  randomSeed(analogRead(0)); //generate different random number
}

void loop()
{
  Alarm.delay(0);
  randNumbers = random(1, 5); //generate a random number from 1 to 4
}

void AlarmF()
{
  if (randNumbers == 1)
  {
    int i;
    int counter1;
    counter1++;

    if (counter1 < 3)
    {
      Serial.print("#S|OPENVID|["); //gobetwino opens video capture software
      Serial.println("]#");
      delay(15000); //wait 15 seconds

      Serial.println("#S|SENDK|[0&{F5}]#"); //gobetwino hits F5 to start recording
      delay(10000); //wait 10 seconds

      digitalWrite(redled, HIGH);  //turn on red LED
      digitalWrite(greenled, HIGH); //turn on green LED

      Serial.print("#S|AUDIO1|["); //gobetwino opens audio1
      Serial.println("]#");

      delay(5000); //wait 5 seconds

      digitalWrite(dirpinb, HIGH); //set the big motor to rotate clockwise
      digitalWrite(dirpin, LOW); //set the small motor to rotate clockwise

      for (i = 0; i<50; i++) //rotate the big motor 50 steps
      {
        digitalWrite(steppinb, LOW);
        digitalWrite(steppinb, HIGH);
        delayMicroseconds(8000);
      }

      delay(1000); //wait 1 second

      for (i = 0; i<200; i++) //feed the fish AKA rotate the small motor 200 steps
      {
        digitalWrite(steppin, LOW);
        digitalWrite(steppin, HIGH);
        delayMicroseconds(8000);
      }

      delay(1000); //wait 2 seconds

      digitalWrite(dirpinb, LOW); //change the direction of the big motor to counterclockwise

      for (i=0; i<50; i++) //return the big motor to its starting position
      {
        digitalWrite(steppinb, LOW);
        digitalWrite(steppinb, HIGH);
        delayMicroseconds(8000);
      }

      Serial.println("#S|SENDK|[1&^q]#"); //gobetwino quits VLC
      digitalWrite(redled, LOW);
      digitalWrite(greenled, LOW);  

      delay(10000); //wait 10 seconds
      Serial.println("#S|SENDK|[0&%{F4}~]#"); //gobetwino hits ALT+F4 to quit video capture software
    }
    else if (counter1 >= 3)
    {
      void AlarmF();
    }
  }
  else if (randNumbers == 2)
  {
    int i;
    int counter2;
    counter2++;

    if (counter2 < 3)
    {
      Serial.print("#S|OPENVID|["); //gobetwino opens video capture software
      Serial.println("]#");
      delay(15000); //wait 15 seconds

      Serial.println("#S|SENDK|[0&{F5}]#"); //gobetwino hits F5 to start recording
      delay(10000); //wait 10 seconds

      digitalWrite(redled, HIGH);  //turn on red LED
      digitalWrite(greenled, HIGH); //turn on green LED

      Serial.print("#S|AUDIO2|["); //gobetwino opens audio2
      Serial.println("]#");

      delay(5000); //wait 5 seconds

      digitalWrite(dirpinb, LOW); //set the big motor to rotate counterclockwise
      digitalWrite(dirpin, LOW); //set the small motor to rotate clockwise

      for (i = 0; i<50; i++) //rotate the big motor 50 steps
      {
        digitalWrite(steppinb, LOW);
        digitalWrite(steppinb, HIGH);
        delayMicroseconds(8000);
      }

      delay(1000); //wait 1 second

      for (i = 0; i<200; i++) //feed the fish AKA rotate the small motor 200 steps
      {
        digitalWrite(steppin, LOW);
        digitalWrite(steppin, HIGH);
        delayMicroseconds(8000);
      }

      delay(1000); //wait 1 seconds

      digitalWrite(dirpinb, HIGH); //change the direction of the big motor to counterclockwise

      for (i=0; i<50; i++) //return the big motor to its starting position
      {
        digitalWrite(steppinb, LOW);
        digitalWrite(steppinb, HIGH);
        delayMicroseconds(8000);
      }

      Serial.println("#S|SENDK|[1&^q]#"); //gobetwino quits VLC
      digitalWrite(redled, LOW);
      digitalWrite(greenled, LOW);  

      delay(10000); //wait 10 seconds
      Serial.println("#S|SENDK|[0&%{F4}~]#"); //gobetwino hits ALT+F4 to quit video capture software
    }
    else if (counter2 >= 3)
    {
      void AlarmF();
    }
  }
  else if (randNumbers == 3)
 (code continues.. didn't copy to save space)
    int counter2;
    counter2++;

    if (counter2 < 3)
    {

Here you are declaring counter2 as a local automatic variable which means it will get recreated each time it comes into scope. (Also, you haven't initialised it.)

If you're only using the counter here, you could declare it as a static variable.

    static int counter2;

If you also need to use it in other places then it needs to be somewhere visible to all those places and the simplest way to do that is to make it a global variable. To do that, move the definition outside of the function.

Declaring the 4 counters at the beginning of the sketch worked to limit the functions to be called no more than 2 times per day, thank you!

Now, I have the opposite problem! The functions are being called a different number of times each day. In the last 3 tests, functions were called 7, 5, and 7 times, respectively. Do you have any suggestions on how to make sure a function is called every time an alarm is run (8 times a day)?

I tried changing

    else if (counter1 >= 3)
    {
      void AlarmF();
    }

to

    else if (counter1 >= 3)
    {
      void return;
    }

but that didn't help. The rest of the code is the same as in my previous post.

Gtown:
The functions are being called a different number of times each day.

If you're trying to count how many times each function has been used (per day) then clearly either you aren't counting correctly, or you aren't testing the count correctly. If you can't tell which is the case, try printing out the counter each time the associated function is called and check whether it's being incremented properly.

If it's being incremented properly and your code still calls the function when it shouldn't, it's not testing the counter correctly.

If you have 4 functions, and want to call each one 2 times, but in a random order...

I think I might handle it by making an 8 element array, and populate it with 4 numbers.

byte funcNum[] = {0,1,2,3,0,1,2,3};

Then you can shuffle the array, using two random numbers in the range of 0 through 7 to swap two of the bytes.

Finally, number each alarm, from 0 through 7, and when one happens, fetch the corresponding funcNum, and switch/case on that to call the function. Or, make the numbers range from 1 through 4, and when an alarm happens, just take the next non-zero entry as the next funcNum, and make that entry = 0.

You will need to take steps to avoid using the same sequence of random numbers, of course. Perhaps you could shuffle in loop() until the first alarm occurs, then stop shuffling before handling the first one.

I wasn't able to figure out how to correct the counter issue of too few functions running per day so I made an attempt to switch to arrays instead. I have also changed the paradigm to include 4 functions that are called 3 times per day, for a total of 12 functions per day. All 12 functions run now, however, each of the 4 functions (UpwardsFM, DownwardsFM, UpwardsSham, and DownwardsSham) are not being called an equal number of times. I would like them to be called 3 times each, in random order of course.

Could somebody please advise me on how to fix the issue?

void setup()
{
  Serial.begin(9600); //initialize communication
  setTime(11,59,30,3,15,14); //set time
  Alarm.alarmRepeat(12,0,0, AlarmF); //set first alarm time
  Alarm.alarmRepeat(12,1,0, AlarmF); //set second alarm time
  Alarm.alarmRepeat(12,2,0, AlarmF); //set third alarm time
  Alarm.alarmRepeat(12,3,0, AlarmF); //set fourth alarm time
  Alarm.alarmRepeat(12,4,0, AlarmF); //set fifth alarm time
  Alarm.alarmRepeat(12,5,0, AlarmF); //set sixth alarm time
  Alarm.alarmRepeat(12,6,0, AlarmF); //set seventh alarm time
  Alarm.alarmRepeat(12,7,0, AlarmF); //set eighth alarm time
  Alarm.alarmRepeat(12,8,0, AlarmF); //set ninth alarm time
  Alarm.alarmRepeat(12,9,0, AlarmF); //set tenth alarm time
  Alarm.alarmRepeat(12,10,0, AlarmF); //set eleventh alarm time
  Alarm.alarmRepeat(12,11,0, AlarmF); //set twelfth alarm time 

  randomSeed(analogRead(0)); //generate  random number
}

int funcarray[12] = {1,2,3,4,1,2,3,4,1,2,3,4}; //Function array whose elements represent 4 functions that are called 3 times each
int boolarray[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; //Boolean array all of whose values are set to False

int randselect;
int funcselect;

void loop()
{
  Alarm.delay(0);

  randselect = random(0,12); //Generate a random number from 0 to 11

  if (boolarray[randselect] == 0) //If the element chosen randomly from the boolean array is set to False
  {
    funcselect = funcarray[randselect]; //funcselect is used below to call the appropriate function
  }
  else if (boolarray[randselect] == 1) //If the element chosen randomly from the boolean array is set to True
  {
    return;
  }
}

void AlarmF()
{
  if (funcselect == 1) //UpwardsFM
  {
   //code for UpwardsFM removed for brevity
    boolarray[randselect] == 1; //Set boolean array element to True to prevent unwanted repetition
  }
  
  else if (funcselect == 2) //DownwardsFM
  {
    //code for DownwardsFM removed for brevity
    boolarray[randselect] == 1; //Set boolean array element to True to prevent unwanted repetition
  }
  else if (funcselect == 3) //UpwardsSham
  {
   //code for UpwardsSham removed for brevity
    boolarray[randselect] == 1; //Set boolean array element to True to prevent unwanted repetition
  }
  else if (funcselect == 4) //DownwardsSham
  {
   //code for DownwardsSham removed for brevity
    boolarray[randselect] == 1; //Set boolean array element to True to prevent unwanted repetition
  }
}
int funcarray[12] = {1,2,3,4,1,2,3,4,1,2,3,4};

Perhaps you need to use long or long long, instead to hold these byte sized values.

int boolarray[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

I'd expect an array with bool in it's name to ACTUALLY be a bool array. I'm just strange that way, I guess.

  if (boolarray[randselect] == 0) //If the element chosen randomly from the boolean array is set to False
  {
    funcselect = funcarray[randselect]; //funcselect is used below to call the appropriate function
  }
  else if (boolarray[randselect] == 1) //If the element chosen randomly from the boolean array is set to True
  {
    return;
  }

The values in boolarray should be true or false. If the value is true, do something. If it's not true, it can't be anything but false, so there is no reason to have the second if test.

If the value is NOT false, the thing to do is NOT return. It is to keep looping, choosing another random value until the value IS false.

You ACTUALLY have to do something with funcselect.

Thanks for your help!

Still no luck though. Each of the 4 functions are still being called an unequal number of times.

I tried changing int 'array' to

long long funcarray[12] = {1,2,3,4,1,2,3,4,1,2,3,4};
long long boolarray[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

and

long funcarray[12] = {1,2,3,4,1,2,3,4,1,2,3,4};
boolean boolarray[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

and even

long funcarray[12] = {1,2,3,4,1,2,3,4,1,2,3,4};
long boolarray[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

I also removed the "else if" statement from void loop()

int randselect;
int funcselect;
void loop()
{
  Alarm.delay(0);

  randselect = random(0,12);

  if (boolarray[randselect] == 0)
  {
    boolarray[randselect] == 1;
    funcselect = funcarray[randselect];
  }
}

Any idea why this is happening?

I think the boolarray's elements aren't being updated to True. Is there a way I can print the entire boolarray to see if it is being updated? I tried using serial.println(boolarray[]) but only 1 element was printed.

Any idea why this is happening?

Geez, when I pulled your leg, I didn't expect it to come off. The array types should be byte and boolean, not long or long long.

Your code chooses which function to call, but then you don't call the function you chose. Instead, you have some timers that go off at weird times. I don't understand that at all.

:grin: I was kidding about the long long too, but I did try long!

To explain in more detail, I need to randomly call 1 of 4 functions at specific times everyday. The actual times are 8 AM, 9AM ... 7 PM and the timers are used to call the functions at those times.

For testing purposes, I scheduled the timers in the code posted above to run consecutively (1 min apart) so I don't have to wait all day to see if the code worked.

Is there a better way for me to get the job done, perhaps without the use of timers?

    boolarray[randselect] == 1; //Set boolean array element to True to prevent unwanted repetition

The code is NOT doing what the comment says. It is testing whether boolarray[randselect] is 1, and throwing the result of the equality test away. Why? = is the assignment operator.