Random State Machine

Hi I am building a Useless Machine which will have 3 servos which act in different ways when the switch is pressed.The servos will not be a problem for me. I have been experimenting with them and seem to have that part sorted. I have been thinking of using a state machine to control the box. This bit is very easy I know. The thing is I want to have around 9 or 10 different consequences when the switch is activated. But I do not want it to be predictable. How do I make it choose a random state each time. If you have never seen a useless machine just take a look on you tube.

Obviously i am not very experienced but I suppose what I want is staring me in the face. Thank you for your time guys. If you need any more information please ask. A little snippet of code

if (val==LOW){// button has been pressed
        if(nextState == 0){
          nextState=1;//   I want to jump to a random state here
         //Do something 

        }
        else if(nextState == 1){
          nextState=2;//and here too
         //Do something else
        }
        else if(nextState == 2){
          nextState=3;// change the mode  again
          //Do something different
        }

Moderator edit: tags corrected

Have you looked into the use of random()?

http://arduino.cc/en/reference/random

You may also want to use randomSeed() to prevent the pseudo-random sequence from repeating itself each time the device is powered up. The simplest way to do that is:

void setup()
{
  randomSeed(analogRead(a0));
}

The assumption is that a0 is not connected to any analog input. The disconnected analog pin will be "floating" so it will return an unpredictable value that will seed the random number generator differently each time.

So, basically, seed the random number generation algorithm in setup(), then use random() to generate the number of the state that you are going to next.

Rather than using all those if .... else statements generate a random number and use the switch construct to select what function you want to use. http://arduino.cc/en/Reference/SwitchCase

joshuabardwell: You may also want to use randomSeed() to prevent the pseudo-random sequence from repeating itself each time the device is powered up. The simplest way to do that is:

void setup()
{
  randomSeed(analogRead(a0));
}

Disregarding the obvious syntax error, using a floating pin to initialize random is a bad choice.

Thank you Guys I think have got it. I have made a little tester sketch using some led’s. I also used a simple debounce routine to help keep everything tight. I have posted the code below (Please be aware that I am fairly new to programming.) I know there are probably lots of things I could do to improve my sketch. Please be merciful. :slight_smile:
Thanks again…

long randNumber;// variable for the random number
int button = 12;// button pin connected to digital pin 12

int val;//variable to read the pin status
int timer=10;//milliseconds we need to debounce the button
int val2;//variable to read pin status again after a short delay.

int buttonState;//this holds the state of the button
void setup(){
  Serial.begin(9600);
  for (int i=2;i<10;i++){// I had an led strip I used for testing
    pinMode(i,OUTPUT);    // Just as a visual aid to see if it works
  }                       // Although I only used 4 of them
  pinMode (button,INPUT);
  //
  //************ read the button in setup*******
  buttonState = digitalRead(button); // give us a starting state
}


void loop() {


  //The Debounce
  val=digitalRead(button);//read the button
  delay(timer);// time for button to stop bouncing.
  val2=digitalRead(button);//read the button again
  //this debounces the switch


  // use the lines below if the switch is not working to debug
  // Serial.print("Val =  ");// prints the word (val =) and some spaces
  // Serial.println(val);//the button reading just to make sure it works
  // if the circuit does not work you can see if the switch is working or not


  if (val == val2){//read the input and compare the readings
    if(val !=buttonState){//if something has changed the button has been pressed

      if (val==LOW){// button has been pressed
        randNumber = random(0, 4);// Random number generated for the switch
        Serial.println(randNumber);// print the random number
        int range = (randNumber);
        switch (range) {
        case 0:  
          Serial.println("Case 0");
          digitalWrite(2,HIGH);
          digitalWrite(3,LOW);
          digitalWrite(4,LOW);
          digitalWrite(5,LOW);

          break;
        case 1:    
          Serial.println("Case 1");
          digitalWrite(3,HIGH);
          digitalWrite(2,LOW);
          digitalWrite(4,LOW);
          digitalWrite(5,LOW);

          break;
        case 2:    
          Serial.println("Case 2");
          digitalWrite(4,HIGH);
          digitalWrite(2,LOW);
          digitalWrite(3,LOW);
          digitalWrite(5,LOW);


          break;
        case 3:   
          Serial.println("Case 3");

          digitalWrite(5,HIGH);
          digitalWrite(2,LOW);
          digitalWrite(3,LOW);
          digitalWrite(4,LOW);


          break;

        }
      }
    }
    buttonState=val;// save the button state in the variable
    //the arduino is ready for the next button event 
  }
  delay(50);
}

        int range = (randNumber);Why do this and why the brackets ?

int range = (randNumber);

Why do this and why the brackets ?

The brackets yes that is a mistake. but as for the line itself The sketch will not work without it. int range = randNumber; // is what I should have used.

int range; or int range=0; do not work. What do you suggest i do ?

What do you suggest i do ?

Maybe something like this:

int uselessCopy = randomNumber;
int uselessCopyOfUselessCopy = uselessCopy;
int anotherUselessCopy = uselessCopyOfUselessCopy;
switch(anotherUselessCopy)
{
}

I am not convinced by the "floating analog input" theory of initialising the "random" number sequence.

An alternative suggestion, is to measure the time in millis() between when the sketch starts, and the first time you press the button. Use that number to initialise the random number sequence. Unless you are very predictable, you are not going to make that first button press exactly the same number of milliseconds after the arduino reset very often.

michinyon: I am not convinced by the "floating analog input" theory of initialising the "random" number sequence.

An alternative suggestion, is to measure the time in millis() between when the sketch starts, and the first time you press the button. Use that number to initialise the random number sequence. Unless you are very predictable, you are not going to make that first button press exactly the same number of milliseconds after the arduino reset very often.

Just take the lowest 8 or fewer bits of time. No one is that consistent. It's so easy to get past human capabilities with Arduino!

PaulS:

What do you suggest i do ?

Maybe something like this:

int uselessCopy = randomNumber;

int uselessCopyOfUselessCopy = uselessCopy;
int anotherUselessCopy = uselessCopyOfUselessCopy;
switch(anotherUselessCopy)
{
}

Dear OP: In case you do not learn most effectively when your advisers respond to you in a very sarcastic way, I will try to make up for my earlier transgressions by translating. You do this:

        randNumber = random(0, 4);// Random number generated for the switch
        Serial.println(randNumber);// print the random number
        int range = (randNumber);
        switch (range) {

The “range = randNumber” line is redundant. You could simply do this:

        randNumber = random(0, 4);// Random number generated for the switch
        Serial.println(randNumber);// print the random number
        switch (randNumber) {

There isn’t an obvious benefit to or need to create a second variable that duplicates the contents of randNumber.

Thank you all for your advice. I seem to have it sorted for this project now. I am going to start writing the servo code and will post an update soon. Thanks