FSM (was dysfunctional function)

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.

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

 }   
}

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

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

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.

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

Better?

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;

    }

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

Can you remind me what you are trying to do ?

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!

For the initial requirement, you can of course just use an if:

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:

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

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?

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

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 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.

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;

  }
}

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()

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.

The whole idea behind state machines was to enable you to get rid of the delay()s. You just keep adding more. I don't get it.

I assumed the immediate delay (500) was necessary to read the serial monitor? As for those within the servo statements, I pirated that part of the sketch and, frankly, don't completely understand it.

ifugaopapercraft:
I assumed the immediate delay (500) was necessary to read the serial monitor?

Nope.

As for those within the servo statements, I pirated that part of the sketch and, frankly, don't completely understand it.

Now is your chance to play around with it so that you CAN completely understand it.