Go Down

Topic: FSM (was dysfunctional function) (Read 825 times) previous topic - next topic

ifugaopapercraft

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: [Select]
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;
   
}

}   

 

Arrch

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

Arrch

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

ifugaopapercraft

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.

Arrch

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

ifugaopapercraft

Better?
Code: [Select]
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;

    }

  }   

Arrch

Code: [Select]
  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?

UKHeliBob

Can you remind me what you are trying to do ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

ifugaopapercraft

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!

wildbill

For the initial requirement, you can of course just use an if:
Code: [Select]

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: [Select]

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;
  }   


ifugaopapercraft

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? 

wildbill

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

ifugaopapercraft

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.

ifugaopapercraft

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: [Select]
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;

  }
}

UKHeliBob

#14
Mar 20, 2013, 08:40 am Last Edit: Mar 20, 2013, 01:54 pm by UKHeliBob Reason: 1
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: [Select]

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.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Go Up