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

Thread: Best way to reduce this power consumption?

  1. #1
    Junior Member
    Join Date
    Jan 2019
    Posts
    7

    Best way to reduce this power consumption?

    I have a basic MP3 player using the prop shield LC from Frank B's MP3 player here

    The code below basically will play the MP3 file based off a pin trigger. With so many inputs (eventually possibly hooking up a matrix) I am wondering what the best way to save power moving forward... Ideally a trigger button can be pressed and wake up the teensy and jump right to the MP3 file being played. Any help is greatly appreciated!

    Code:
    // Simple MP3 file player example
    // https://forum.pjrc.com/threads/27059-MP3-Player-Lib-with-example?p=101537&viewfull=1#post101537
    // Requires the prop-shield and Teensy 3.2 or 3.1
    // This example code is in the public domain.
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <play_sd_mp3.h> // https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib
    //#include <play_sd_aac.h>
    #include <Bounce2.h>
    
    // GUItool: begin automatically generated code
    //AudioPlaySdWav           playSdWav1;     //xy=154,422
    AudioPlaySdMp3           playMp31; //xy=154,422
    AudioMixer4              mixer1;         //xy=327,432
    AudioOutputAnalog        dac1;           //xy=502,412
    AudioConnection          patchCord1(playMp31, 0, mixer1, 0);
    AudioConnection          patchCord2(playMp31, 1, mixer1, 1);
    AudioConnection          patchCord3(mixer1, dac1);
    // GUItool: end automatically generated code
    
    #define PROP_AMP_ENABLE    5
    #define FLASH_CHIP_SELECT  6
    //#define FLASH_CHIP_SELECT 21  // Arduino 101 built-in SPI Flash
    
    // Bounce objects to read two pushbuttons (pins 0,1)
    Bounce button0 = Bounce(0, 5);
    Bounce button1 = Bounce(1, 5);  // 5 ms debounce time
    
    void setup() {
      // Configure the pushbutton pins for pullups. Each button should connect from the pin to GND.
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
      Serial.begin(9600);
      AudioMemory(8); //4
      delay(2000);
    
      // Start SerialFlash
      if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1) {
          Serial.println ("Cannot access SPI Flash chip");
          delay (1000);
        }
      }
    
      //Set Volume
      mixer1.gain(0, 0.9);
      mixer1.gain(1, 0.9);
    
      //Start Amplifier
      pinMode(PROP_AMP_ENABLE, OUTPUT);
      digitalWrite(PROP_AMP_ENABLE, HIGH);    // Enable Amplifier
    }
    
    void playFile(const char *filename)
    {
      SerialFlashFile ff = SerialFlash.open(filename);
      Serial.print("Playing file: ");
      Serial.println(filename);
    
      uint32_t sz = ff.size();
      uint32_t pos = ff.getFlashAddress();
    
      // Start playing the file.  This sketch continues to
      // run while the file plays.
      playMp31.play(pos,sz);
    
      // Simply wait for the file to finish playing.
      /*
      while (playMp31.isPlaying()) {
        yield();
      }
      */
    }
    
    void loop() {
      //
      // Update all the button objects
      button0.update();
      button1.update();
      //
      if (button0.fell()) {
        // playMp31.stop();
        playFile("PinZero.mp3");
      } else if (button1.fell()) {
        // playMp31.stop();
        playFile("PinOne.mp3");
      }
      //
    }

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,525
    - use Duffs snooze library
    - switch off the amplifier when not in use
    - reduce the speed to 48MHz.

  3. #3
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,943
    Or possibly just have a mechanical on/off switch (you would need to record into the EEPROM or the flash memory the current file being played to start where you left off).

  4. #4
    Junior Member
    Join Date
    Jan 2019
    Posts
    7
    Thanks for the input @Frank B and @MichaelMeissner

    The project is actually a set of sound effects (no more than 2 seconds long) but with many buttons/inputs.

    The aim is to have it be able to be picked up and used anytime rather than a delay with a switch. My inspiration comes from some of the off-the-shelf toys which have batteries which (seemingly) last years...

    I will work towards getting Duff's snooze library implemented. I will do some more reasearch on it, but I am wondering if this would limit me to using just 2,4,6,7,9,10,11,13,16,21,22,26,30,33 as input pins? I wonder how this would work in a matrix setup...

    Thanks!

  5. #5
    Junior Member
    Join Date
    Jan 2019
    Posts
    7
    I am working through the 3 suggestions above, but I realize that there is most likely not a way to power this off of 3xAA batteries?

    I am measuring the voltage @ 4.15v from the battery pack and I am hoping to not have to get too sophisticated with the power supply after the 3xAA batteries

    reading this:
    https://www.pjrc.com/teensy/external_power.html

    Am I correct to see that the max CPU speed is 16Mhz? I hope not to have to cross this bridge, as it won't compile below 48Mhz

    Is there any option that would allow me to power this off of the 3xAA battery pack I have? Or maybe I just need new batteries...

    Thanks in advance!

    Jon

  6. #6
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    944
    Quote Originally Posted by dash4g View Post
    ...but I am wondering if this would limit me to using just 2,4,6,7,9,10,11,13,16,21,22,26,30,33 as input pins? I wonder how this would work in a matrix setup...
    Those are the wakeup pins for deepSleep and hibernate only so if you want every pin to be able wake the teensy up those are your choices.

    If I where you I would work one step at a time, having a power switch hooked to the batteries is a sure fire way to save your batteries as long as the person turns it off. The other things I have done in the past is to uses some sort of IC switch to programmatically kill power to sub systems that eat up to much power when the Teensy is sleeping or not. I always start with a base-line power measurements (sleeping and run) of a Teensy with nothing hooked up to it. I then add components one at a time and re-measure everything while keeping journal of those measurements. I then go and research different ways to save power like setting pins into a high Z state and such if need be. Once you get more specific to what you need we can help more.

  7. #7
    Junior Member
    Join Date
    Jan 2019
    Posts
    7
    Hey Duff, just to say thanks for replying, love the implementation of the snooze library, thanks for your work!

    Quote Originally Posted by duff View Post
    Those are the wakeup pins for deepSleep and hibernate only so if you want every pin to be able wake the teensy up those are your choices.
    Since I have posted, I have played a bit with these and I have found the combination of these pins along with others. Very slick.

    Quote Originally Posted by duff View Post
    If I where you I would work one step at a time, having a power switch hooked to the batteries is a sure fire way to save your batteries as long as the person turns it off.
    Yes, this would be ideal; what I am actually doing is restructuring a child's toy, (children using the toy) which is why the wake up pins were so preferable and if a parent/adult remembers to switch it off, then great. But, perhaps I jumped the gun on working forward with this as I now have the code and snooze library implemented. I just found out that the 3xAA batteries won't just work with the teensy and this implementation

    Which leads me to your other point

    Quote Originally Posted by duff View Post
    The other things I have done in the past is to uses some sort of IC switch to programmatically kill power to sub systems that eat up to much power when the Teensy is sleeping or not.
    I have looked at a "LM2623" to provide 5v constant, however I suspect this would burn through the batteries like no business.

    Another thing I was thinking of was a timed IC which switches the power in line with the HIBERNATE_DELAY but that seems convoluted

    I also found out that an Anker powerbank hooked up to the Micro USB will not power on the teensy. I suspect there may be an issue with the cable or bank itslef, but I will investigate this as well.

    For what it is worth, here is the code I have been working through:
    Code:
    // Simple MP3 file player example
    //
    // https://forum.pjrc.com/threads/27059-MP3-Player-Lib-with-example?p=101537&viewfull=1#post101537
    //
    // Requires the prop-shield and Teensy 3.2 or 3.1
    // This example code is in the public domain.
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <play_sd_mp3.h> // https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib
    #include <Bounce2.h>
    #include <Snooze.h>
    #include <SnoozeBlock.h>
    
    #define PINTER_DELAY 2000
    #define HIBERNATE_DELAY  300000
    
    #define PROP_AMP_ENABLE    5
    #define FLASH_CHIP_SELECT  6
    //#define FLASH_CHIP_SELECT 21  // Arduino 101 built-in SPI Flash
    
    // GUItool: begin automatically generated code
    //AudioPlaySdWav           playSdWav1;     //xy=154,422
    AudioPlaySdMp3           playMp31; //xy=154,422
    AudioMixer4              mixer1;         //xy=327,432
    AudioOutputAnalog        dac1;           //xy=502,412
    AudioConnection          patchCord1(playMp31, 0, mixer1, 0);
    AudioConnection          patchCord2(playMp31, 1, mixer1, 1);
    AudioConnection          patchCord3(mixer1, dac1);
    // GUItool: end automatically generated code
    
    const char *sounds[] = {
      "achest.mp3",
      "afoot.mp3",
      "ear.mp3",
      "lfoot.mp3",
      "rhand.mp3",
      "hand.mp3"
      };
    
    bool buttons[33];    // create a symbol for every button
    Bounce buttonsB[33]; // debounce handler for each button not excluded.
    //
    uint8_t exclude_buttons[] = { 6, 7, 10, 11, 12, 13 };   // exclude pins that may be required for communication or other
    uint8_t switch_buttons[] = { 23, 24 };
    
    // button 0 -> 33
    void initButtonStates() {
      for ( uint8_t i = 0; i < 33; i++ ) {
        buttons[i] = false;
      }
    }
    
    bool isSwitch(uint8_t b) {
      uint8_t n = sizeof(switch_buttons);
      for ( uint8_t i = 0; i < n; i++ ) {
          if ( b == switch_buttons[i] ) {
            return(true);
          }
      }
      return(false);
    }
    
    bool excludedButton(uint8_t b) {
      uint8_t n = sizeof(exclude_buttons);
      for ( uint8_t i = 0; i < n; i++ ) {
          if ( b == exclude_buttons[i] ) {
            return(true);
          }
      }
      return(false);
    }
    
    void setupBouncers(void) {
      for ( uint8_t i = 0; i < 33; i++ ) {
        if ( !excludedButton(i) ) {
          buttonsB[i].attach( i , INPUT_PULLUP  );  //setup the bounce instance for the current button
          buttonsB[i].interval(10);                 // interval in ms
        }
      }
    }
    
    void buttonUpdates(void) {
      // Update all the button objects
      for ( uint8_t i = 0; i < 33; i++ ) {
        if ( !excludedButton(i) ) {
          buttonsB[i].update();
        }
      }
    }
    
    bool buttonSense(void) {
      //
      buttonUpdates();
      //
      bool hasActivity = false;
      for ( uint8_t i = 0; i < 33; i++ ) {
        if ( !excludedButton(i) ) {
          bool bstate = ( buttonsB[i].read() == 0 );
          bool bfell = buttonsB[i].fell();
          if ( isSwitch(i) ) {
            buttons[i] = bstate;
          } else {
            buttons[i] = bstate && bfell;
          }
          hasActivity = hasActivity || bstate;
        }
      }
      //
      return(hasActivity);
    }
    
    SnoozeDigital digital;
    // install drivers to a SnoozeBlock
    SnoozeBlock config(digital);
    
    uint8_t wakeupPins[] = { 2, 4, 6, 7, 9, 10, 11, 13, 16, 21, 22, 26, 30, 33 };
    
    void initWakeupPins(void) {
      uint8_t n = sizeof(wakeupPins);
      for ( uint8_t i = 0; i < n; i++ ) {
        if ( !excludedButton(wakeupPins[i]) ) {
          pinMode(wakeupPins[i], INPUT_PULLUP);
          digital.pinMode(wakeupPins[i], INPUT_PULLUP, FALLING);  // pin, mode, type
        }
      }
    }
    
    void setAmpliferState(bool ampEnableState) {
      if ( ampEnableState ) {
        digitalWrite(PROP_AMP_ENABLE, HIGH);    // Enable Amplifier
      } else {
        digitalWrite(PROP_AMP_ENABLE, LOW);    // Disable Amplifier
      }
    }
    
    void init_amplifier(void) {
      //Start Amplifier
      pinMode(PROP_AMP_ENABLE, OUTPUT);
      setAmpliferState(true);
    }
    
    void setup() {
      //
      // Configure the pushbutton pins for pullups.
      // Each button should connect from the pin to GND.
      initButtonStates();
      setupBouncers();
      //
      initWakeupPins();
      //
      pinMode(LED_BUILTIN, OUTPUT);
      //Serial.begin(9600);
      while (!Serial);
      AudioMemory(8); //4
      delay(2000);
      Serial.println("start...");
    
      // Start SerialFlash
      if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1) {
          Serial.println ("Cannot access SPI Flash chip");
          delay (1000);
        }
      }
    
      //Set Volume
      mixer1.gain(0, 0.5);
      mixer1.gain(1, 0.5);
    
      init_amplifier();
    
      Serial.println("ready...");
    }
    
    void playFile(const char *filename)
    {
      SerialFlashFile ff = SerialFlash.open(filename);
      Serial.print("Playing file: ");
      Serial.println(filename);
    
      uint32_t sz = ff.size();
      uint32_t pos = ff.getFlashAddress();
    
      // Start playing the file.  This sketch continues to
      // run while the file plays.
      playMp31.play(pos,sz);
    
      // Simply wait for the file to finish playing.
      /*
      while (playMp31.isPlaying()) {
        yield();
      }
      */
    }
    
    
    
    // JUST A LITTLE CHANGE:  Just put in the buttons on this one. But. It looks like the whole thing will delay until the file is done playing.
    // That means the buttons should be useless until the sound is done.
    // One way to fix that is to quit using the call to yield() above. Eliminate the loop.
    // Again, the stops might have to be uncommented.
    
    elapsedMillis gt_activityTimeout = 0;
    
    bool activityTimeout(void) {
      if ( gt_activityTimeout > HIBERNATE_DELAY ) {
        return(true);
      }
      return(false);
    }
    
    void actvityRefreshTimer(void) {
      gt_activityTimeout = 0;
    }
    
    void actvityWakeup() {
      delay(PINTER_DELAY);
      actvityRefreshTimer();
    }
    
    
    void triggerAwake(void) {
    
      if ( !playMp31.isPlaying() ) {
        if ( activityTimeout() ) {
          digitalWrite(LED_BUILTIN, LOW);
          Serial.println("going to sleep...");
          setAmpliferState(false);
          delay(100);
          //Snooze.sleep( config );
    
          Serial.print(gt_activityTimeout);
          Serial.print(" ");
    
          elapsedMillis timeout = 0;
    
          Serial.println(gt_activityTimeout);
          // bounce needs to call update longer than the debounce time = 5ms,
          // which is set in constructor.
          while (timeout < 10)  buttonUpdates();
          //
          Snooze.hibernate( config );
          //Snooze.sleep( config );
          //
          actvityWakeup();
          setAmpliferState(true);
          Serial.println("Woke up");
          digitalWrite(LED_BUILTIN, HIGH);
        }
        // actually never really returns.
      } else {
        actvityRefreshTimer();
      }
    }
    
    
    
    
    void loop() {
      //
      triggerAwake(); // block on sleeping so does not have to be boolean
      if (  buttonSense() ) {
        actvityRefreshTimer();
    
        if ( buttons[0]) {
          playFile(sounds[0]);
    
        } else if ( buttons[1]) {
          playFile(sounds[1]);
    
        } else if ( buttons[2]) {
          playFile(sounds[2]);
    
        } else if ( buttons[3]) {
          playFile(sounds[3]);
    
        } else if ( buttons[4]) {
          playFile(sounds[4]);
    
        } else if ( buttons[5]) {
          playFile(sounds[5]);
    
        } else {
          // no selections
        }
      }
      //
    }
    The core of the code is the ability to use booleans to trigger the buttons and audio files, allowing me to use switches and buttons in combination.

    Again, any help is greatly appreciated!

Posting Permissions

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