state machine

I want to turn on red/blue/green leds with specific thresholds, depending upon sensor input. With other sketches, the sensor functions but not with this. I obviously don't know the state machine procedure well enough to pull this off. Would appreciate help. Thanks.

int redLED = 13 ;
int blueLED = 12;
int greenLED = 8;

int sensor = 1;

int state = 0;

#define GREEN 0
#define BLUE  1
#define RED   2


void setup()
{
sensor = analogRead(1);

pinMode(redLED,OUTPUT);
pinMode(blueLED,OUTPUT);
pinMode(greenLED,OUTPUT);



Serial.begin(9600);
}


void loop(){
  if(sensor < 1023) {
    switch(state) {
      
      case GREEN:
       if((sensor >0) && (sensor < 600)) {
         digitalWrite(greenLED,HIGH);
         digitalWrite(blueLED,LOW);
         digitalWrite(redLED,LOW);
       }
     break;  
     
      case BLUE:
       if((sensor >601) && (sensor < 800)) {
         digitalWrite(greenLED,LOW);
         digitalWrite(blueLED,HIGH);
         digitalWrite(redLED,LOW);
       }
     break; 
     
      case RED:
       if((sensor >801) && (sensor < 1023)) {
         digitalWrite(greenLED,LOW);
         digitalWrite(blueLED,LOW);
         digitalWrite(redLED,HIGH);
       }
     break; 
     
    }
  }
  Serial.println(sensor);
}

You never seem to change the state... :wink:

//http://www.arduino.cc/playground/Code/FiniteStateMachine
#include <FiniteStateMachine.h>
 
//initialize states
State Red = State(red);
State Green = State(green);
State Blue = State(blue);
 
FSM ledStateMachine = FSM(On);     //initialize state machine, start in state: On
 
int sensor = 0

void setup(){ /*nothing to setup*/ }
 
//poor example, but then again; it's just an example
void loop(){
      sensor = analogRead(1);
      
      if((sensor >= 0) && (sensor <= 600)) {
            ledStateMachine.transitionTo(Red);
      }

      if((sensor > 601) && (sensor <= 800)) {
            ledStateMachine.transitionTo(Green);
      }

      if((sensor > 801) && (sensor <= 1023)) {
            ledStateMachine.transitionTo(Blue);
      }
      
      ledStateMachine.update();
}
 
//utility functions
void red(){ /*implement*/ }
void green(){ /*implement*/ }
void blue(){ /*implement*/ }
//end utility functions

[edit]Here you go:

http://www.arduino.cc/playground/Code/FiniteStateMachine
:)[/edit]

Thank you. I will download the library. A bit lost on this one.

An error occurs when I run your code: "expected unqualified id before numeric constant". This is the error I find most difficult to resolve. I have downloaded the library. What am I doing wrong? Appreciate your help.

#include <FiniteStateMachine.h>

//initialize states
State Red = State(red);
State Green = State(green);
State Blue = State(blue);

FSM ledStateMachine = FSM(On);     //initialize state machine, start in state: On

int sensor = 0

void setup(){ /*nothing to setup*/ }

//poor example, but then again; it's just an example
void loop(){
      sensor = analogRead(1);

      if((sensor >= 0) && (sensor <= 600)) {
            ledStateMachine.transitionTo(Red);
      }

      if((sensor > 601) && (sensor <= 800)) {
            ledStateMachine.transitionTo(Green);
      }

      if((sensor > 801) && (sensor <= 1023)) {
            ledStateMachine.transitionTo(Blue);
      }

      ledStateMachine.update();
}

//utility functions
void red(){ /*implement*/ }
void green(){ /*implement*/ }
void blue(){ /*implement*/ }
//end utility functions

Sorry...
This FSM(On); need be this: FSM(Red);
:slight_smile:

I must have not written the utility functions correctly because the lights don't blink.

#include <FiniteStateMachine.h>
int redLED = 13;
int blueLED = 12;
int greenLED = 8;
int sensor = 0;


//initialize states
State Red = State(red);
State Green = State(green);
State Blue = State(blue);

FSM ledStateMachine = FSM(Red);     //initialize state machine, start in state: On

void setup(){ /*nothing to setup*/

pinMode(redLED,OUTPUT);
pinMode(blueLED,OUTPUT);
pinMode(greenLED,OUTPUT);


}


//poor example, but then again; it's just an example
void loop(){
      sensor = analogRead(1);

      if((sensor >= 0) && (sensor <= 600)) {
            ledStateMachine.transitionTo(Green);
      }

      if((sensor > 601) && (sensor <= 800)) {
            ledStateMachine.transitionTo(Blue);
      }

      if((sensor > 801) && (sensor <= 1023)) {
            ledStateMachine.transitionTo(Red);
      }

      ledStateMachine.update();
}

