Pow function for pwm output control exponentially

Hello,
I need to control the pwm output of an arduino nano, in my project that I am working on. I want to control it exponentially.

Will the pow function do the job, or there is a simple way for controlling the out pwm exponentially?

Thanks!

A bit shift will do something similar and takes far less computation time.
'<<'

1 Like

what @build_1971 is suggesting will be to base 2.

still will be give you and exponential function, but question is to what base you want/need it to be (ie to what formulae are you working from?)

Hello all,
I just sample the input voltage and based on that I do map, and calculate the pwm, proportionally. The problem is that using this way, the controller is doing very shapr and fast. That is why i want to have the posibiloty to work and tune the exponential rise/control of the pwm output.

Are there any exmples with shifting method??

Thanks!

pow(2,3) is equivalent to
1 << 3

if you don't want to do a simple 1 2 4 8 16 32 64 128 255 which is an exponential growth for the PWM (the last one being capped at 255 instead of 256) then you need to define more finely the shape of the "exponential" curve

may be this discussion on Interpolation functions can help ?


SIGMOID

1 Like
int linearValue = analogRead(A0); // Read a linear input (0-1023) from A0
int exponent = linearValue / 256; // Adjust the divisor as needed
int exponentialValue = 1 << exponent; // Calculate an exponential output

analogWrite(9, exponentialValue); // Output the exponential value to PWM pin 9

I found this snipet. Is it similar to the above expression?

Yes similar.
Try and see if it fits your needs.

it's different (your variable evolves slowly, not faster and faster)

what it does is as follow:

  • read the value of the potentiometer (likely) an get a 10 bit value (0 to 1023)
  • divide by 256, which is basically the same as shifting 8 bits (256 = 28) right, so you keep only the 2 most significant bits of your potentiometer's value.
  • use that to set the PMW on pin 9

what you get for PWM is this

if linearValue was in [0, 255] ➜ exponentialValue = 0
if linearValue was in [256, 511] ➜ exponentialValue = 1
if linearValue was in [512, 767] ➜ exponentialValue = 2
if linearValue was in [768, 1023] ➜ exponentialValue = 3

EDIT= I meant exponent not exponentialValue

then the code will simply not work, as pwm value of 1, 2, or 3 is nothing.
I just use proportional block, that calculates PWM based on the input change. In some cases, when the input change is big, for example the voltage rises from 100V up to 150, the MAP functions calculates the new value, for example if the older was 100 discretes, the new wan is 200. and the pwm acts as a relay, instead of smoothing integral part.

I Can use increment of +1 at every cycle, but it will be slow, as well.

That is why my idea is to try to exponentially control the output pwm, and control the speed of rising or falling of the PWM output.

will try with pow function also.

Thanks!

what's driving the change of PWM value? A human movement on some sort of joystick or turning a rotary encoder or is it something process driven?

ADC input value, from 0-1023 in this case. So there is a map function to turn this range in PWM discretes from 0 up to 255. As the input can vary in steps, the pwm should follow the change exponentialy.

so you want to monitor the acceleration of the change in the ADC input to change the PWM value ?

(if the PWM stable if the ADC input is stable ?)

The result will be 2^0, 2^1, 2^2, 2^3.
So, you should not divide by 256, but by 128.
Then you will have a much wider range (until 2^7=128).
Which is often sufficiently bright.

I cannot see your point!
Can you please post a scetch to get your idea, and understad you better?

Thanks

indeed exponent will be 0, 1, 2 or 3 so exponentialValue will be 1, 2, 4 or 8

he meant

int linearValue = analogRead(A0); // Read a linear input (0-1023) from A0
int exponent = linearValue >> 7; // divide by 128 (Adjust the divisor as needed)
int exponentialValue = 1 << exponent; // Calculate an exponential output

analogWrite(9, exponentialValue); // Output the exponential value to PWM pin 9

now exponent will be 0, 1, 2, 3, 4, 5, 6 and 7

1 Like
int pwmPin = 9;  // Replace with your PWM pin number
int currentDutyCycle = 50;
int targetDutyCycle = 131;
unsigned long duration = 1000;   
unsigned long startTime = millis();
int tolerance = 2;   

void setup() {
  // Initialize the PWM pin
  pinMode(pwmPin, OUTPUT);
}

void loop() {
  unsigned long elapsedTime = millis() - startTime;

  if (currentDutyCycle < targetDutyCycle) {
    // Calculate the new duty cycle exponentially
    float t = (float)elapsedTime / duration;
    int pwm = currentDutyCycle + (targetDutyCycle - currentDutyCycle) * (1.0 - exp(-t));

 
    if (pwm > targetDutyCycle) {
      pwm = targetDutyCycle;
    }

     
    if (abs(pwm - targetDutyCycle) <= tolerance) {
      pwm = targetDutyCycle;
    }

 
    analogWrite(pwmPin, pwm);

    // Update the current duty cycle for the next cycle
    currentDutyCycle = pwm;
  } else {
  
  }

  // Delay for a short time to control the update rate
  delay(10);  // Adjust the delay as needed
}

Something like this can be, I will try to simulate it and test it, to see if it works. Currently only for increasing of the PWM.

don't forget to update startTime otherwise you measure the elapsedTime since the last reboot of your arduino

Thanks, good point!

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