Is this possible? Teensy 3.2 + Audio Shield + Lipo Charger + Lipo Fuel Gauge?

Status
Not open for further replies.

lerxstrulz

Well-known member
Hey guys,

I've been working on converting a project that uses a Teensy 3.2 + Audio Adaptor to work on a lipo battery and have the lipo charger (https://www.adafruit.com/product/2124) connected and working fine. I really need to be able to tell how much voltage the battery has, but have not been able to find a reliable way to do that. I found a snippet from another thread that reads pin 39 and tried this code to start reading the battery once a minute and then decrease the interval it is read as the voltage gets lower:

Code:
/***
 * Main program loop
 */
elapsedMillis batteryMillis;
int batteryCheck = 0;   // set to 0 so that a check is done as soon as the loop starts (it will be reset.)
int minutes = 0;

// in mA
const int lowBatteryThreshold      = 3300;
const int criticalBatteryThreshold = 3100;
const int fatalBatteryThreshold    = 3000;

void loop() 
{

    // every 5 minutes
  if (batteryMillis >= batteryCheck) {
    batteryMillis = 0;
    // ready mA
    int mv = 1195 * 4096/analogRead(39);
    if (mv <= fatalBatteryThreshold) {
      // battery almost dead...go to sleep!
      audioShield.unmuteHeadphone();
      audioShield.unmuteLineout();
      // plays a WAV file to notify user it is shutting down
      long l = playSound(SHUTDOWN_WAV);
      delay(l+500);
      // turn everything back off
      audioShield.muteHeadphone();
      audioShield.muteLineout();
      MUTED = true;
      // Need to wait a second...
      delay(1000);
      // see this method below
      gotoSleep();
    } else if (mv <= criticalBatteryThreshold) {
      // battery really low...change check time to 10 seconds
      batteryMillis = 0;
      int batteryCheck = 10000;
      // warn user battery is critically low and about to die
      long l = playSound(CRITICAL_BATTERY_WAV);
      delay(l+500);
      // turn off all sound in case the battery dies
      // before the fatal check
      audioShield.muteHeadphone();
      audioShield.muteLineout();
    } else if (mv <= lowBatteryThreshold) {
      batteryCheck = 60000;
      // warn user battery is low
      playSound(LOW_BATTERY_WAV);
    } else {
      // set to 1 minute
      batteryCheck = 60000;
    }
  }
  
}

/********************* go to deep sleep *********************/
#define SMC_PMPROT_AVLLS_MASK   0x2u
#define SMC_PMCTRL_STOPM_MASK   0x7u
#define SCB_SCR_SLEEPDEEP_MASK  0x4u

// see SMC section (e.g. p 339 of K66) 
#define VLLS3 0x3  // RAM retained I/O states held
#define VLLS2 0x2 // RAM partially retained
#define VLLS1 0x1 // I/O states help
#define VLLS0 0x0 // all stop

#define VLLS_MODE VLLS0
void gotoSleep(void)
{  
//  /* Make sure clock monitor is off so we don't get spurious reset */
//   MCG_C6 &= ~MCG_C6_CME0;
   //
   /* Write to PMPROT to allow all possible power modes */
   SMC_PMPROT = SMC_PMPROT_AVLLS_MASK;
   /* Set the STOPM field to 0b100 for VLLSx mode */
   SMC_PMCTRL &= ~SMC_PMCTRL_STOPM_MASK;
   SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x4); // VLLSx

   SMC_VLLSCTRL =  SMC_VLLSCTRL_VLLSM(VLLS_MODE);
   /*wait for write to complete to SMC before stopping core */
   (void) SMC_PMCTRL;

   SYST_CSR &= ~SYST_CSR_TICKINT;      // disable systick timer interrupt
   SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;  // Set the SLEEPDEEP bit to enable deep sleep mode (STOP)
   asm volatile( "wfi" );  // WFI instruction will start entry into STOP mode
   // will never return, but call ResetHandler() in mk20dx128.c
}
// END

I do not get consistent results with this. Sometimes it works fine, sometimes the battery just drops off without warning. Sometimes the Teensy will not go into sleep mode. (The other problem with this is that I cannot tell when the battery is being charged....)

So I got this:

https://www.sparkfun.com/products/10617

