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

Thread: Perhaps a silly question: analogWriteResolution and Teensy 3.1 DAC/PWM

  1. #1
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,600

    Perhaps a silly question: analogWriteResolution and Teensy 3.1 DAC/PWM

    As I understand the documentation here, analogWriteResolution(nBits) is a rather global setting. Now, if I want to use 12bit resolution on pin A14 (Teensy 3.1 DAC), but 16bit resolution for PWM on a Timer0 pin (i.e. pin5) and 10bit resolution for PWM on a Timer1 pin (i.e. pin 3), how do I proceed?

  2. #2
    Senior Member
    Join Date
    Feb 2013
    Posts
    563
    Quote Originally Posted by Theremingenieur View Post
    As I understand the documentation here, analogWriteResolution(nBits) is a rather global setting. Now, if I want to use 12bit resolution on pin A14 (Teensy 3.1 DAC), but 16bit resolution for PWM on a Timer0 pin (i.e. pin5) and 10bit resolution for PWM on a Timer1 pin (i.e. pin 3), how do I proceed?
    i never use the PWM stuff but looks as if you could simply hardcode it into the analogWrite() function:

    ie https://github.com/PaulStoffregen/co...teensy.c/#L407

  3. #3
    Senior Member
    Join Date
    Nov 2012
    Location
    Boston, MA, USA
    Posts
    1,113
    I wasn't aware analogWriteResolution applied to PWM. Despite the silly name, PWM is not analog so the fact that the same call is used to write PWM and to write Analog is a historical curiousity.

  4. #4
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    There is a Digital to analog converter (DAC) in the T3.1.
    And some apps and libraries for it.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    25,092
    If you look at the analogWrite code, or the PWM documentation, you'll see the code is scaling the resolution you choose to the actual timer numerical range. In the "PWM Resolution" section, there's a list of frequencies that give the timer an exact power-of-2 range.

    If you want 16 bits of actual resolution, not only do you need to use analogWriteResolution(16), but you should also make sure you're using a PWM frequency that really does give 16 bits. When F_BUS is 48 MHz, that's 732 Hz.

    It's easy to scale 10 or 12 bits up to a 16 bit number by left shifting.

  6. #6
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,600
    Thanks for all the replies. I wanted to use different resolutions on different PWM pins in order to have also different speed. The link towards pins_teensy.c is extremely helpful, because it allows to understand what happens behind. It's really a pity (at least for teensy beginners as I am one) that there is not a systematic WIKI with an exhaustive and systematic function and object documentation for developers using teensyduino, similar to the arduino reference page.

  7. #7
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,600
    I think I started to sort it out and thus to solve it. I created a DAC class which is fully independent of any analogWrite settings. This gives me the freedom to work on PWM with different frequencies and resolutions later.

    My goal was to do as many of the needed calculations and settings as possible during the class initialization to speed up the write procedure compared to the analogWriteDAC0() function in analog.c

    This DAC class is initialized with a pointer to the signal and updates the output value every time the method action() is called from the signal generating object.

    In the .h file:
    Code:
    #define dVoxDacRes 12
    #define dVoxSigRes 16
    
    class dVoxDAC {
    public:
      dVoxDAC(int32_t *signalBus = NULL);
      void action();
    private:
      int32_t *_signalBus;
      const uint16_t _ofs = 1 << (dVoxDacRes - 1);
      const uint16_t _max = (1 << dVoxDacRes) - 1;
      const uint16_t _min = 0;
      const int8_t _shift = dVoxSigRes - dVoxDacRes;
    };
    In the .cpp file:
    Code:
    dVoxDAC::dVoxDAC(int32_t *signalBus) {
      /* Hardware configuration 
       ** sets reference to DACREF_2 = 3.3V VDDA */
      SIM_SCGC2 |= SIM_SCGC2_DAC0;
      DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS;
      /* Connect */
      _signalBus = signalBus;
    }
    
    void dVoxDAC::action() {
      if (_signalBus != NULL)
        *(int16_t *)&(DAC0_DAT0L) = constrain((*_signalBus  >> _shift) + (_ofs), _min, _max);
    }
    Last edited by Theremingenieur; 01-11-2015 at 12:08 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
  •