0

My Arduino motor speed controller setup

I am using the potentiometer to control the duty cycle of a PWM signal to the MOSFET trigger switch module, thus controlling the motor speed.

In my code, I have used the map function to utilize the full resolution of my potentiometer (0 - 1023) and thus create a proportional PWM signal using analogWrite function (0 - 255).

However, in my setup I want to limit the speed of the motor from going beyond a MAX_RPM value, despite any further increase in analog value input from the potentiometer.

This means I have to continously check the RPM value (the RPM code works fine, so I will not include it).

If the motor speed hits the MAX_RPM value, any further potentiometer input should be ignored. To achieve this, I figured I need to hold the analogWrite function value constant thus holding the speed constant.

In the event that I turn the potentiometer in the reverse direction, this should decrease the PWM value thus also decreasing the speed.

I have written the code to achieve the process described above to no avail i.e., increasing potentiometer input causes the speed to go beyond the MAX_RPM value which is undesired.

In this project, I am developing a rev limiter of sorts.

Please help me figure out the problem in my code.

#define MAX_RPM 500
    #define MAX_RPM_PWM_MAPPED_VALUE 15
    
    //In this case, I first ran the motor while monitoring the speed and the potentiometer value
    //While doing this, I noted the potentiometer value at which the MAX_RPM is obtained
    //I then defined this potentiometer value as MAX_RPM_PWM_MAPPED_VALUE
    //With MAX_RPM_PWM_MAPPED_VALUE, I would directly limit the value written to the analogWrite function
    // 
    
    MOSFETMODULE = 4;
    potentiometer = AO;
    
    void setup()
    {
        pinMode(MOSFETMODULE, OUTPUT);
    }
    
    void loop()
    {
        val = analogRead(potentiometer);  //Read potentiometer value - represents accelerator input
        mappedValue = map(val, 0, 1023, 0, 255); //Map the 10 bit value to 8 bit equivalent
        
        if(RPM >= MAX_RPM)
        {
            analogWrite(MOSFETMODULE, MAX_RPM_PWM_MAPPED_VALUE);
        }
            else
            {
              mappedValue = constrain(mappedValue, 0, MAX_RPM_PWM_MAPPED_VALUE);
              analogWrite(MOSFETMODULE, mappedValue); //Output a PWM signal to the MOSFET trigger module
            }
    }
5
  • Note the the actual RPM doesn't just depend on the PWM duty cycle, but also the load on the motor. Just like pressing the gas pedal on a car. If you don't change the gas pedal position, but you suddenly go up a hill, your speed will decrease.
    – Gerben
    Feb 19, 2021 at 15:03
  • Thanks, I totally understand the loading scenario. In fact, my setup aims to mimic a car operation - throttle position and engine speed. I aim to create a device that restricts the motor speed from exceeding various max speed levels depending on the load condition.
    – Curiousone
    Feb 19, 2021 at 15:31
  • Try using analogWrite(MOSFETMODULE, 0); when the RPM exceeds the maximum value. Of maybe use 1 instead of 0. That way the code will throttle way back, if the RPM ever exceeds it's maximum. If will return to using the pot value, when the RPM goes back down. It may result in some weird oscillations, but cars make some weird noises too, when they are at their max RPM, so +1 for realism.
    – Gerben
    Feb 19, 2021 at 16:29
  • To clarify why your code isn't working. Currently, it's mapping the value of the pot (0-1023) to the 0-15 PWM duty cycle. But when the RPM exceeds it's limit you set the PWM to 15, which is the same value you get when you turn the pot to it's maximum. You want to turn down the PWM duty cycle, instead of setting it to it's max. (Imagine going down hill in a car. You don't press the throttle, but due to going downhill the RPM exceeds 500. Now your car will set it's throttle to full. Oops ;-p )
    – Gerben
    Feb 19, 2021 at 16:34
  • I agree with both responses, they totally make sense. Lemme try to implement them in my code. This problem makes me think deeply about how electronic throttles work in modern cards. Thank you.
    – Curiousone
    Feb 19, 2021 at 21:48

1 Answer 1

1

Your problem is that you don't know what ADC value maps to the maximum RPM. If you did you wouldn't need to know the RPM.

What you have here is a "feedback loop", and what you need is some method of using the detected RPM to control the speed of the motor.

You need to decouple the potentiometer from the analogWrite completely - the potentiometer should be setting the desired RPM, not the value being sent to set the RPM.

So if you want an RPM range from, say, 0 to 100RPM you can map() the analogRead() to the values 0-100. Then you can examine the actual RPM and adjust the value you send to the PWM accordingly - if the motor is too fast then slow it down. If it's too slow then speed it up.

There's a special method that is used for this: PID. And there's a library that does it for you too:

The potentiometer provides the "set point", the RPM detection provides the "input", and the PID library gives you the "output" to feed to the analogWrite(). You need to then provide the special magic "tuning" parameters to give the best control over your motor.

3
  • Thank you for the detailed response. In this setup, I am aiming to mimic a car driving scenario, whereby the potentiometer is the gas pedal, while the MOSFET reps the fuel injector, and the motor speed reps engine speed. In essence, I wanted a setup that would restrict the motor/engine speed from exceeding a certain point i.e., the MAX RPM, regardless of an increasing input rather than holding the speed constant. As the pot is reversed/pedal released, I also want the motor/engine speed to drop appropriately. I just want to set an engine speed limit. A PID holds a constant speed value instead.
    – Curiousone
    Feb 19, 2021 at 15:28
  • am trying to develop a rev limiter of sorts
    – Curiousone
    Feb 19, 2021 at 15:49
  • @Curiousone maybe something like if (rpm>max) analogWrite(mosfet, PID_output); else analogWrite(mosfet, analogRead(pot_pin)>>2) could work
    – Sim Son
    Feb 20, 2021 at 18:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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