//utility functions
void red()
{
  redLED = HIGH;
  blueLED = LOW;
  greenLED = LOW;
  delay(1000);
  }
void green()
{
  greenLED = HIGH;
  redLED = LOW;
  blueLED = LOW;
  delay(1000);
 
   }
void blue()
{
 blueLED = HIGH;
 redLED = LOW;
 greenLED = LOW;
  delay(1000);
  
  }
//end utility functions

You need some digitalWrite(xyzLED,HIGH); and digitalWrite(xyzLED,LOW); in there to make them blink.
[edit]Where xyz is either one of red blue green[/edit]

Gee, how dumb! Thanks.

With this sketch, the light does not move from green, regardless of sensor data. Another dumb mistake, no doubt.

#include <FiniteStateMachine.h>
int greenLED = 12;
int redLED = 13;
int blueLED =8;
int sensor = 0;

unsigned long starTime;
int flashRed = 20000;
 
 
 const int numReadings = 3;
 int readings[numReadings];      // the readings from the analog input
 int index = 0;                  // the index of the current reading
 int total = 0;                  // the running total
 int average = 0;


//initialize states
State Red = State(red);
State Green = State(green);
State Blue = State(blue);

FSM ledStateMachine = FSM(Green);     //initialize state machine, start in state: On

void setup(){ /*nothing to setup*/

pinMode(redLED,OUTPUT);
pinMode(blueLED,OUTPUT);
pinMode(greenLED,OUTPUT);
sensor = analogRead(1);
Serial.begin(9600);


}



void loop(){
      //sensor = analogRead(1);

 // subtract the last reading:
   total= total - readings[index];         
   // read from the sensor:  
   readings[index] = analogRead(sensor); 
   // add the reading to the total:
   total= total + readings[index];       
   // advance to the next position in the array:  
   index = index + 1;                    
   // if we're at the end of the array...
   if (index >= numReadings)              
     // ...wrap around to the beginning: 
     index = 0;                           
   // calculate the average:
   average = total / numReadings ;
  

      if((sensor >= 0) && (average <= 510)) {
            ledStateMachine.transitionTo(Green);
      }

      if((sensor > 511) && (average <= 549)) {
            ledStateMachine.transitionTo(Blue);
      }

      if((sensor > 550) && (average <=1023)) {
            ledStateMachine.transitionTo(Red);
      }

      ledStateMachine.update();



Serial.println(average, DEC);
}
//utility functions
void red()
{
  digitalWrite(redLED, HIGH);
  digitalWrite(blueLED,LOW);
  digitalWrite(greenLED, LOW);
  delay(1000);
  }
void green()
{
  digitalWrite(redLED,LOW);
  digitalWrite(blueLED,LOW);
  digitalWrite(greenLED,HIGH);
  delay(1000);
 
   }
void blue()
{
 digitalWrite(redLED, LOW);
  digitalWrite(blueLED,HIGH);
  digitalWrite(greenLED, LOW);
  delay(1000);
  
  }
//end utility functions

What kind of values do you see printed for average?

How about adding a print after reading the sensor, so you can be sure that average is being computed correctly? Maybe add print statements in each if block to verify that the correct transitionTo statement is being invoked.

The sensor variable does not seem to be used?
[edit]Insane! I missed PaulS by 2 hundreds of a second![/edit]

I found the error involving the sensor pin and changed both to "1" but the results are the same; no change. Sorry, not quite sure what you are pointing to regarding the sensor.

Values range from 470~520, depending on setting of the pot.

I think you need a sensor = analogRead(1); in the loop. :slight_smile:

Geez, I missed that thing with the sensor, too.

You have sensor as the pin that the data is coming in on. It will never be greater than 1, so, depending on the average value of the sensor data, the first if test may, or may not, be true, but none of the others can ever be true.

With the sensor in the loop, the data gets wild from 0~300. Three to four 0~2, followed by as many higher numbers.

What kind of sensor do you have connected?

Aside from the variations in sensor data, is the state machine now working?

No, the green light stays on, despite sensor input that should turn it off and blue or red, on. I don't understand this part of the sketch:

//initialize states
State Red = State(red);
State Green = State(green);
State Blue = State(blue);

I haven't made any reference to these all lower case colors anywhere else.

Those all low-case names are the names of your functions.

To test the statemachine.

Use this loop:

void loop(){
  ledStateMachine.transitionTo(Green);
  ledStateMachine.update();
  delay(1000);
  ledStateMachine.transitionTo(Blue);
  ledStateMachine.update();
  delay(1000);
  ledStateMachine.transitionTo(Red);
  ledStateMachine.update();
  delay(1000);
}

:slight_smile:
[edit]The functions associated with a state gets called each time the state machine is updated while in that state.[/edit]

The sensor is from a mic via LM386 that has been rectified and works fine on another sketch with simple if statements (but the results are not stable so I was looking for an alternative).