How to use 3xAA Batteries with Teensy 3.2

Status
Not open for further replies.

dash4g

Member
In a nutshell, I am trying to change the voice of toys to a different language.

6edPYaR.png

There are many toys I am hoping to change, but I am looking to re-purpose the:
Battery pack (often 3x AA batteries)
Built-in speaker
Inputs (buttons, switches)

I have a project which uses a prop shield LC, using the on board memory and audio outputs. I have imported duff's snooze library and Frank B's MP3 example. I have also lowered the clock speed to 24mHz. The aim is to have a longer lasting setup that can play audio files based on pin inputs. The project is outlined here.

I can get the code to work just fine playing files and pulling data from the prop shield while plugged into the USB, however once I unplug the usb and attach my power source (3x AA batteries in series) the teensy is unresponsive.

I was wondering if anyone has any ideas on how to proceed to use my power source of 3xAA batteries.

I have been looking at regulators, but again, the aim is to have a lot of standby time and be able to wake up and play an audio file simply, and I can't see anything that might be very efficient.

Any help 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 <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
    }
  }
  //
}
 
Not sure I'm understanding it well, but you can connect 3x1.5V batteries directly to the Vin pin of the LC.
When fully charged, 3xAA alkaline batteries give you 4.8V; when almost empty, they may give you 3.1-3.2V.
The range is acceptable for Vin (yes, specs say min voltage is 3.6V, but it works well even at 3.2V).
 
Thank you for that XFer!

After testing the batteries... by my calculations, I should only see 4ish days out of this code and batteries. Not really ideal, as I was hoping to get months. The slopes of the voltages are attached. I suspect it may be the brand of batteries, as these were very cheap batteries.

I will report back with a usage of some Energizer Ultimate Lithiums...

2019-05-14 21_56_31-Book1 - Excel.png
 
Thank you for that XFer!

After testing the batteries... by my calculations, I should only see 4ish days out of this code and batteries. Not really ideal, as I was hoping to get months. The slopes of the voltages are attached. I suspect it may be the brand of batteries, as these were very cheap batteries.

I will report back with a usage of some Energizer Ultimate Lithiums...

Take a look on Snooze library for low power.
You should put teensy in low power state, when no button is pressed and no mp3 is played.
Then you migth achieve weeks or month battery lasting.
 
Take a look on Snooze library for low power.
You should put teensy in low power state, when no button is pressed and no mp3 is played.
Then you migth achieve weeks or month battery lasting.

Duff's snooze library? In the above code, it is implemented...but I wonder if there is some tweaking to be done to hone it in...
 
In another thread, someone was asking about a circuit activated by a vibration sensor but kept energized for the duration of a timer.

I wonder if it would make sense to only power the teensy after a button was pressed? Or maybe use a vibration sensor with a timer to power up the teensy when the toy was moved, but timeout relatively quickly.
 
Duff's snooze library? In the above code, it is implemented...but I wonder if there is some tweaking to be done to hone it in...

Ahh didn't see Snooze is already involved.
I do not know your external circuit, but I see in the code nothing in hibernate mode, the power supply for it interrupts.
 
I was wondering if anyone has any ideas on how to proceed to use my power source of 3xAA batteries.

Following good advice elsewhere, I have found optimal battery life from 4 x AA LiFe batteries (about 6.7 V when new) coupled to a Polulu D24V5F5 step-down 5V voltage regulator. Once the combined voltage of the LiFe battery pack falls below the drop-out voltage of the regulator, it is already in steep decline. Equivalent step-down/step-up regulators have appreciably higher quiescent current drain, so they aren't worthwhile.

From what others have said here, you might get away with 3 x LiFe batteries and a 3.3 V step-down regulator.

I also use sleep mode as much as possible, and cut power to accessories using a MOSFET which is a very small additional component.

Hope this helps.
 
Ahh didn't see Snooze is already involved.
I do not know your external circuit, but I see in the code nothing in hibernate mode, the power supply for it interrupts.

The circuit I have is basically the following:

2019-05-16 22_10_35-Window.png

Except the buttons are going to ground not positive.

I will admit I had some help getting someone to impliment Duff's snooze library. My focus is on the loop and getting the files to play after pressing a button.

I am wondering if there is someone who may be able to point me in the direction of implementing the Hibernate portion of Duff's snooze library. But I was also under the assumption that:

#define HIBERNATE_DELAY 300000

Automatically initiated hibernate after 300000ms. obviously I am wrong in this.

I don't necessarily want to start a new thread, but I suspect this may be a better problem solved in project -advice?

Any help is greatly appreciated; thanks in advance!
 
The circuit I have is basically the following:


Except the buttons are going to ground not positive.

I will admit I had some help getting someone to impliment Duff's snooze library. My focus is on the loop and getting the files to play after pressing a button.

I am wondering if there is someone who may be able to point me in the direction of implementing the Hibernate portion of Duff's snooze library. But I was also under the assumption that:

#define HIBERNATE_DELAY 300000

Automatically initiated hibernate after 300000ms. obviously I am wrong in this.

I don't necessarily want to start a new thread, but I suspect this may be a better problem solved in project -advice?

Any help is greatly appreciated; thanks in advance!

The circuit you posted can not match the one for which the code was written because there is no flash memory and no audio amplifier.
It is correct that hibernate enters after 5 minutes if no key is pressed and no mp3 is played.
Since you do not seem to have an overall understanding of the circuit and the code, I recommend you to work yourself in small steps.
 
Yes, my apologies. I have posted in different forums and I had forgot to mention that this is being used with a Prop Shield LC.

The LC is married-up, pin for pin exactly as shown on the PJRC shield portion of the store:
propLC.png

The difference from that image being that I am using a Teensy 3.2 and a Prop Shield LC.

This allows me to not only utilize the on board memory of the LC, but also the speaker output in the form of the DAC.

On top of that, are the buttons as shown in the post above.

So, just to reiterate that: Duff's snooze library is implemented correctly with hibernate?

I wonder where I can start chasing the 'power drain gremlins' if you will. Right now, my number 1 suspect are the cheap batteries that are being used for testing. They are the batteries which came with the toys and seem very cheap.
 
I don't have the time to scrutinize your code, but seems OK to me.

Anyway, you should perform a few calculations vs. power usage, to estimate battery duration consistently.

Teensy 3.2 at 72 MHz (default clock) draws about 35 mA while running and about 0.35 mA in Hibernate if you don't (explicitely) shut off all the unneeded peripherals and put all the unused pins in DISABLED mode.

Add to this the i2c bus draw (about 2 mA because of pullups), the Pro Shield draw and whatever else you are powering from the 3xAA battery pack (audio amp? Leds?).

Consider that a cheap 3xAA battery pack may offer 800-1000 mAh (maybe less for a very cheap nobrand).
 
Status
Not open for further replies.
Back
Top