New user trying to use servos with a wave like pattern

Hi,

I have designed and printed some boxes in CAD software that hold micro servos. Right now I have this code that beautifully overlaps a sine wave movement. I was hoping I could stop the movement at 90 degrees where i'm able to hold it there for a set amount of time where it then afterwards returns back 90 degrees to the original position where it can also be held for a set amount of time. Right now it is just looping back and forth.

Thank you!

Jason

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
int servomin = 320;  //150
int servomax = 550;  //600
void setup() {
  Serial.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(60);
}


void loop() {
  oneCycle();
}


void oneCycle() {
  for (int degrees = 0; degrees < 360; degrees++) {
    float radians = (degrees * M_PI) / 180.0;
    for (int servo = 0; servo < 3; servo++) {
      // Map the sin() function to the servomin..servomax range
      int position = (sin(radians) + 1) * ((servomax - servomin) / 2) + servomin;
      pwm.setPWM(servo, 0, position);
      radians += (4.0 * M_PI) / 16.0;  // Advance 1/16th of a circle
    }
    delay(10);  //  3600 milliseconds per cycle
  }
}

Hi Jason

That's sounds possible. Do you have a question for the forum?

I’m curious to know ifI can I stop the servos motion halfway through its routine and what code might help me accomplish this action

Ok, as I already said, it sounds possible.

Are you asking the forum to write the code for you?

Read this tutorial it will show you how to pause actions
https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay

Modify oneCycke() so it only goes half way.

Rename it, like goUp().

Copy the original oneCycke() and rename it goDown(), edit goDown() so it does the other half.

In the loop, call goUp(), delay with delay() for a bit, then call goDown() and delay again.

a7

Hey,

Thanks for this! I've tried so many variations of this while doing basic tutorials and I'm not sure I'm on the right track. I'm just getting different waves but the action isn't stopping. I'm pretty lost, I'm so new to this that I feel like I'm terrible at even describing my issue.

Until what makes it go again? I thought you said for awhile, as in stop for some time.

a7

I’ve tried uploading a video here twice but strangely the forum doesn’t allow for the iPhone video codec

Right I just want it to
-be still for maybe one minute or so
-gradually turn all the servos 90 degrees
-be still for another minute or so
-gradually turn back
-loop

Sounds kind of like a problem I had with a set of fading RGB LED's. I had two knobs, one to control brightness, and one to control the rate of change. If I used delay() it would usually stutter and then kick up or down a large amount. Not visually appealing.

I'll have to look for the code, but if I remember correctly I set up three nominal curves that would increment using the milli function. The upper and lower bounds of each of the three would then map to min and max functions based on the brightness and change speed desired.

You might be able to do this with two nominal curves, mapped to speed and step length if required. Take the curves position and do some math for the position of each foot so that each one gets it's position from the one curve. If the curve changes based on speed or stroke length, the curve will remap and all positions will update automatically keeping synch.

That sounds promising, let me know if you find it!

Thank you!

I believe this was the working version. It was written 7 years ago and I was still learning to program so it has some odd things going on, but hopefully the idea works.

int LoopCount = 0;      // Creates a mini loop for analog reads for performance reasons
int sensorValueA0;      // A0 sensor value
int sensorValueA1;      // A1 sensor value

int Led9 = 9;           // Led9 (Red*) operating PWM digital pin 9
int Led10 = 10;         // Led10 (Green*) operating PWM digital pin 10
int Led11 = 11;         // Led11 (Blue*) operating PWM digital pin 11

int brightness9 = 0;   // Initial brightness
int brightness10 = 0;
int brightness11 = 0;

int fadeamount = 1;     // How much to fade up/down per loop

int Maxbrightness9 = 0;     // Maximum brightness
int Maxbrightness10 = 0;    // This value is mapped to the current main loop value
int Maxbrightness11 = 0;    // So that the main loop value doesn't get changed and stays stable

int TimerDelay1 = 0;    // Used to create a pause between loops instead of using delay
                        // Delay can be used, but during long durations the program
                        // can become unresponsive and the light jitters
int TimerDelay2 = 0;    // Used to pause the fade at max brightness
int RunOnce = 1;        // At startup runs the first if statement to 'prime' the program
int HighPause;

int RunZeroLoop = 1;    // controls which statement to run
int RunFirstLoop = 0;
int RunSecondLoop = 0;
int RunThirdLoop = 0;
int RunFourthLoop = 0;
int RunFifthLoop = 0;
int RunSixthLoop = 0;
int RunSeventhLoop = 0;
int RunEighthLoop = 0;

// Program Setup. Runs once
// pinmode not required when using PWM
void setup() {
}

