Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: analogWrite() Max Value in Question

  1. #1
    Junior Member
    Join Date
    Oct 2014
    Posts
    5

    analogWrite() Max Value in Question

    From Teensyduino 1.19, file: pins_teensy.c

    Code:
    void analogWrite(uint8_t pin, int val) {
    	uint32_t cval, max;
    
    #if defined(__MK20DX256__)
    	if (pin == A14) {
    		uint8_t res = analog_write_res;
    		if (res < 12) {
    			val <<= 12 - res;
    		} else if (res > 12) {
    			val >>= res - 12;
    		}
    		analogWriteDAC0(val);
    		return;
    	}
    #endif
    
    	max = 1 << analog_write_res;
    	if (val <= 0) {
    		digitalWrite(pin, LOW);
    		pinMode(pin, OUTPUT);	// TODO: implement OUTPUT_LOW
    		return;
    	} else if (val >= max) {
    		digitalWrite(pin, HIGH);
    		pinMode(pin, OUTPUT);	// TODO: implement OUTPUT_HIGH
    		return;
    	}
    I believe the 'max' value for analogWrite is wrong. I believe it should be
    Code:
    max = (1 << analog_write_res)-1;
    At least this works better for me.

    Jeff

  2. #2
    Senior Member
    Join Date
    Nov 2012
    Location
    Boston, MA, USA
    Posts
    1,111
    Agreed, the minimum value is 0 and the max is 2^n - 1

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,821
    For PWM pins, 0 is fully off. 2^n - 1 is the max duty cycle (eg, on 255 out of 256 timer periods). 256 is fully on.

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Location
    Boston, MA, USA
    Posts
    1,111
    wow.
    pwm takes one of 257 values

  5. #5
    Junior Member
    Join Date
    Oct 2014
    Posts
    5
    Oh, I see your logic! I was just thinking of 8 bits being 0 to 255.

    Thanks,
    Jeff

    PS. I did notice that you mentioned "The value is between 0 to 255" on your web site.
    https://www.pjrc.com/teensy/td_pulse.html
    Last edited by JeffByrd; 10-20-2014 at 02:08 AM.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,821
    Quote Originally Posted by Nantonos View Post
    wow.
    pwm takes one of 257 values
    Yes. But if you prefer 256, you can just not use the last one.

    A couple years ago, I put some substantial time into testing against Arduino's implementation, to make sure the results are the same for 0 to 255.

  7. #7
    Senior Member
    Join Date
    Jun 2013
    Location
    Montréal
    Posts
    467
    ah, some of my led cicuits have their range inverted (0 is full on and 256 is off)
    I never understood when using a byte (rather than an int) my leds would'nt turn off completely at 255... Guess I have my answer now !

  8. #8
    Junior Member
    Join Date
    Oct 2014
    Posts
    5
    Quote Originally Posted by nlecaude View Post
    ah, some of my led cicuits have their range inverted (0 is full on and 256 is off)
    I never understood when using a byte (rather than an int) my leds would'nt turn off completely at 255... Guess I have my answer now !
    This is exactly what happened to me!
    It's works great now that I understand the logic.

    Jeff

  9. #9
    Member
    Join Date
    Oct 2014
    Location
    World
    Posts
    31
    Well, I need to go edit some code now!
    Code:
    int analogWriteMaxValue = ( pow( 2, analogWriteResValue) -1 )  //wrong
    int analogWriteMaxValue = pow( 2, analogWriteResValue)    //right!

  10. #10
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,679
    Quote Originally Posted by mcivan View Post
    Well, I need to go edit some code now!
    Code:
    int analogWriteMaxValue = ( pow( 2, analogWriteResValue) -1 )  //wrong
    int analogWriteMaxValue = pow( 2, analogWriteResValue)    //right!
    You really do not want to use pow to calculate 2**analogWriteResValue, because that converts everything to double precision floating point, which it then has to emulate in integer arithmetic. At the end, you would need to convert it back to integer. I'm guessing, but I would suspect that pow takes thousands if not tens of thousands of instructions to implement. Fortunately the chips are fast, but even so, you probably want to use the cpu for other things and/or read more analog values.

    What you want is to use is bit shifting. If you shift the value left n bits, it is the same as multiplying it by the appropriate power of 2. So you want to do:
    Code:
    int analogWriteMaxValue = 1 << analogWriteResValue;

  11. #11
    Member
    Join Date
    Oct 2014
    Location
    World
    Posts
    31
    Thanks for the tip Michael! I'm using this now! I'll have to read up more on bitwise in general!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •