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

Thread: All things - Low Power

  1. #51
    Junior Member
    Join Date
    Aug 2016
    Posts
    4
    Quote Originally Posted by duff View Post
    Ok good, i was going to suggest that first, I also had to use a pulldown resistor to make your sketch work as expected when power is not present on pin 2. Yes, the USB gets disconnected when sleeping so you have to reopen the Serial monitor and even then it could take awhile for the usb to stabilize. What I found works best is to use usb for debug and use a delay of 1000 ms after sleeping to let the usb reconnect with your pc and it still can be a little flakey.
    OK great, and yes my external circuit has a pulldown on pin 2. Sorry should have mentioned that.

    So far I have tried to reopen the serial monitor and used different delays after waking on the USB but I have not had any luck yet. I am using a Teraterm terminal for my Serial monitor window. When you say serial monitor are you referring to the Arduino IDE serial monitor? I have not tried that one but will give that a shot to see if that is more forgiving on the reconnect. I am only using the usb for debug and I may have some other options for that.

    Thank you for all the help.

  2. #52
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955
    Quote Originally Posted by reldats View Post
    OK great, and yes my external circuit has a pulldown on pin 2. Sorry should have mentioned that.
    I added the pin mode INPUT_PULLDOWN to the digital sleep options in v6 of Snooze, so you might be able get rid of that resistor.
    Last edited by duff; 11-23-2016 at 04:20 PM. Reason: update link

  3. #53
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,549
    Duff - as you hopefully saw I (ab)used your V6_beta REDUCED_CPU_BLOCK to safely get the CPU speed down to drop out of HSRUN on the T_3.6 for a quick write to EEPROM test. I didn't try because I think the HSRUN raises he MCU voltage to assure the processing works at 'speed', which is why it is unsafe to access the EEPROM memory.

    Some questions there - maybe they and others belong here?
    > Is there a way to set to other than 2 MHz or is that a magic value?
    > Can an alternate version of the set_runlp() set the clock upwards to 16MHz in this mode? Higher? Maybe not drop to VLP mode but just to a mode with 120 MHz or less to exit HSRUN?

    Question on returning to the 'sketch in progress'::
    _> The use case is: stop what the Teensy is doing - Drop CPU speed - Exit HSRUN mode - perform EEPROM writes - Enter HSRUN mode - { Restore speed }
    __> Say you want to write some observed "ROBOT servo initial data" to the EEPROM without swapping the sketch to a lower speed and re-entering it.
    _> Nothing else will be done at this time - just a break to safely write to EEPROM.
    > Is the world really unsafe at this point - supposing anything time based was in use ( SPI, SDHC, I2C, USB, Ethernet, ...)
    ?> i.e. Can this be done for the duration of xxx usecs to write some or all of the EEPROM and then return to normal operation?
    ?> Or would the dynamic nature of the interrupts and bus usage suggest a best practice of Only doing this followed by a Full RESET?
    { I did not time the duration of a full 4KB EEPROM write at this lower speed }

    > Is there a single hunk of code to extract to perform your magic for this 'special case'?
    ?> Could you, or I, extract a clean working 'SNOOZE' subset to just facilitate this case of EEPROM write { and perhaps other things like 'reading the serial number', or items yet unknown }
    _> It might be a compromise in that inbound data might be lost/scrambled, but better than going offline, reprogramming twice and figuring out a way to know what was to be written when RAM is lost.

    Question: When running snooze on T_3.6 would it ever make sense for you to add the code like in the linked post to Exit and Enter HSRUN as I did to make sure other things (like EEPROM, ?) are not blocked?

    Any tips or feedback or a better way are welcome.
    PS: I'm glad I saw your code and that it worked so well for my test case!

  4. #54
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955
    Quote Originally Posted by defragster View Post
    Duff - as you hopefully saw I (ab)used your V6_beta REDUCED_CPU_BLOCK to safely get the CPU speed down to drop out of HSRUN on the T_3.6 for a quick write to EEPROM test. I didn't try because I think the HSRUN raises he MCU voltage to assure the processing works at 'speed', which is why it is unsafe to access the EEPROM memory.
    @defragster - So we are sure the eeprom for the T3.6/5 doesn't work in HS run mode? It would be easy to change the cpu dividers or do you have to change clock domains and cpu dividers, probably not. If its just cpu dividers and clearing the HS run bit then that should be pretty painless I would think.

  5. #55
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,549
    Quote Originally Posted by duff View Post
    @defragster - So we are sure the eeprom for the T3.6/5 doesn't work in HS run mode? It would be easy to change the cpu dividers or do you have to change clock domains and cpu dividers, probably not. If its just cpu dividers and clearing the HS run bit then that should be pretty painless I would think.
    Yes, that has been confirmed by myself and manitou, perhaps others - and documented in the F.M. per Paul. In fact that sketch as noted when the #IFDEF detection is ignored ( don't set DoSnooze = 1; ) can run forever and the EEPROM is never updated. I did not test - but I suspect the serial # read - that is ignored in HSRUN - would also work with these edits.

    This only applies to the T_3.6! The T_3.5 has different silicon bits - won't run as fast - 5v Tolerance - and does not up the voltage into an HSRUN mode where EEPROM access is not safe. I tested this code at 168 MHz on a T_3.5 and at full speed the EEPROM writes works.

    For T_3.6 the clock must be at or under a net 120 MHz and then HSRUN can be disabled, the EEPROM written, then HSRUN enabled, and the cock restored. My understanding is that much, and I knew only enough to trust your SNOOZE library to provide a safe testing area - and find the 'simple' sketch to work within. The 'clock domain' should not matter as long as the speed is low and HSRUN can be disabled. If it is done at 120 MHz the time the clocks are lowered will minimize the chance of losing bus connects or data.

    If you want to suggest the needed steps for that I will happily test it to work. I might be able to guess my way to an answer with cut and paste, my first thought was to just undo what PJRC does in mk20dx128.c :: void ResetHandler(void), and then put that back, but I couldn't have done that in the time I did to know it worked without being lucky, or reading something.

  6. #56
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    4,677
    I have not done as much testing on the EEPROM stuff as defragster, but have read in the manual things like:
    Page 736
    HSRUN — An MCU power mode enabling high-speed access to the memory resources
    in the FTFE module. The user has no access to the Flash command set when the MCU is
    in HSRUN mode
    And p771 32.4.10.1
    Attempts to launch an FTFE command in VLP mode will be ignored. Attempts to launch
    an FTFE command in HSRUN mode will be trapped with the ACCERR flag being set.
    Not sure if you can solve this easily in a generic case, of automagically switching modes, while otherstuff is going on? Example suppose I do an EEPROM.write... at the same time, that some of the USARTS and/or SPI and/or DMA stuff are actively sending or receiving data, or I am using something like an Interval timer or PWM...

    But in my case, the majority of the time, EEPROM writes are an exception. Typically I may have the program go into some special mode, like Hexapod going into servo offset mode, where I do some stuff to adjust the servos until they are properly aligned and then tell the system to save away the offsets... in cases like this it probably does not matter if there is a minor hiccup.

  7. #57
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,549
    For the T_3.6 I was seeing the USER needing to know to batch EEPROM when they are prepared to lose time/data for speeds drops. VLP mode isn't needed if we can just drop the clocks enough, it was just what I thought to do with SNOOZE to do the tricky lifting and have it work. But that is a good reason for SNOOZE to be HSRUN aware.

    It might be possible to 'auto fix' any EEPROM write - but if you had a loop of 100 writes that would result in 100 cycles of the CPU speed. Like in your case something like this would be good:

    // ENTER code area where nothing but EEPROM is expected to work
    EEPROM.AllowFlashWrites_HSRUN( TRUE )
    // write whatever you want to the EEPROM
    for (I=1 to 100) write[I]=???
    write struct_x at 500
    for (I=2000 to 2999) write[I]=???
    write struct_y at 1000
    EEPROM.AllowFlashWrites_HSRUN( FALSE )
    // User may choose to RESTART to load/test new setttings and get all hardware restarted

  8. #58
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955
    KurtE is right about changing clock speeds while using things like hardware serial and such. I feel there is going to be no easy answer if you can't do eeprom writes in HS Run mode? Maybe if the code lets you register what peripherals you are using and adjust them before and after but there is still a chance that data could be corrupted if it hits a right when you are changing the cpu speed. This could happen in Snooze also using REDUCED_CPU_BLOCK too.

  9. #59
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,549
    Yeah - I knew and expected as much - and documented my code with these comments - just hoping to hear otherwise.
    // Now may be a good time to leave
    and pseudo above . . .
    // User may choose to RESTART to load/test new setttings and get all hardware restarted

    Made a sketch that drops speed to 120 MHz and successfully writes EEPROM - and USB didn't seem to survive. I'll start a thread so maybe it can be refined.

    <UPDATE> New Thread Posted - I got USB to recover at 180 MHz compile/restore speed.

    DUff - this macro is very cool!
    Code:
    #define REDUCED_CPU_BLOCK( SNOOZE_BLOCK )   \
    for ( TYPE __ToDo = SNOOZE_BLOCK.set_runlp( SNOOZE_BLOCK );  __ToDo;  __ToDo = SNOOZE_BLOCK.set_run( SNOOZE_BLOCK ) )
    Last edited by defragster; 09-09-2016 at 05:30 AM.

  10. #60

    Snooze.hibernate appears to stop audio intermittently on wakeup

    Working with Snooze_v6_beta and Teensyduino v1.30.

    I'm having an intermittent issue with using Snooze.hibernate with the audio library recording from Line In.
    It appears the problem is that the LRCLK does not start (if I am correct in the audio library driving the LRCLCK).
    MCLCK and BCLK do start correctly on wake.

    It seems to wake and record properly about 90% of the time. It does not make sense that it does not fail all of the time.

    Including SnoozeAudio in the SnoozeBlock does not solve issue.

    Switching to Snooze.sleep or not sleeping at all solves the issue.

    I will post a smaller bit of code that works with Teensy audio shield shortly to demonstrate issue.

    Is there any reason Pin 23 would not work properly on wakeup?

  11. #61
    Junior Member
    Join Date
    Nov 2015
    Posts
    15
    Hey duff, I really love the library. I've learned a lot about embedded development just by trying to understand how it all works and why you designed it the way you did; I really appreciate the work you have and continue to put into it.

    In my project, a processor is logging PWM inputs and sends out (over uart or otherwise) the pulse counts every 60 seconds. The way I have the snoozeblock configured is to have the PWM input pins wake up the processor and increment the counts, and to have it wake up every 60 seconds (in case there are no pulses, it still needs to send out 0's). The trouble is when the pulses run for forty seconds, then stop, and the processor won't be woken until the 100 second mark. I've solved this in the 3.1/3.2 with the RTC, by recording the last send time and reconfiguring the snoozeblock timer to 60-(timeSinceLastSend) and it works great.

    However, I'd really like to use the Teensy LC for this, and I've been struggling to figure out how. I see that the RTC and LPTMR are still running in LLS, and I've made code that keeps seconds pretty well for the LC RTC, as well as code that reads the LC LPTMR, but I can't get either of them to give me a good read before and after hibernate/deepSleep calls. Do you have an idea of how I can accomplish this?

    Thank you in advance for any time you can spare for this. I promise that I spent the better part of a day trying different things to no avail.
    Last edited by TMcGahee; 09-30-2016 at 08:52 PM.

  12. #62
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955
    Quote Originally Posted by TMcGahee View Post
    However, I'd really like to use the Teensy LC for this, and I've been struggling to figure out how. I see that the RTC and LPTMR are still running in LLS, and I've made code that keeps seconds pretty well for the LC RTC, as well as code that reads the LC LPTMR, but I can't get either of them to give me a good read before and after hibernate/deepSleep calls. Do you have an idea of how I can accomplish this?
    RTC is not implemented for Snooze with the Teensy LC but you have found a issue I ran into before I think. Say you setup your SnoozeBlock for digital wakeup event and you want to know how long that you where asleep. With the Teensy LC the RTC is not running so your in the dark of how long you where asleep. With my new version 6 of Snooze I think I'll have a way to use the RTC with Teensy LC but haven't tried it yet. When or if I get it working I'll let you know here. In the mean time try upgrading to that version 6, you will have to have the latest Teensyduino installed for it to compile though.

    If you want me to look at particular problem please post some code also cause I'm not exactly sure what I just said answers your question?

  13. #63
    Junior Member
    Join Date
    Nov 2015
    Posts
    15
    Quote Originally Posted by duff View Post
    RTC is not implemented for Snooze with the Teensy LC but you have found a issue I ran into before I think. Say you setup your SnoozeBlock for digital wakeup event and you want to know how long that you where asleep. With the Teensy LC the RTC is not running so your in the dark of how long you where asleep. With my new version 6 of Snooze I think I'll have a way to use the RTC with Teensy LC but haven't tried it yet. When or if I get it working I'll let you know here. In the mean time try upgrading to that version 6, you will have to have the latest Teensyduino installed for it to compile though.

    If you want me to look at particular problem please post some code also cause I'm not exactly sure what I just said answers your question?
    It sounds like you understand what I'm running into: "how long was I asleep" with a digital wakeup (in my case, with a timer wakeup as backup), and I appreciate that. The RTC could be one solution if we're really clever about it (and I definitely don't put that past you), but I was thinking if the user is expecting a short sleep times, they could just get the LPTMR count before and after. However, I couldn't get any code to read the LPTMR reliably both before and after going to sleep. Some of the register options from my code and inside the Snooze library are interfering with each other.

    Here's some code to try and time the deepSleep using the LPTMR:

    Code:
    #include <Snooze.h>
    
    #define DEBUG_SERIAL Serial1
    
    void setup() {
      DEBUG_SERIAL.begin(115200);
      while (!DEBUG_SERIAL);
    
      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, HIGH);
      delay(1000);
      digitalWrite(LED_BUILTIN, LOW);
     
      LPTMR_config(0);
    }
    
      // try to time deepSleep() using LPTMR
    void loop() {
      if(!DEBUG_SERIAL) DEBUG_SERIAL.begin(115200);
      digitalWrite(LED_BUILTIN, LOW);
    
    
      DEBUG_SERIAL.println("now for narcolepsy...");
      DEBUG_SERIAL.flush();
    
      SnoozeBlock config;
      config.pinMode(4,INPUT_PULLUP,FALLING);
      config.setTimer(10000);
    
      uint32_t t1 = LPTMR_get();
    
      Snooze.deepSleep(config);
    
      digitalWrite(LED_BUILTIN, HIGH); // To prove that LC didn't hang
    
      uint32_t dt1 = LPTMR_get() - t1;
    
      DEBUG_SERIAL.print("deep slept for "); DEBUG_SERIAL.print(0.001*dt1, 3); DEBUG_SERIAL.println("s - acording to LPTMR");
      DEBUG_SERIAL.println();
    
      delay(5000);
    }
    
    void LPTMR_config(bool useTCF){
      SIM_SOPT1 |= SIM_SOPT1_OSC32KSEL( 3 ); // Use LPO clock for RTC and LPTMR
      SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Allow read/write access to LPTMR
      LPTMR0_PSR = LPTMR_PSR_PBYP | LPTMR_PSR_PCS(1); // Set LPTMR prescaler to accomodate LPO clock
      if(useTCF)
        LPTMR0_CSR = LPTMR_CSR_TCF | LPTMR_CSR_TFC | LPTMR_CSR_TEN;
      else
        LPTMR0_CSR = LPTMR_CSR_TFC | LPTMR_CSR_TEN; // Definitely needs TFC
    }
    
    uint16_t LPTMR_get(){
        LPTMR0_CNR = 0;
        return LPTMR0_CNR;
    }
    It basically just attempts to get the LPTMR count before and after going to sleep. This version returns 0 before and after, but there are lots of register configurations that make it hang. I'm testing it by connecting Serial1 to another Teensy with the MultiSerial code.

    Any guidance on how I can set up the registers to get good readings from the LPTMR before and after a Snooze with both setTimer and pinMode wakeups (or just a "this isn't possible, the settings are mutually exclusive") would be greatly appreciated!
    Last edited by TMcGahee; 10-03-2016 at 07:19 PM. Reason: Removed unneeded lines of code for clarity

  14. #64
    Junior Member
    Join Date
    Nov 2015
    Posts
    15
    Aha! I figured it out!

    My mistake was trying to read the before and after, and find settings that could persist through the library's adjustments. Snooze aggressively shuts things down for the sake of low power, which is great, since that's the point, but it shuts down the timer and resets the count a few times, so that wasn't really an option.

    So, what I did is comment out the lptmr_disable() call from deepSleep and hibernate. Then, to keep the Timer Compare Flag (TCF) from resetting the timer count when it's done, I enabled LPTMR_CSR_TFC in the init function and kept it enabled in the setup function. Since the disable function call is no longer called, I changed the ISR to clear the TCF and disable the interrupt without disabling the timer. This way, I let the library reset the counter as we're going to sleep, and then I'm free to read the timer after we wake up.

    You can see the diff here (new lptmr.h compared to the version in 5.5.x ): diffchecker.com/5qHHdYPO

    Now, as desired, if we're woken by the timer, it'll read back that sleep time plus about 1ms (e.g. setTimer(10000) gives a time of 10001), and if we're woken by a digital wakeup, it'll read back that time. To save power I disable the timer again.

    Here's the sketch to see it working:
    Code:
    #include <Snooze.h>
    SnoozeBlock config;
    
    #define DEBUG_SERIAL Serial1
    
    void setup() {
      DEBUG_SERIAL.begin(115200);
      while (!DEBUG_SERIAL);
    
      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, HIGH);
      delay(1000);
      digitalWrite(LED_BUILTIN, LOW);
      
      config.pinMode(22, INPUT_PULLUP, RISING);
      config.setTimer(10000);
      // Other wakeups here!
    }
    
    // time deepSleep() using LPTMR
    void loop() {
      DEBUG_SERIAL.println("And now for something entirely narcoleptic.");
      DEBUG_SERIAL.flush();
    
      int who = Snooze.deepSleep(config);
      uint32_t t2 = LPTMR_get();
      LPTMR0_CSR = 0; // Disable the LPTMR to save a tiny bit of power
    
      DEBUG_SERIAL.begin(115200); delay(100);
      DEBUG_SERIAL.print("wakeup = "); DEBUG_SERIAL.println(who);
      DEBUG_SERIAL.print("Time asleep: "); DEBUG_SERIAL.println(t2);
      DEBUG_SERIAL.println();
    
      delay(2000);
    }
    
    uint16_t LPTMR_get(){
        LPTMR0_CNR = 0;
        return LPTMR0_CNR;
    }
    Here's lptmr.h (only tested with version 5.5.1):
    Code:
     /***********************************************************************************
     *  lptmr.h
     *  Teensy 3.x/LC
     *
     * Purpose: Low Power Timer
     *
     ***********************************************************************************/
    #ifndef __LPTMR_H__
    #define __LPTMR_H__
    /***********************************************************************************/
    #include <utility/util.h>
    /***********************************************************************************/
    static void ( * return_lptmr_irq ) ( void );
    /***********************************************************************************/
    typedef struct {
        uint16_t period;
        bool state = false;
    } lptmr_mask_t;
    /***********************************************************************************/
    #ifdef __cplusplus
    extern "C" {
    #endif
        /*******************************************************************************
         *
         *       lptmr_init
         *
         *******************************************************************************/
        static inline
        void lptmr_init( void )
        __attribute__((always_inline, unused));
        
        static inline
        void lptmr_init( void ) {
            SIM_SOPT1 |= SIM_SOPT1_OSC32KSEL( 3 );
            SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
            LPTMR0_PSR = LPTMR_PSR_PBYP | LPTMR_PSR_PCS(1);//LPO Clock
            LPTMR0_CSR = LPTMR_CSR_TCF | LPTMR_CSR_TFC;
            //SIM_SCGC5 &= ~SIM_SCGC5_LPTIMER;
        }
        /*******************************************************************************
         *
         *       lptmr_configure_pin_mask
         *
         *******************************************************************************/
        static inline
        void lptmr_configure_period_mask( uint16_t period, lptmr_mask_t *mask )
        __attribute__((always_inline, unused));
        
        static inline
        void lptmr_configure_period_mask( uint16_t period, lptmr_mask_t *mask ) {
            mask->period = period;
            mask->state = true;
        }
        /*******************************************************************************
         *
         *       lptmr_isr
         *
         *******************************************************************************/
        static inline
        void lptmrISR( void )
        __attribute__((always_inline, unused));
        
        static inline
        void lptmrISR( void ) {
           
            if ( !( SIM_SCGC5 & SIM_SCGC5_LPTIMER ) || !( irqEnabledFlag & LPTMR_IRQ_BIT ) ) return;
            LPTMR0_CSR |= LPTMR_CSR_TCF | ~LPTMR_CSR_TIE;
            irqEnabledFlag &= ~LPTMR_IRQ_BIT;
            if ( enable_periph_irq ) wakeupSource = 36;
        }
        /*******************************************************************************
         *
         *       lptmr_set
         *
         *******************************************************************************/
        static inline
        void lptmr_set( lptmr_mask_t *mask )
        __attribute__((always_inline, unused));
        
        static inline
        void lptmr_set( lptmr_mask_t *mask ) {
            if ( mask->state == false ) return;
            if ( enable_periph_irq ) {
                int priority = nvic_execution_priority( );// get current priority
                // if running from handler mode set priority higher than current handler
                priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128;
                NVIC_SET_PRIORITY( IRQ_LPTMR, priority );//set priority to new level
                __disable_irq( );
                return_lptmr_irq = _VectorsRam[IRQ_LPTMR+16];// save prev isr
                attachInterruptVector( IRQ_LPTMR, lptmrISR );
                __enable_irq( );
            }
            lptmr_init( );
            LPTMR0_CMR = mask->period;
            if( enable_periph_irq ) NVIC_ENABLE_IRQ( IRQ_LPTMR );
            LPTMR0_CSR = LPTMR_CSR_TEN | LPTMR_CSR_TIE | LPTMR_CSR_TCF | LPTMR_CSR_TFC;
            irqEnabledFlag |= LPTMR_IRQ_BIT;
        }
        /*******************************************************************************
         *
         *       lptmr_stop
         *
         *******************************************************************************/
        static inline
        void lptmr_disable( lptmr_mask_t *mask )
        __attribute__((always_inline, unused));
        
        static inline
        void lptmr_disable( lptmr_mask_t *mask ) {
            if ( mask->state == false ) return;
            LPTMR0_CSR = 0;
            SIM_SCGC5 &= ~SIM_SCGC5_LPTIMER;
            if ( enable_periph_irq ) {
                NVIC_DISABLE_IRQ( IRQ_LPTMR );//return priority to core value
                NVIC_SET_PRIORITY( IRQ_LPTMR, 128 );// return priority core level
                __disable_irq( );
                attachInterruptVector( IRQ_LPTMR, return_lptmr_irq );// return prev interrupt
                __enable_irq( );
            }
        }
    #ifdef __cplusplus
    }
    #endif
    /***********************************************************************************/
    #endif /* defined(__LPTMR_H__) */
    And don't forget to comment out lptmr_disable( &p->lptmr_mask ); from deepSleep and/or hibernate in Snooze.cpp

    Thanks again for the great work you've put into this duff; it's a totally awesome and clever library.
    Last edited by TMcGahee; 10-04-2016 at 05:47 PM.

  15. #65
    Senior Member
    Join Date
    Sep 2013
    Location
    Boston, MA
    Posts
    111
    Quote Originally Posted by Dascyllus View Post
    Working with Snooze_v6_beta and Teensyduino v1.30.

    I'm having an intermittent issue with using Snooze.hibernate with the audio library recording from Line In.
    It appears the problem is that the LRCLK does not start (if I am correct in the audio library driving the LRCLCK).
    MCLCK and BCLK do start correctly on wake.

    It seems to wake and record properly about 90% of the time. It does not make sense that it does not fail all of the time.

    Including SnoozeAudio in the SnoozeBlock does not solve issue.

    Switching to Snooze.sleep or not sleeping at all solves the issue.

    I will post a smaller bit of code that works with Teensy audio shield shortly to demonstrate issue.

    Is there any reason Pin 23 would not work properly on wakeup?
    Were you able to resolve this issue? I seem to be having the same intermittent problem playing back.

  16. #66
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955
    Quote Originally Posted by ftrias View Post
    Were you able to resolve this issue? I seem to be having the same intermittent problem playing back.
    Are you using the Audio Shield?

  17. #67
    Senior Member
    Join Date
    Sep 2013
    Location
    Boston, MA
    Posts
    111
    Quote Originally Posted by duff View Post
    Are you using the Audio Shield?
    Yes I am using the Audio Shield. But I have a lot of things going on and my code is a mess so it could be something else. I just wanted to see if there are some things to try to see if I have the same problem that can be easily fixed. If not, that's ok, I'll debug some more.
    Last edited by ftrias; 03-26-2017 at 08:47 PM.

  18. #68
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955
    The clocks are probably one issue with sleeping, I never looked at the I2S stuff yet but I know PDB clocks where not starting back up when going to deepSleep or hibernate which that Snooze Audio driver attempts to fix. I'll take a look tonight if I feel better, just ate something and broke out in hives.

  19. #69
    Senior Member
    Join Date
    Oct 2015
    Location
    Vermont, USA
    Posts
    167
    I'm not sure this is relevant for the Teensy LC, but for the Teensy 3.1-3.6, you can also save a lot of power by simply having it wait for the triggering of any interrupts you've set up (timers or pins). Simply add: asm(" WFI"); to your sketch and bask in the power savings.

    I had started my search for power savings by slowing the CPU speed. While this is effective, it means that you have to manually re-evaluate your target CPU speed every time that you alter your software stack. What a pain!

    If you instead become interrupt driven, then the asm(" WFI") command lets you keep the Teensy at full speed while letting your software tell it when to sleep and letting your interrupts tell it when to wake. It saves you a good bit of power with very little programmer effort.

    More info: http://openaudio.blogspot.com/2016/1...rent-draw.html

    Click image for larger version. 

