I trying to create a piece of code which will ramp up the motors speed to a changing value controlled by a joystick. For example joystick requests 120 speed to motors so instead of going 0 to 120 it goes 0, 10, 20 …. 120. But the maximum value will constantly change between 0-130 so it needs to ramp up each time. This is a snippet of my code to run the motors in the forwards direction.

  motorControl = analogRead(joystick);
  motorControl = motorControl / 4;
  if(motorControl > 129)


    digitalWrite(pwm2, 0);
    digitalWrite(pwm3, 0);
    speedI = (motorControl - 130);
    speedFadeI = 
    analogWrite(pwm1, (speedFadeI - 130));
    analogWrite(pwm4, (speedFadeI - 130));

thank you for anyone who has a idea

  • 2
    do you have a question? – jsotola Mar 28 '19 at 16:23

I assume from the 0, 10, 20 …. 120 series, that you want to have a linear ramp to the desired speed. This can be done really easily, if your requirements are not to high.

First we define the interval, in which we want to update the speed, and a constant acceleration, that you can choose. The current speed will be saved in a global variable.

#define INTERVAL        100
#define ACCELERATION    51
int current_speed = 0;

I chose an interval of 100ms and the acceleration value, so that it will ramp from 0 to 255 (full speed) in 5s (which results in 51 PWM values per second). Now, in the void loop() function, we use an if-statement with the millis() function to trigger an speed update at the regular interval. For this to work, we need a (here global) variable, that holds a timestamp. (If you don't know this technique, you can see it in the BlinkWithoutDelay example, that comes with the Arduino IDE, and there are many tutorials about this on the web)

Inside the if-statement, we write a second if-statement. It checks, if the current speed is above or below the set point, that comes from the joystick. If it's above, we will substract one speed step (calculated by acceration and interval and divided by 1000, because we used milliseconds and not seconds for the interval), if it's below we will add one speed step.

unsigned long timestamp = 0;

void loop(){
    int setpoint = analogRead(joystick)/4;
    if(millis() - timestamp > INTERVAL){
        if(current_speed > setpoint){
            current_speed -= ACCELERATION*INTERVAL/1000;
        } else {
            current_speed += ACCELERATION*INTERVAL/1000;
        if(current_speed > 255) current_speed = 255;
        else if(current_speed < 0) current_speed = 0;
        analogWrite(pwm1, current_speed);
        timestamp += INTERVAL;

I also added if-statements to cap the current speed between 0 and 255. Otherwise the value would overflow, when written to the corresponding 8-bit timer register by the analogWrite() function.

Of course, this method also has drawbacks. You will have to find a good value combination of ACCELERATION and INTERVAL, because when the current speed reaches the setpoint, it will oscillate around this value. The best way is to set the ACCELERATION, that you need, and choose a good interval based on that.

There are other ways to program this, but I like this way for being really simple.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.