// Looping Routine. Runs forever
void loop() {

  // Checks for first Loop
  // Used to control fade transition speed
  // Could be mapped to adjust for different pots or duration likeness
  if (LoopCount == 0) {
  // sensorValueA0 = analogRead(A0);
  // sensorValueA0 = map(sensorValueA0, 0, 1023, 1023, 0);
  sensorValueA0 = 1023;
  }

  // Checks for second (tenth) loop
  // Additional loops between reads for better performance
  // Sensor value won't populate until tenth cycle so a startup value is specified
  // Controls maximum brightness by limiting PWM value
  if (RunOnce == 1) sensorValueA1 = 10;
  //if (LoopCount == 10) sensorValueA1 = map(analogRead(A1), 0, 1023, 255, 0);
  sensorValueA1 = 255;

  // Increases loop counter
  LoopCount = LoopCount + 1;
  
  // Resets loop counter
  if (LoopCount == 19) LoopCount = 0;

  TimerDelay1 = TimerDelay1 + 1;
  if (RunOnce == 1) TimerDelay1 = 1024; // Forced to enter loop on first run
  if (TimerDelay1 > sensorValueA0) {    // Loop only runs when TimerDelay is greater 
    // than the sensor value

    TimerDelay1 = 0;

    RunOnce = 0;      

    // *
    // PinX as a color is only to differntiate the pins,
    // not an actual color correspondency

    //Fade into Pin9 only & hold for a moment - Red at full
    //Run once
    if (RunZeroLoop == 1) {
      b9Plus();
      ReadWrite9();
      if (brightness9 == 255) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0;
          RunZeroLoop = 0;
          RunFirstLoop = 1;
        }
      }
    }

    //Fade Pin10 in fully & hold for a moment - Red/Green at full
    if (RunFirstLoop == 1) {
      b10Plus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness10 == 255) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0;
          RunFirstLoop = 0;
          RunSecondLoop = 1;
        }        
      }
    }

    //Fade out Pin9 & hold for a moment - Green at full
    if (RunSecondLoop == 1) {
      b9Minus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness9 == 0) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0;        
          RunSecondLoop = 0;
          RunThirdLoop = 1;
        }              
      }
    }    

    //Fade in Pin11 & hold for a moment - Green/Blue at full
    if (RunThirdLoop == 1) {
      b11Plus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness11 == 255) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0;           
          RunThirdLoop = 0;
          RunFourthLoop = 1;
        }
      }
    }    

    //Fade out Pin10 & hold for a moment - Blue at full
    if (RunFourthLoop == 1) {
      b10Minus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness10 == 0) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0; 
          RunFourthLoop = 0;
          RunFifthLoop = 1;
        }
      }
    }    

    //Fade in Pin9 & hold for a moment - Blue/Red at full
    if (RunFifthLoop == 1) {
      b9Plus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness9 == 255) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0; 
          RunFifthLoop = 0;
          RunSixthLoop = 1;
        }
      }
    }    

    //Fade in Pin10 & hold for a moment - Red/Blue/Green at full
    if (RunSixthLoop == 1) {
      b10Plus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness10 == 255) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0;
          RunSixthLoop = 0;
          RunSeventhLoop = 1;
        }
      }
    }    

    //Fade out Pin10,Pin11 & hold for a moment - Red at full
    if (RunSeventhLoop == 1) {
      b10Minus();
      b11Minus();
      ReadWrite9();
      ReadWrite10();
      ReadWrite11();
      if (brightness10 == 0) {
        TimerDelay2 = TimerDelay2 + 1;
        HighPause = sensorValueA1 / 3;
        if (TimerDelay2 >= HighPause) {
          TimerDelay2 = 0;
          RunSeventhLoop = 0;
          RunFirstLoop = 1;
        }
      }
    }     

  }
  
}

// Controls whether pin value increases or decreases
// *************************************************  
  void b9Plus() {
    brightness9 = brightness9 + fadeamount;
    brightness9 = constrain(brightness9, 0, 255);
  }
  
  void b9Minus() {
    brightness9 = brightness9 - fadeamount;
    brightness9 = constrain(brightness9, 0, 255);
  }
  
  void b10Plus() {
    brightness10 = brightness10 + fadeamount;
    brightness10 = constrain(brightness10, 0, 255);
  }
  
  void b10Minus() {
    brightness10 = brightness10 - fadeamount;
    brightness10 = constrain(brightness10, 0, 255);
  }
  
  void b11Plus() {
    brightness11 = brightness11 + fadeamount;
    brightness11 = constrain(brightness11, 0, 255);
  }
  
  void b11Minus() {
    brightness11 = brightness11 + fadeamount;
    brightness11 = constrain(brightness11, 0, 255);
  }
// *************************************************
// *************************************************


// Maps brightness value and sends value to pin
// ++++++++++++++++++++++++++++++++++++++++++++

  void ReadWrite9() {
    Maxbrightness9 = map(brightness9, 0, 255, 0, sensorValueA1);
    analogWrite(Led9, Maxbrightness9);
  }
  
  void ReadWrite10() {
    Maxbrightness10 = map(brightness10, 0, 255, 0, sensorValueA1);
    analogWrite(Led10, Maxbrightness10);
  }
  
  void ReadWrite11() {
    Maxbrightness11 = map(brightness11, 0, 255, 0, sensorValueA1);
    analogWrite(Led11, Maxbrightness11);
  }

// ++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++

If you're using an ESP32, then this could help. Try the servo easing simulation.

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