Name:	Graph-CurrentDraw.png 
Views:	108 
Size:	22.1 KB 
ID:	10127

    So, sure, this graph shows that manually finding and selecting the slowest speed that still gets your software to run (in this case ~30 MHz) yields the lowest power, it's nice to know that simply running it full-blast (180 MHz) and tossing in the asm(" WFI") command will still get you some nice savings with so, so little effort.

    Chip
    Last edited by chipaudette; 03-26-2017 at 08:51 PM.

  20. #70
    Junior Member
    Join Date
    Jan 2018
    Posts
    16
    Hello, i am trying to figure out how the Snooze library works and i cannot find where all the register options are defined, like the SIM_SOPT1CFG_USSWE or the SIM_SOPT1_USBSSTBY so i can use them directly.

  21. #71
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,412
    Depends on the processor you are using. Get the corresponding Reference Manual (not the simplified electrical data sheet) from here https://www.pjrc.com/teensy/datasheets.html

  22. #72
    Junior Member
    Join Date
    Jan 2018
    Posts
    16
    I know they are in the manual, i have found them, i just cant see where they are declared in a header or somewhere else. For example

    #define SIM_SOPT1_USBSSTBY (1 << 30)

  23. #73
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,549
    Using sublime text editor on the install directory is shows me this for a search on "USBSSTBY":

    T:\arduino_b1.9_B31_td142\hardware\teensy\avr\core s\teensy3\kinetis.h:
    1070 #define SIM_SOPT1 (*(volatile uint32_t *)0x40047000) // System Options Register 1
    1071 #define SIM_SOPT1_USBREGEN ((uint32_t)0x80000000) // USB regulator enable
    1072: #define SIM_SOPT1_USBSSTBY ((uint32_t)0x40000000) // USB regulator standby in Stop, VLPS, LLS and VLLS
    1073 #define SIM_SOPT1_USBVSTBY ((uint32_t)0x20000000) // USB regulator standby in VLPR and VLPW
    1074 #define SIM_SOPT1_OSC32KSEL(n) ((uint32_t)(((n) & 3) << 18)) // 32K oscillator clock, 0=system osc, 2=rtc osc, 3=lpo

    T:\arduino_b1.9_B31_td142\hardware\teensy\avr\libr aries\Snooze\Snooze.cpp:
    40 /*SnoozeClass::SnoozeClass( void ) {
    41 //SIM_SOPT1CFG |= SIM_SOPT1CFG_USSWE;
    42: //SIM_SOPT1 &= ~SIM_SOPT1_USBSSTBY;
    43 }*/
    44 /************************************************** *****************************
    ..
    142 NVIC_SET_PRIORITY( IRQ_LLWU, priority );//set priority to new level
    143 SIM_SOPT1CFG |= SIM_SOPT1CFG_USSWE;
    144: SIM_SOPT1 |= SIM_SOPT1_USBSSTBY;
    145 PCR3 = PORTA_PCR3;
    146 PORTA_PCR3 = PORT_PCR_MUX( 0 );
    ...
    172 p->mode = RUN;
    173 SIM_SOPT1CFG |= SIM_SOPT1CFG_USSWE;
    174: SIM_SOPT1 &= ~SIM_SOPT1_USBSSTBY;
    175 PORTA_PCR3 = PCR3;
    176 return p->source;

    T:\arduino_b1.9_B31_td142\hardware\teensy\avr\libr aries\Snooze\SnoozeBlock.h:
    162 if ( global_block_count == 0 ) {
    163 SIM_SOPT1CFG |= SIM_SOPT1CFG_USSWE;
    164: SIM_SOPT1 &= ~SIM_SOPT1_USBSSTBY;
    165 attachInterruptVector( IRQ_LLWU, wakeupIsr );
    166 NVIC_ENABLE_IRQ( IRQ_LLWU );

  24. #74
    Junior Member
    Join Date
    Jan 2018
    Posts
    16
    So its in the kinetis.h library, its one of the core libraries. Thank you very much for the help

  25. #75
    Bump,

    Sorry guys I did my best to search but what pin states have the lowest sleep current?

    I know in the Atmel AVR world there is a big difference:
    All pins as outputs, and LOW: 0.35 A
    All pins as outputs, and HIGH: 1.86 A.
    All pins as inputs, and LOW (in other words, internal pull-ups disabled): 0.35 A
    All pins as inputs, and HIGH (in other words, internal pull-ups enabled): 1.25 A.

Posting Permissions

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