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

Thread: Teensy4 with different analogWriteResolution settings on each pin

  1. #1

    Teensy4 with different analogWriteResolution settings on each pin

    Presently analogWriteResolution is a global setting. Is this necessarily so, or can settings be made to get different resolution settings on different pins?

    The use case is that Teensy4 enables PFM at ultrasonic frequencies ie 40khz. This center frequency requires resolution to be set to 11 bits. At this resolution, there is poor behavior attempting to generate lower frequencies with other pins. Is there a work around?

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,422
    I believe it is global but is easy to change.

    That is if you only need it for a specific pin or pins, you can probably do something like:
    Code:
    uint32_t previous_analog_res = analogWriteRes(11);  // Set resolution 11 which returns what the previous value was.
    analogWrite(pin, my_11_bit_value);
    analogWriteRes(previous_analog_res);
    Why I think this might work: The code does:
    Code:
    uint32_t analogWriteRes(uint32_t bits)
    {
    	uint32_t prior;
    	if (bits < 1) {
    		bits = 1;
    	} else if (bits > 16) {
    		bits = 16;
    	}
    	prior = analog_write_res;
    	analog_write_res = bits;
    	return prior;
    }
    is in the two places that set up the new anlogWriteRes

    Code:
    void flexpwmWrite(IMXRT_FLEXPWM_t *p, unsigned int submodule, uint8_t channel, uint16_t val)
    {
    	uint16_t mask = 1 << submodule;
    	uint32_t modulo = p->SM[submodule].VAL1;
    	uint32_t cval = ((uint32_t)val * (modulo + 1)) >> analog_write_res;
    	if (cval > modulo) cval = modulo; // TODO: is this check correct?
    ...
    Code:
    void quadtimerWrite(IMXRT_TMR_t *p, unsigned int submodule, uint16_t val)
    {
    	uint32_t modulo = 65537 - p->CH[submodule].LOAD + p->CH[submodule].CMPLD1;
    	uint32_t high = ((uint32_t)val * (modulo - 1)) >> analog_write_res;
    	if (high >= modulo - 1) high = modulo - 2;
    And these two functions are the ones that are called by analogWrite depending on if it is a FlexPWM timer or a Quad Timer that is doing the PWM on that pin

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,467
    It returns the prior setting, so you can use it to change the resolution, do an analogWrite(), and then put the setting back as it was so other parts of your program or other libraries work as normal.

    For example:
    Code:
      uint32_t prior = analogWriteResolition(12);
      analogWrite(3, 3831);
      analogWriteResolition(prior);

  4. #4
    Junior Member
    Join Date
    Mar 2020
    Posts
    10
    Teensy 4.0 PWM is extremely impressive!
    I need 17 bits minimum resolution. (1 part in 100k)
    Is there a limit of 15 or 16 bits if one is willing to have a lower PWM ideal frequency?
    It is 4577.64 Hz for 15 bit resolution, so 17 bits would be 1144.41 Hz, quite acceptable for my app.
    Will this work? If not, can one use a timer interrupt routine with frequency of 1MHz or 200khz if necessary?
    600 mhz machine should enable a lot in this regard.

    PJRC doc seems to indicate that 16 bit resolution is possible only for 180 and 120 Mhz chips.
    Is it possible to get 16 bit PWM from a 600 Mhz chip?

    Thank you. (I can make this a new post if advised)

    UPDATE - I found the PWM section in the Teensy 4.0 chip manual download ( IMXRT1060RM_rev2.pdf ).
    Since all compare registers are 16 bit, 16-bits is the maximum precision without advanced jumping through hoops.
    Last edited by Yochanon; 08-09-2020 at 02:52 AM.

Posting Permissions

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