analogWrite() PWM negative value

Hi,

I can't understand this code which sets the PWM value between -255 and 255 since PWM is only supposed to be of type int and only between 0 and 255. But somehow, this code below works to control the speed as well as the direction of rotation of the two DC motors on the robot, so how??

Declaration as global variables:

float pwm1 = 0, pwm2 = 0;

In a function which controls the speed and direction of the two DC motors.

 if(pwm2 >= 0)    
  {
    digitalWrite(left_L1, LOW);
    digitalWrite(left_L2, HIGH);
    analogWrite(PWM_L, pwm2);
  }
  else
  {
    digitalWrite(left_L1, HIGH);
    digitalWrite(left_L2, LOW);
    analogWrite(PWM_L, -pwm2);
  }

  if(pwm1 >= 0)
  {
    digitalWrite(right_R1, LOW);
    digitalWrite(right_R2, HIGH);
    analogWrite(PWM_R, pwm1);
  }
  else
  {
    digitalWrite(right_R1, HIGH);
    digitalWrite(right_R2, LOW);
    analogWrite(PWM_R, -pwm1);
  }

I did research to try to understand this code and why it works with the negative PWM values. I only found this: https://www.arduino.cc/en/Tutorial/PWM and it states that the value of PWM can only be of data type int and that it has to be between 0 and 255.

Can someone please explain this strange phenomena?

 analogWrite(PWM_L, -pwm2);

There's a clue there, though I don't know why they chose to use "float" - "int" would've worked just as well.

But my confusion is that the Arduino analogWrite function is not supposed to even be able to accept negative values?? Is that a secret of the analogWrite? Since it has not been mentioned anywhere, not even in the official documentation.

It isn't accepting a negative value - look carefully.

if(pwm2 >= 0)   
  {
    digitalWrite(left_L1, LOW);  
    digitalWrite(left_L2, HIGH);
    analogWrite(PWM_L, pwm2);
  }
  else
  {
    digitalWrite(left_L1, HIGH);
    digitalWrite(left_L2, LOW);
    analogWrite(PWM_L, -pwm2);
  }

If the calculated PWM value is positive, set the direction to, say clockwise, and send the value to the motor.
If the calculated PWM value is negfative, set the direction to, say counter clock wise, invert the sign of the PWM value (-pwm2) and send the (positive now) value to the motor.

groundFungus:
If the calculated PWM value is positive, set the direction to, say clockwise, and send the value to the motor.
If the calculated PWM value is negfative, set the direction to, say counter clock wise, invert the sign of the PWM value (-pwm2) and send the (positive now) value to the motor.

Ah, it makes sense now! :o That's quite an ingenious way of controlling the direction of the motor.

I have also been wondering about this: if the PWM is a float type, does this mean that the value of the PWM sent is actually a float type or is it automatically converted to an int type? That's because until now, i have not encountered any PWM values which are not int, so decimal numbers seem wrong??
But, if the PWM value is allowed to be a float type, that would mean that the duty cycle can be a float percentage, like 52.789 or 12.632? Until now, i have only seen whole numbers.

analogWrite accepts only "int" parameters - there are no overloads.
The compiler knows this, so converts whatever the user tries to pass to an "int".

AWOL:
analogWrite accepts only "int" parameters - there are no overloads.
The compiler knows this, so converts whatever the user tries to pass to an "int".

It cleared my doubts. Thanks! :slight_smile:

It cleared my doubts

OK let’s put a stop to that then.

Only the least significant 8 bits of the value you pass to analogWrite are used. So if you give it 257 it is the same as giving it 257-256 = 1. and give it 258 is he same as giving it 2 and so on until 511. This cycle repeats every 256 numbers. This is because all numbers are in binary. Even negative numbers will produce values in the PWM, these will not be negative values but what ever the least significant 8 bits of the two’s complement of that number is.

Grumpy_Mike:
Only the least significant 8 bits of the value you pass to analogWrite are used. So if you give it 257 it is the same as giving it 257-256 = 1. and give it 258 is he same as giving it 2 and so on until 511. This cycle repeats every 256 numbers. This is because all numbers are in binary. Even negative numbers will produce values in the PWM, these will not be negative values but what ever the least significant 8 bits of the two’s complement of that number is.

That was very enlightening. I will implement constrain() on the PWM values before they are sent to the analogWrite. :slight_smile: Thank you!