But I am not sure how it should go into the setup, or if it will even work. It uses the SDA and SCL pins (18 & 19) to communicate to the Teensy, which are already in use by the Audio Adaptor. However, according to the Teensy schematic, there is another set of pins (16 & 17) that it could possibly use? (see PINOUTS section here https://www.sparkfun.com/products/10617)

If that's the case, I'm pretty sure I would plug the battery into the charger, then run the VCC/GND to the fuel gauge and then out to the Teensy, correct? Has anyone done something like this before? I am using 500mAh batteries and need the 500mAh recharge rate. I saw another board on Tindie that handles the charge, but it does not have a status pin.

Any ideas appreciated! Thank you!

20170801_213443 (1).jpg
 
Last edited:
LiPos have a very flat curve while being discharged. The go pretty quickly from 4.2V to 3.7V, and then stay at 3.7V or thereabouts for a long time. Then, once discharged, they quickly drop off; you may have seconds to spare once it goes below 3.5V. This also depends on the battery capacity and the specific amount of load you draw.

To get the voltage of the battery, a high-resistance voltage divider (1 MOhm or more) is recommended, with a capacitor in the middle of the divider parallel to the analog input pin. (100 nF would be fine.) Ideally, you need some way of turning off the battery once you detect under-voltage (such as with a MOSFET) because otherwise the divider will keep drawing power from the battery until the battery drains to dead.

To know whether you're being charged, you could hook a diode from the charging input port to the actual circuitry, and then hook a 47 kOhm resistor from before that diode (Anode) to a 3.3V Zener to ground, and detect the voltage at the Zener as a "charging connected."
 
So I got this:

https://www.sparkfun.com/products/10617

But I am not sure how it should go into the setup, or if it will even work. It uses the SDA and SCL pins (18 & 19) to communicate to the Teensy, which are already in use by the Audio Adaptor. However, according to the Teensy schematic, there is another set of pins (16 & 17) that it could possibly use? (see PINOUTS section here https://www.sparkfun.com/products/10617)

The audio adapter uses pins 18 and 19 as a standard i2c bus. You can hook multiple devices to a i2c bus as long as each device has a unique address. The audio adapter uses a SGTL5000 at address 0x0A and a WM8731 at address 0x1A. As far as I can tell, the i2c address of the fuel gauge is 0x36, so it will not interfere with either of the i2c devices used by the audio adapter.

Since the audio adapter supports i2c devices, it provides the pull-up resistors Teensy needs for i2c, so you don't need to do anything there.

However, I took a look at the so-called code that Sparkfun provides, and it is a mess. The author decided to write their own i2c driver, using the AVR ports directly instead of using the Wire library abstraction that is common to the higher end AVR systems like the Arduino UNO. So, it may work, or it may not on Teensy. Paul has a bunch of things to support importing code from AVR systems, but I don't know if it is complete enough to run the Fuel Gauge. Hopefully somebody has rewritten the library using the Wire library.
 
As you can tell I had to put this project down for quite a while and am just now able to resume it ;)

After a bit of more research, I found this:

https://www.sparkfun.com/products/13777

which is a charger/monitor in one. They have an Arduino library:

https://github.com/sparkfun/Battery_Babysitter

And it looks like their lib is using Wire for the I2C connections:

https://github.com/sparkfun/Battery_Babysitter/blob/master/Libraries/Arduino/src/SparkFunBQ27441.cpp

I ordered one of these and when it arrives I'll start experimenting. Since space is limited in the enclosure I want to stuff all this into, I may look at taking the code for the Battery Babysitter and seeing if I can get it to work with the Fuel Gauge.

Thanks for the help and suggestions! I'll post updates once I get started.
 
I am trying my setup with the separate charger and lipo fuel gauge. I have it all connected, and the battery charges and powers the teensy+audio adaptor just fine. I also found this code:

http://www.lucadentella.it/en/max17043-libreria-per-arduino/

That will work with the MAX17043 chip that's on the fuel gauge. However, when I check the battery in code, it says it has 256% charge and 5.0 volts. Apparently I have something wired up wrong lol.

UPDATE: Actually, it's not reading from the fuel gauge at all. I disconnected the SDA and SLC cables and am still getting the same readings, which means it's reading from the SDA/SLC connected to the Audio Adaptor :/
 
I got this working using a Teensy 3.2 with Audio Adaptor, the lipoly backpack from Adafruit and the Lipo fuel gauge from Sparkfun.

You have to set the SDA and SLC pins using the Wire library:

Wire.setSDA(17);
Wire.setSCL(16);
Wire.begin();



And you have to do it AFTER initializing the Audio Adapter. It is working great and the library in the previous post works great and telling me how much charge is left as well as voltage!
 
Status
Not open for further replies.
Back
Top