Pages: [1] 2   Go Down
Author Topic: FSM (was dysfunctional function)  (Read 589 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My first attempt was a partial success. Motors will start with correct sensor input but won't stop. Probably apparent that I have never tried an FSM and am not entirely sure this sketch qualifies. A dozen versions preceded this one. All behaved badly in one way or another.

Code:
void loop ()
{
 static int state = 1;
  sonarVal = analogRead (sonarPin);
 Serial.println (sonarVal);
 delay(500);
 if (sonarVal < 11)
 {
switch (state)
{
if (sonarVal < 11)
{
state = 1;
}
break;
 case 1:
   digitalWrite (motorLeft, HIGH);
   digitalWrite (motorMiddle,HIGH);
   digitalWrite (motorRight, HIGH);
   

 
 if (sonarVal > 11)
{
 state = 2;
}
break;
 case 2:
   digitalWrite (motorLeft, LOW);
   digitalWrite (motorMiddle,LOW);
   digitalWrite (motorRight,LOW);
   state =1;
   break;
   default:
     state = 1;
     break;
   
}

 }   

 
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That indentation is horrible. Use the Arduino IDE's Auto Format tool (Tools > Auto Format) before posting your code.
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why are you assigning the state back to 1 in state 2?
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

All the text and web examples include this step. Monkey see, monkey do until this starts to gel.  After deleting "state =1;", the motor responds the same; starts, but won't stop.
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...So why haven't you fixed the indenting?
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Better?
Code:
void loop ()
{
  static int state = 1;
  sonarVal = analogRead (sonarPin);
  Serial.println (sonarVal);
  delay(500);
  if (sonarVal < 11)
  {
    switch (state)
    {
      if (sonarVal < 11)
      {
        state = 1;
      }
      break;
    case 1:
      digitalWrite (motorLeft, HIGH);
      digitalWrite (motorMiddle,HIGH);
      digitalWrite (motorRight, HIGH);



      if (sonarVal > 11)
      {
        state = 2;
      }
      break;
    case 2:
      digitalWrite (motorLeft, LOW);
      digitalWrite (motorMiddle,LOW);
      digitalWrite (motorRight,LOW);
      state =1;
      break;
    default:
     // state = 1;
      break;

    }

  }   
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  if (sonarVal < 11)
  {
    switch (state)
    {
      if (sonarVal < 11)
      {
        state = 1;
      }

I have no idea what you are trying to do here. Why are there two tests for the sonarVal? Why is there a test for sonarVal inside the switch, but not in a case?
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 90
Posts: 3526
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you remind me what you are trying to do ?
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, I have four very helpful books, printed a web tutorial, and still have only a vague idea of how to structure an FSM that will turn these motors on and off, depending upon the value of sensor input. Once, or if, this is up and running, there are steppers, and random servo FSM's to add. I appreciate your patience!
Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 50
Posts: 3435
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For the initial requirement, you can of course just use an if:
Code:
void loop()
{
sonarVal = analogRead (sonarPin);
Serial.println (sonarVal);
delay(500);
if (sonarVal < 11)
  {
  digitalWrite (motorLeft, HIGH);
  digitalWrite (motorMiddle,HIGH);
  digitalWrite (motorRight, HIGH);
  }
else
  { 
  digitalWrite (motorLeft, LOW);
  digitalWrite (motorMiddle,LOW);
  digitalWrite (motorRight,LOW);
  }
}
If you want to do it as a FSM, it might look more like this:
Code:
void loop()
{
static int state = 1;
sonarVal = analogRead (sonarPin);
Serial.println (sonarVal);
delay(500);
switch (state)
  {
  case 1:
    if (sonarVal < 11)
      {
      digitalWrite (motorLeft, HIGH);
      digitalWrite (motorMiddle,HIGH);
      digitalWrite (motorRight, HIGH);
      }
    else
      {
      state=2;
      }
    break;

  case 2:
    if (sonarVal > 11)
      {
      digitalWrite (motorLeft, LOW);
      digitalWrite (motorMiddle,LOW);
      digitalWrite (motorRight,LOW);
      }
    else
      {
      state = 1;
      }
    break;
  default:
    break;
  }   

Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bravo!  Works great. Now if I haven't gone too far astray, I can now write the servos, etc., as case three, four, five.........by simply prefacing all with the if/else sonar threshold. Is that right? 
Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 50
Posts: 3435
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hard to say. I'm not at all clear what your system as a whole is doing.
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The motors (dc, servos, and steppers) are intended to activate parts of the piece when the viewer approaches the sculpture, continuously until the the sensor no longer detects their presence.
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have searched far and wide but can't find an example of multiple FSM in a single loop. Both these FSM function in separate sketches, but not together here. The motors respond, the servos don't. Guesswork has proven futile.

Code:
void loop()
{
  static int state1 = 1;
  static int state2 = 1;
  sonarVal = analogRead (sonarPin);
  Serial.println (sonarVal);
  delay(500);
  switch (state1)
  {
  case 1:
    if (sonarVal < 11)
    {
      digitalWrite (motorLeft, HIGH);
      digitalWrite (motorMiddle,HIGH);
      digitalWrite (motorRight, HIGH);
    }
    else
    {
      state1=2;
    }
    break;

  case 2:
    if (sonarVal > 11)
    {
      digitalWrite (motorLeft, LOW);
      digitalWrite (motorMiddle,LOW);
      digitalWrite (motorRight,LOW);
    }
    else
    {
      state1 = 1;
    }
    break;
    // default:
    // break;
    switch (state2)
    case 3:
      if (sonarVal < 11)
      {

        Serial.println(sonarVal);
        delay(250);//50

          lasttime1 = millis();
        randstart =  random(554, 1054);
        randend =  random(500, 2400);

        while(pos1 <= randend) 
        {     
          pos1 += 1;
          myservo1.writeMicroseconds(pos1);   
          delay(2);   //2                 
        }
        while(pos2 <= randend) 
        {     
          pos2 += 1;
          myservo2.writeMicroseconds(pos2);
          delay(2);   //2                 
        }
        while(pos3 <= randend) 
        {
          pos3 += 1;
          myservo3.writeMicroseconds(pos3);   
          delay(2);   //2                 
        }
        duration = millis() - lasttime1;
        lasttime2 = millis();

        while(pos1 >= randstart)   
        {                               
          pos1-=1;
          myservo1.write(pos1);   
          delay(2);                     
        }
        while(pos2 >= randstart)   
        {                               
          pos2-=1;
          myservo2.write(pos2);   
          delay(2);                     
        }
        while(pos3 >= randstart)   
        {                               
          pos3-=1;
          myservo3.write(pos3);   
          delay(2);                     
        }
        duration = millis() - lasttime2;
        duration = millis() - lasttime1;

      } 
      else
      {
        state2 =4;
      } 
    break;

  case 4:
    if (sonarVal > 11)
    {
      myservo1.write(0);
      myservo2.write(0);
      myservo3.write(0); 
    }
    else
    {
      state2 = 3;
    }
    break;
  default:
    break;

  }
}
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 90
Posts: 3526
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The motors (dc, servos, and steppers) are intended to activate parts of the piece when the viewer approaches the sculpture, continuously until the the sensor no longer detects their presence.

I don't really see why you need to use states in the loop()
Code:
if (someone in range)
{
  move stuff;
}
else
{
  stop stuff;
}
States are useful when there are many of them and when events happening need to cause the system to switch between states, often not in a linear way (state 1, state 2, state 3 etc)

A suggestion.  Write a non blocking function for each action that should happen when someone is in range.  One for DC motors, one for servos and one for steppers.   The functions may well use states to keep track of the actions to be carried out.  They can be tested in isolation to make sure that they work.  Put a call to each of them where I have said 'move stuff' in the code block above.
« Last Edit: March 20, 2013, 07:54:16 am by UKHeliBob » Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Pages: [1] 2   Go Up
Jump to: