Forum Rule: Always post complete source code & details to reproduce any issue!
Page 3 of 3 FirstFirst 1 2 3
Results 51 to 61 of 61

Thread: 2Hz analogWriteFrequency on Teensy 3.1

  1. #51
    Junior Member
    Join Date
    Jan 2017
    Posts
    5
    By any chance has anyone got the analogWriteFrequencySlow function running on the Teensy 4.0?

  2. #52
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,433
    This is an old T_3.1 thread - if an example problem on T_4.0 shows up it would be good to start a new thread perhaps.

    Quote Originally Posted by darellon View Post
    By any chance has anyone got the analogWriteFrequencySlow function running on the Teensy 4.0?
    More context please? Not seeing a analogWriteFrequencySlow() so it wasn't added to the Teensy CORES.

    Does the analogWriteFrequency() not work on T_4.0 at 2Khz?

  3. #53
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    28,468
    Quite some time ago I merged a contribution which I believe was originally named analogWriteFrequencySlow. But it was merged into normal analogWriteFrequency, rather than adding a new function name. If you request a frequency on Teensy 3.x which is too low to be generated by the timer+prescalers from F_BUS, then it switches the timer to using a much slower clock. This is only possible because the FTM timers have an option to use a slower clock.

    So far, I am not aware of anyone managing to use an alternate clock for PWM on Teensy 4. It may be possible. Here's the info from the reference manual.

    Click image for larger version. 

Name:	pwmclock.png 
Views:	127 
Size:	212.6 KB 
ID:	21070

    Normally we run with mux input 0, which is 150 MHz. With only an 8 bit prescaler and 16 bit counters, we just can't reach very slow PWM frequency because we can only divide 150 MHz by 2^24.

    The AUX_CLK (input 2) might be possible, but it would require dedicating submodule0 to act as a prescaler. My understanding is it could only apply to the pins controlled by the other 3 submodules of each FlexPWM, and doing so would make the PWM unusable on the pins controlled by that first submodule.

    EXT_CLK (input 1) looks much more promising. It appears to be connected to XBAR output 34 for FlexPWM1 and XBAR output 48 for the other 3 FlexPWM timers. So perhaps we could dedicate one of the unused QuadTimers to generate a relatively slow clock, like 100 kHz and route its through the XBAR to the EXT_CLK inputs.

    Of course this would only work on the PWM pins controlled by FlexPWM timers. The QuadTimer controlled pins would need some other approach. But the QuadTimer prescaler has more bits, so maybe not such an issue with those pins.

  4. #54
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,781
    Quote Originally Posted by darellon View Post
    By any chance has anyone got the analogWriteFrequencySlow function running on the Teensy 4.0?
    Re: slow PWM with GPT

    I think you can run the T4 GPT timer at low PWM frequency. The compare register is 32 bits so you should be able to get below 1 hz. I think you can only do 50% duty and the output pin is different for T4.0 (GPT2 compare3, pin 16) vs T4.1 (GPT2 compare1, pin 41). here is a T4.1 GPT PWM example
    Code:
    //teensy 4.1 GPT PWM  pin 41 AD_B1_05 PWM GPT2 compare1 ALT8
    
    #define TICKS  24000
    
    void setup() {
      //initialise general hardware
      Serial.begin(115200);             //setup serial port
    
      //  CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode
      CCM_CCGR0 |= CCM_CCGR0_GPT2_BUS(CCM_CCGR_ON) ;  // enable GPT2 module
    
      //configure GPT2 for test
      GPT2_CR = 0;                                //clear the control register, FRR = 0 means restart after Compare
      GPT2_SR = 0x3F;                             //clear all prior status
      GPT2_PR = 0;                                //prescale register set divide by 1
      GPT2_CR |= GPT_CR_CLKSRC(1);                //clock selection #1 24 mhz crystal
    
      GPT2_CR |= GPT_CR_ENMOD;                    //reset count to zero before enabling
      GPT2_CR |= GPT_CR_OM1(1);           // toggle mode compare1
      GPT2_OCR1 = TICKS - 1;                   //Compare1 value  1khz
    
      GPT2_CR |= GPT_CR_EN;                   //enable GPT2
    
      //configure T41 pin 41 as Compare1 output
      IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_05 = 8;
    }
    
    
    void loop() {
    
    }
    if you want to go real slow, you can select the 32khz clock for the GPT timer.

    Restart mode (FRR = 0) only works on compare channel 1.
    Last edited by manitou; 07-30-2021 at 01:08 AM.

  5. #55
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,781
    Re: slow PWM

    As Paul noted, one can use EXT_CLK via XBAR to flexpwm timers to get a slower clock. Here is a proof-of-concept sketch using quad-timer to provide a 10khz clock via XBAR to flexpwm timer. Hook scope to pin 8 (PWM output pin).
    Code:
    // QTIMER4 timer 0  xbar 36 to EXT_CLK flexpwm via XBAR  34
    // pin 8 FLEXPWM1_A3   XBAR1_OUT34
    
    #define MMASK (1<<3)   // module mask 3 for PWM1_A3
    
    #define PRREG(x) Serial.print(#x" 0x"); Serial.println(x,HEX)
    
    void flexpwm_init(int scale) {
      // flexpwm pin 8  external clock
    
      FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(MMASK);  //A3
      IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6 ;  // ALT6
      FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(MMASK);   // clear
      FLEXPWM1_FSTS0 = FLEXPWM_FSTS0_FFLAG(MMASK);    // clear
      FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(MMASK);
      FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP | FLEXPWM_SMCTRL2_CLK_SEL(1); // ext clk
      FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_PRSC(0);
      FLEXPWM1_SM3INIT = 0;
      FLEXPWM1_SM3VAL0 = 0;
      FLEXPWM1_SM3VAL1 = scale - 1;  // period ticks
      FLEXPWM1_SM3VAL2 = 0;
      FLEXPWM1_SM3VAL3 = scale / 2;
      FLEXPWM1_SM3VAL4 = 0;
      FLEXPWM1_SM3VAL5 = 0;
      FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(MMASK) | FLEXPWM_MCTRL_RUN(MMASK);
    }
    
    void xbar_connect(unsigned int input, unsigned int output)
    {
      if (input >= 88) return;
      if (output >= 132) return;
      volatile uint16_t *xbar = &XBARA1_SEL0 + (output / 2);
      uint16_t val = *xbar;
      if (!(output & 1)) {
        val = (val & 0xFF00) | input;
      } else {
        val = (val & 0x00FF) | (input << 8);
      }
      *xbar = val;
    }
    
    void xbar_init() {
      CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);   //turn clock on for xbara1
      xbar_connect(XBARA1_IN_QTIMER4_TIMER0, XBARA1_OUT_FLEXPWM1_EXT_CLK);   // 36,34
    }
    
    void qtmr40_init(int hz) {
      int cnt, pcs = 0;
      cnt = 150000000 / hz;
      while (cnt > 65536) {
        pcs++;
        hz *= 2;
        cnt = 150000000 / hz;
      }
      CCM_CCGR6 |= CCM_CCGR6_QTIMER4(CCM_CCGR_ON);  // enable qtmr4
      TMR4_CTRL0 = 0; // stop
      TMR4_SCTRL0 =  TMR_SCTRL_OPS | TMR_SCTRL_OEN ;
      TMR4_LOAD0 = 0;  // start val after compare
      TMR4_COMP10 = cnt - 1;  // count up to this val, interrupt,  and start again
      TMR4_CMPLD10 = cnt - 1;
      TMR4_CTRL0 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + pcs) | TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(4) ; // prescale
    }
    
    
    void setup() {
      Serial.begin(9600);
    
      delay(1000);
      xbar_init();
      flexpwm_init(10);   //divisor
      qtmr40_init(10000);  // 10 khz
    }
    
    void loop() {
    
    }
    EDIT: use QTIMER4/0 since not used by T4*
    https://github.com/manitou48/teensy4...r/qtmrxpwm.ino
    Last edited by manitou; 01-06-2021 at 09:50 AM. Reason: use QTIMER4/0

  6. #56
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    28,468
    Quote Originally Posted by manitou View Post
    Here is a proof-of-concept sketch
    Awesome!

    I had already put this thread on my low priority issue list, where "low priority" means I'll probably never actually get around to doing it. But with this proof of concept paving the way, I'll integrate it into analogWriteFrequency in Teensyduino 1.54 or 1.55.

  7. #57
    Senior Member vjmuzik's Avatar
    Join Date
    Apr 2017
    Posts
    855
    I'm also interested in this being included for the T4.x hopefully in Teensyduino 1.54.

  8. #58
    Junior Member
    Join Date
    Oct 2022
    Posts
    1
    Has anyone found a way to make this work for teensy 4.x? Seems like it will be a while before we can order teensy 3's...

  9. #59
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    1,376
    Could you not use a frequency divider chip?
    That way the 4.x can generate a higher frequency which is divided down by the external chip.

  10. #60
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,781
    Quote Originally Posted by doggy View Post
    Has anyone found a way to make this work for teensy 4.x? Seems like it will be a while before we can order teensy 3's...
    see example in post #55, flexpwm_init(5000); will give 2hz on pin 8
    Last edited by manitou; 10-10-2022 at 06:06 PM.

  11. #61
    Senior Member
    Join Date
    Jan 2020
    Location
    Toronto, Canada
    Posts
    137
    Quote Originally Posted by doggy View Post
    Has anyone found a way to make this work for teensy 4.x? Seems like it will be a while before we can order teensy 3's...
    You can try this Teensy_Slow_PWM library, designed for very low (sub-Hz) up to 500Hz ISR-based PWM.

Posting Permissions

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