Trouble understanding irregular servo function with POT

Hello gang,

I have tinkered for a while with this project and have not been able to understand why my program on the servos are so inconsistent.

Goal:

  1. 6 servos randomly moving (continuously)
  2. Potentiometer used to control the speed movement of the servo's movement. ( I set up POT to map to a 20 levels ).

technically, these goals do work, however I am having inconsistent behaviors pending the POT's input. Hopefully the chart below will better show the performance differences at each POT setting.

POT | Servo range of motion | Servo pause before | Servo speed
setting | | returning to 0 |

1 180 degrees 12 sec. Slowest
5 180 degrees 2 sec. Fast
10 180 degrees 1 sec. Med
20 Progressively less, down 0 sec. Fast
to about 165 degrees

The code is repeated for each servo , so I am at a loss as to why such behaviors are showing pending on the POT setting.
Another irregularity is that the servos are all set to move 360 degrees, but none do this. Not even if I set it directly in Void Setup, as a test run calibration. Servos move just under 180 degrees.

To my understanding:

  1. All servos are to move 0 to 360, then from 360 to 0
  2. The potentiometer is to control the speed of the servo movement
  3. No noticeable pauses were programmed into the code

So, my concerns are:

  1. Servo movement ranges changing between POT setting of 17-20. (All code is repeated for each servo.
  2. Pauses between the servo movement from 0-180, and then returning back to 0. These pauses show up when the POT is set to 1-10 (out of 20 level settings). No delays are programmed greater than 50 ms.

I hope this was clear and to the point. The code is below. I used the simulator TinkerCad.

#include <Servo.h> 

int pos = 20;

int delayval = 0;
int dir = 1;

Servo aservo; 
Servo bservo; 
Servo cservo;
Servo dservo;
Servo eservo;  
Servo fservo;  

int apos=0; 
int bpos=0; 
int cpos=0;
int dpos=0;
int epos=0;   
int fpos=0;   
int strtPos=0;


void setup() { 
	
    pinMode(A0, INPUT);   // POT 
  
  	aservo.attach(12); 
	bservo.attach(11); 
	cservo.attach(10); 
  	dservo.attach(9);
    eservo.attach(8);
    fservo.attach(7);
  
  	apos = (0);
 	aservo.write(apos);
   	bpos = (0);
 	bservo.write(bpos);
   	cpos = (0);
 	cservo.write(cpos);
   	dpos = (0);
 	dservo.write(dpos);
      epos = (0);
 	eservo.write(0);
   	fpos = (0);
 	fservo.write(0);
  
  delay(100);
  
 	aservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES REGARDLESS OF 180, 360 INPUT
   	bservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	cservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	dservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	eservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	fservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
  
  delay(400);
    apos = (0);
 	aservo.write(apos);
  
 	bpos = (0);
 	bservo.write(bpos);
  
 	cpos = (0);
 	cservo.write(cpos);
  
 	dpos = (0);
 	dservo.write(dpos);
  
    epos = (0);
 	eservo.write(epos);
  
 	fpos = (0);
 	fservo.write(fpos);
  
  delay(200);
  
  	Serial.begin(9600);
  	Serial.print('\n');
  	Serial.print('\n');
  	Serial.print("Ardunio random servos controlled speed");
  	Serial.print('\n');
  	Serial.print('\n');
} 

void loop()
  { 
    int val = analogRead(A0);
    val= map(val,1,1023,1,21);
    Serial.print("              Speed set at ");
    Serial.print(val);
  
    int rand_num = random(1,7);
  	Serial.println('\n');
    Serial.print("random # is: ");
    Serial.print(rand_num);
    delay(800);
  
    if (rand_num==1)    
      { 
     	Serial.print(" Servo 1 selected ");
        delay(15);
    
    for (pos = 0; pos <= 360; pos +=val) 
      { 
        aservo.write(pos); 
        delay(15);   
      }
    
    for (pos = 360; pos >= 0; pos -= val) 
      { 
        aservo.write(pos);             
        delay(50);                 
      }
      
    return;
  }
    
   if (rand_num==2)    
     { 
    	Serial.print(" Servo 2 selected ");
        delay(15);
       
     for (pos = 0; pos <= 360; pos +=val) 
       { 
          bservo.write(pos);     
          delay(15);                      
       }
     for (pos = 360; pos >= 0; pos -= val) 
      { 
        bservo.write(pos);    
        delay(50);    
      }
    return;
  } 
  
   if (rand_num==3)    
    { 
   	  Serial.print(" Servo 3 selected ");
      delay(15);
   
    for (pos = 0; pos <= 360; pos +=val) 
      { 
        cservo.write(pos);    
        delay(15);     
      }
    for (pos = 360; pos >= 0; pos -= val) 
      { 
        cservo.write(pos); 
        delay(50);     
      }
  
    return;
  }
    
  if (rand_num==4)    
    { 
       Serial.print(" Servo 4 selected ");
       delay(15);
       
      for (pos = 0; pos <= 360; pos +=val) 
        { 
          dservo.write(pos); 
          delay(15);        
        }
     for (pos = 360; pos >= 0; pos -= val) 
       { 
          dservo.write(pos);              
          delay(50); 
       }
    
    return;
  }
     
  if (rand_num==5)    
    { 
      Serial.println(" Servo 5 selected ");
      delay(15);
      
     for (pos = 0; pos <= 360; pos +=val) 
       { 
         eservo.write(pos); 
         delay(15);  
       }
     for (pos = 360; pos >= 0; pos -= val) 
       { 
         eservo.write(pos); 
         delay(50); 
       }
  
    return;
  }
  
  if (rand_num==6)    
    { 
      Serial.print(" Servo 6 selected ");
      delay(15);
         
      for (pos = 0; pos <= 360; pos +=val) 
        { 
          fservo.write(pos);    
          delay(15); 
        }
      for (pos = 360; pos >= 0; pos -= val)
        { 
          fservo.write(pos);   
          delay(50);   
        }
    
    return;
  }
}   

You forgot to add the chart. Hopefully that will make your descriptions much clearer for us.

Most models of servo have only 180 degrees of movement. A few models have 270 degrees. Some have 360 degree movement and these are called "continuous rotation servos" but in reality they are not truly servos because they are not aware of their current angle and so cannot seek (move to) a given angle on request like a true servo can.

Thanks for your time and wisdom.

I had a makeshift chart with settings of the POT and the outcomes, and differences in times, movements and pauses. Sorry about the confusion.

I know that some servos has range limitations. My concern was, these simulations are moving the servos inconsistently pending what the POT setting is at. If I set the servos to move 180, then they move 40 degrees. I used example code from another sketch (which did move as expected), then modified it. Now it is different.
Strangely, I don't have code that uses the POT as a delay function, but it shows up when POT is set between 1-10, with up to a 12 second pause.

Thanks again for your time.

Update:
mentioning the delay function, I tweaked the code to allow a delay depending on the POT setting.

NOTE: below code is repeated for each servo, this does give consistent behaviors between all servos.

for (pos = 0; pos <= 360; pos +=val) 
        { 
          fservo.write(pos);    
        delay(val*2);
        }
      for (pos = 360; pos >= 0; pos -= val)
        { 
          fservo.write(pos);   
          delay(50);   
        }
    ```
This code seems to allow the servos to move 180 degrees on all POT variations.

So, at this point, added pauses are still showing up.  With this change in the code, the pauses seem to be the same as when I had only a 50 millisecond delay.

Try also tweeking the Baud rate to a much faster value. With all the serial.Print you do the buffer is likely filling and stopping your program.

Appreciate the reply.

This is a different approach I never would have thought of. I will try this and report findings. Thanks again.

Hello again,

So I changed the baud rate to a few different values, including the lowest value at 300. This did
Here are my findings for the changed baud rates of 2400, and 300. They seem to be the same results with level 1 on a curve. The original code had a pause of 12 seconds.
These changed baud rates brought level 1 down to an 8 second delay (improvement).

POT speed setting Range Pause
1 180 8
2 180 4
3 180 3
4 180 2
5 180 2
6 180 1
7-20 180 1 (or less than 1 sec pause observed)
(*hopefully this chart spacing translates with aligned margins. Previous posting of chart, changed font size and spacing so it did not appear to show data in a chart format)

My latest version of code has dropped the pause time, however I cannot understand what is causing this pause to begin with. The pauses only seem to show around POT selections between 1-8 (out of 20).

Here is the latest code I am at, which still has the unexpected pauses only on the lower POT settings (roughly 1-5).

//latest version 12/23/24

#include <Servo.h> 

int pos = 20;

int delayval = 0;
int dir = 1;

Servo aservo; 
Servo bservo; 
Servo cservo;
Servo dservo;
Servo eservo;  
Servo fservo;  

int apos=0; 
int bpos=0; 
int cpos=0;
int dpos=0;
int epos=0;   
int fpos=0;   
int strtPos=0;


void setup() { 
	
    pinMode(A0, INPUT);   // POT 
  
  	aservo.attach(12); 
	bservo.attach(11); 
	cservo.attach(10); 
  	dservo.attach(9);
    eservo.attach(8);
    fservo.attach(7);
  
  	apos = (0);
 	aservo.write(apos);
   	bpos = (0);
 	bservo.write(bpos);
   	cpos = (0);
 	cservo.write(cpos);
   	dpos = (0);
 	dservo.write(dpos);
      epos = (0);
 	eservo.write(0);
   	fpos = (0);
 	fservo.write(0);
  
  delay(100);
  
 	aservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES REGARDLESS OF 180, 360 INPUT
   	bservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	cservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	dservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	eservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
   	fservo.write(180);  //ONLY MOVES ABOUT 30 DEGREES
  
  delay(400);
    apos = (0);
 	aservo.write(apos);
  
 	bpos = (0);
 	bservo.write(bpos);
  
 	cpos = (0);
 	cservo.write(cpos);
  
 	dpos = (0);
 	dservo.write(dpos);
  
    epos = (0);
 	eservo.write(epos);
  
 	fpos = (0);
 	fservo.write(fpos);
  
  delay(200);
  
  	Serial.begin(9600);       // was set at 9600
  	Serial.print('\n');
  	Serial.print('\n');
  	Serial.print("Ardunio random servos controlled speed");
  	Serial.print('\n');
  	Serial.print('\n');
} 

void loop()
  { 
    int val = analogRead(A0);
    val= map(val,1,1023,1,21);
    Serial.print("     Speed set at ");
    Serial.print(val);
  
    int rand_num = random(1,7);
  	Serial.println('\n');
    Serial.print("random # is: ");
    Serial.print(rand_num);
    delay(200);
  
    if (rand_num==1)    
      { 
     	Serial.print(" Servo 1 selected ");
        delay(15);
    
    for (pos = 0; pos <= 360; pos +=val) 
      { 
        aservo.write(pos); 
        delay(val*2);
      }
    
    for (pos = 360; pos >= 0; pos -= val) 
      { 
        aservo.write(pos);             
        delay(50);                 
      }
      
    return;
  }
    
   if (rand_num==2)    
     { 
    	Serial.print(" Servo 2 selected ");
        delay(15);
       
     for (pos = 0; pos <= 360; pos +=val) 
       { 
          bservo.write(pos);     
        delay(val*2);
       }
     for (pos = 360; pos >= 0; pos -= val) 
      { 
        bservo.write(pos);    
        delay(50); 
      }
    return;
  } 
  
   if (rand_num==3)    
    { 
   	  Serial.print(" Servo 3 selected ");
      delay(15);
   
    for (pos = 0; pos <= 360; pos +=val) 
      { 
        cservo.write(pos);    
        delay(val*2);
      }
    for (pos = 360; pos >= 0; pos -= val) 
      { 
        cservo.write(pos); 
        delay(50);
      }
  
    return;
  }
    
  if (rand_num==4)    
    { 
       Serial.print(" Servo 4 selected ");
       delay(15);
       
      for (pos = 0; pos <= 360; pos +=val) 
        { 
          dservo.write(pos); 
        delay(val*2);
        }
     for (pos = 360; pos >= 0; pos -= val) 
       { 
          dservo.write(pos);              
          delay(50); 
       
       }
    
    return;
  }
     
  if (rand_num==5)    
    { 
      Serial.println(" Servo 5 selected ");
      delay(15);
      
     for (pos = 0; pos <= 360; pos +=val) 
       { 
         eservo.write(pos); 
        delay(val*2);
       }
     for (pos = 360; pos >= 0; pos -= val) 
       { 
         eservo.write(pos); 
         delay(50); 
       }
  
    return;
  }
  
  if (rand_num==6)    
    { 
      Serial.print(" Servo 6 selected ");
      delay(15);
         
      for (pos = 0; pos <= 360; pos +=val) 
        { 
          fservo.write(pos);    
        delay(val*2);
        }
      for (pos = 360; pos >= 0; pos -= val)
        { 
          fservo.write(pos);   
          delay(50);   
        }

    return;
  }
}   

I am not sure if seeing this simulation on Tinkercad.com will be of assistance.
The code and setup simulation is listed under title
"12/23/24 wrk random mvmnt 6 servos with speed controlled pot"

Thanks again for your time and input. I have learned a lot, and the feedback gets me challenging and approaching different considerations and changes.

so the chart keeps getting changed from the margins I make to align the data.
The "POT, speed setting, range, and pause" are all column headers for the data.
unfortunately the spacing squeezed them together looking like an incomplete and illogical sentence.
The data below those columns is also not showing alignment to those column headers.

I hope this helps you to go back and make sense of it.

Use the <CODE/> button to post your chart and the | symbol if needed:

POT speed setting | Range | Pause
1                 |  180  |   8
2                 |  180  |   4
3                 |  180  |   3
4                 |  180  |   2
5                 |  180  |   2
6                 |  180  |   1
7-20              |  180  |   1 (or less than 1 sec pause observed)

Servo position is limited to 0 - 180 (source code, lines 264-273):

void Servo::write(int value)
{
  if(value < MIN_PULSE_WIDTH)
  {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
    if(value < 0) value = 0;
    if(value > 180) value = 180;
    value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX());
  }
  this->writeMicroseconds(value);
}

Hello world,

Thank you again for the suggestions. Though I read through what I could on your source code reference of lines 264-273, I will be honest in saying that it did not make sense.
Either way, I added in the variables into the setup and replaced this code with the segment you selected above. I had an issue with the code line:

 this->writeMicroseconds(value);

So, I replaced the code line with

  dservo.write(value);

And adapted it for each servo it applied to.

This had an impact on the speed of the servo returning back to 0 position from 180. When I further tinkered with my program and took out the second section of my code (commanding the position to return from 180 to 0, nothing worked. Their were no errors in the code, but nothing moved. Checking the serial monitor, the code was selecting random servos and identifying the POT speed selection, but the simulator was not showing activity with the servo.
This could have been:

  1. because of my changed code from the "this" command
  2. I was not referencing or modifying this example code properly into my sketch

@elementalstimulation
You were told :-

But you seem to have done the opposite and used a much slower rate in your experiments. Why have you gone against the advice you have received?

A faster baud rate means a bigger number. Also the baud rate in your code must match the baud rate in the serial monitor. Change the baud rate of the serial monitor window with the drop down menu.

Hey Grumpy_Mike,

Thanks for your time and post. In previous response to recommended Baud rate change, I updated the results when I changed the rate to three different settings. Pauses still occurred. I believe I did post this response to that advice. It was good advice and opened up my thinking, but didn't solve the problem.

Keeping track of the changes and tweaks suggested, I defaulted back to the original code. I am also trying to make my own changes separately, and don't want to mix those changes up with this issue I am posting about (mainly the pause between each servo's movement, and return back to 0.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.