Synchronising servo/actuator and LED

Hey guys,

These forums have been invaluable in my novice exploration of arduino so far but I’m having a bit of a sticking point with a project I’m working on and was wondering if I could get some pointers.

I’m currently using the code below to vary the position of a servo/linear actuator (a Frigelli L12-R -100mm- 50:1 gear ratio) and am trying to synchronise the brightness of some LEDs with the position of the servo/actuator, both controlled by a potentiometer. When the servo is at 0 the LEDs should also be 0, when the servo is at max (1025) the LEDs will be brightest (255).

The code is working great but the servo takes a good 6.5 seconds to fully extend whilst the LEDs can do so almost instantaneously. I’ve tried to add an average delay to the LEDs of 2 seconds but it means that they’re sluggish for small alterations and still a bit fast going straight to full extension. Is there a clever function I can use to get the LEDs to map the real position of the servo? Or some kind of variable delay to give to the LED’s?

#include <Servo.h>
Servo myServo;

int const potPin=A0;       //potentiometer pin
int potVal;                //read potentiometer
int angle;                 //read servo angle 
int LED;                   //read LED

void setup(){
  myServo.attach(9);      //attach servo to pin 9
  Serial.begin(9600);
  pinMode(11, OUTPUT);    //attach LED to pin 11
}
void loop() {
  potVal=analogRead(potPin);   //reads potentiometer
  Serial.print("potVal: ");    //shows potentiometer value on S monitor
  Serial.print(potVal);
  
  angle=map(potVal, 0, 1024, 5, 179);  //map 0-1025 value to servo
  myServo.write(angle);

  Serial.print(", angle: ");    //shows servo angle on S monitor
  Serial.println(angle);
  
  delay(2000);                  //delay for servo positioning
  
  LED=map(potVal, 0, 1024, 0, 255);  //map 0-1025 value to led
  analogWrite(11, LED);
}

Thanks on advance for any pointers!

R

Use the principle used in the Servo sweep example and increment the servo position and LED brightness in small increments by means of a for loop or by using millis() for interval timing.

ok thanks, that looks good. I'll give it a shot tomorrow.

R

hmmm, afraid I got stuck pretty quick with the For command. Is there a way to link two variables to the For line (LED and servo?) the looped code below completes one for cycle and then one increment of the next line. Google gave me no love and I tried two other variations of this code but couldn’t solve this fundamental issue.

void loop() {
  
for(angle = 0; angle < 180; angle += 1) // goes from 0 degrees to 180 degrees 
for (LED = 0; LED <255; LED += 1.4)        // goes from 0 brightness to 255 brightness
   {                               
    myServo.write(angle);              // tell servo to go to position in variable 'pos' 
    analogWrite(11,LED);
    delay(5);                       // waits 15ms for the servo to reach the position 
   }
  for(angle = 180; angle>=1; angle-= 1)     // goes from 180 degrees to 0 degrees 
  for (LED = 255; LED<=1; LED-= 1.4)        // goes from 255 brightness to 0 brightness
       {                          
    myServo.write(angle);              // tell servo to go to position in variable 'pos'
    analogWrite(11,LED);

    delay(5);                       // waits 15ms for the servo to reach the position 
  } 
}

Drop the for loop that runs through the LED brightness, just use the one that does angle and you can derive the PWM value for the LED from the angle. As a first test, just use angle itself as the PWM value. It won’t get to full brightness, but it should illustrate the principle.

Ok cool, I think part of the problem was my servo/actuator controls a 3D geometry which would be unresponsive in the upper and lower ranges of servo motion whilst my LEDs were still working. After adjusting for that, my LEDs fade throughout the 40-150 range, can I map them to their own 0-255 range whilst synchronising to the servo’s time? a bit like adding the +=1.4 modifier with the code above

working code below

void loop() {
  
for(angle = 40; angle < 150; angle += 1) // goes from 0 degrees to 180 degrees 
   {                               
    myServo.write(angle);              // tell servo to go to position in variable 'pos' 
    analogWrite(11, angle);
    delay(50);                       // waits 15ms for the servo to reach the position 
    
      Serial.print("angle: ");    //shows angle value on S monitor
  Serial.print(angle);
  Serial.println();
    
   }
  for(angle = 150; angle>=40; angle-= 1)     // goes from 180 degrees to 0 degrees 
       {                          
    myServo.write(angle);              // tell servo to go to position in variable 'pos'
     analogWrite(11, angle);
    
      Serial.print("angle: ");    //shows angle value on S monitor
  Serial.print(angle);
  Serial.println();

    delay(50);                       // waits 15ms for the servo to reach the position 
  } 
}
for(angle = 40; angle < 150; angle += 1) // goes from 0 degrees to 180 degrees 
   {                               
    myServo.write(angle);              // tell servo to go to position in variable 'pos' 
    analogWrite(11, angle);
    delay(50);                       // waits 15ms for the servo to reach the position

Whilst it makes no difference to the operation of the program it makes sense for the comments to match the code.

As to your question about the LED, do you want the LED brightness to go from 0 to 255 whilst the servo goes from 40 to 150 ? If so use the map() function to derive the LED value from the servo angle.

ledBrightness = map(angle, 40, 150, 0, 255);