Fade a signal sending to ESC to achieve "smooth" signal changes - how to?

Hi.

I have an ESC connected to a pwm pin and i am using servo.h library.

The ESC input is controlled by a potentiometer. Now the ESC gets the value set up on the poti immediatley, but i want the ESC to get the changed signal of the poti with a fade, so that the signal generated by the poti and sent to the ESC ramps up in a specific time (up to the value that is defined by the current poti signal value).

I didnt find anything on the internet, maybe one of you know what kind of code snippet i can use?

Greetings Jim

What's the current code?
Don't forget to take advantage of the IDE's auto-format and copy to forums feature.

The idea is that instead of outputting the POT value directly to the PWM, It will use the POT value as the target value, manage the PWM output value separately, and gradually increase or decrease it toward the target value.

I have to add that i want to achieve this "fade" every time the signal from the poti is changed, not only once, so that every change of speed (signal to ESC) is smooth and not abrupt. So this needs to work with increasing as also decreasing values.


#include <Servo.h>
Servo ESC;     // create servo object to control the ESC
int pot1Value;  // value from the analog pin
void setup() {
  // Attach the ESC1 on pin 9, ESC2 on pin 10
  ESC.attach(9,1000,2000); // (pin, min pulse width, max pulse width in microseconds) 
   }
void loop() {
  pot1Value = analogRead(A0);   // reads the value of the potentiometer (value between 0 and 1023)
  pot1Value = map(pot1Value, 0, 1023, 0, 180);   // scale it to set max speed
  ESC.write(pot1Value);    // Send the signal of potvalue1 to ESC1
  }

Does it work with something like the following?

#include <Servo.h>
const unsigned int esc1pin = 9;
const unsigned int pot1pin = A0;
const unsigned int smoothFactor = 10; // increase for more smooth
Servo ESC1;
void setup() {
  ESC1.attach(esc1pin, 1000, 2000);
}
void loop() {
  static unsigned int esc1Value = 0;
  static unsigned int smoothCounter = 0;
  unsigned int pot1Value = map(analogRead(pot1pin), 0, 1023, 0, 180);
  if (++smoothCounter > smoothFactor)
  {
    smoothCounter = 0;
    if (esc1Value > pot1Value) esc1Value--;
    if (esc1Value < pot1Value) esc1Value++;
  }
  ESC1.write(esc1Value);
}

I don't have an ESC and a motor so I haven't tested it.
I think smoothFactor needs to be adjusted as you wish.

google

leaky integration

and poke around a bit.

The input is your potentiometer value, the output will be the value to send to the ESC which will eventually get to the input signal at a rate determined by the constants you can adjust.

I don’t know if you meant to ask or imply, but the ESC will not know about any of this, it just responds to the calculated value it is sent.

a7

Using servo.writeMicroseconds() (range: 1000 to 2000) instead of servo.write() (range: 0 to 180) you get more, and therefore smoother, control steps.

Using micros() for timing instead of a loop counter you get more accurate timing control and get to directly control the slew rate (how fast the control signal changes). I set it for 25% of full scale per second. That's four seconds from 0 to full speed. Pick a value from 1% (100 seconds full scale) to over 200% (half a second full scale).

#include <Servo.h>
const byte ESC1Pin = 9;
const byte Pot1Pin = A0;

const unsigned SlewRate = 25; // percent full scale per second

const unsigned long MicrosecondsFullScale = 100000000UL / SlewRate;
const unsigned StepsFullScale = 2000 - 1000; // Range is 1000 to 2000 microseconds
const unsigned long MicrosecondsPerStep = MicrosecondsFullScale / StepsFullScale;

Servo ESC1;

void setup()
{
  ESC1.attach(ESC1Pin, 1000, 2000);
}

void loop()
{
  static unsigned long LastMoveTime = 0;
  static unsigned int esc1Value = 0;
  
  unsigned long currentMicros = micros();

  unsigned int pot1Value = map(analogRead(Pot1Pin), 0, 1023, 1000, 2000);

  if (currentMicros - LastMoveTime > MicrosecondsPerStep)
  {
    LastMoveTime = currentMicros;
    if (esc1Value > pot1Value) esc1Value--;
    if (esc1Value < pot1Value) esc1Value++;
    ESC1.writeMicroseconds(esc1Value);
  }
}

Thanks for your replies.

Is this line correct?

    ESC1.writeMicroseconds(esc1Value);

shouldnt it be

ESC1.writeMicroseconds(pot1Value); ? 

If the line was correct where is the esc1value correlated to pot1Value? Idont see anything in the code.

Greetings Jim

There are two one-line if statements that either increment or decrement that value based on the pot reading.

Yes. If pot1Value was used in place of esc1Value, there would be absolutely no smoothing.

Why do the analogRead every loop if you are only using the value every MicrosecondsPerStep microseconds?

a7