Teensy 3.2 with Adafruit Featherwing Adapter - Battery voltage reading too low

Status
Not open for further replies.

spiff72

Member
This feels like a total noob question, but it is driving me crazy that I can't figure out the problem here. I am trying to get the Teensy to measure the battery voltage with a Lipo attached, with to the Featherwing adapter and I keep getting a value from the Teensy that is too low.

I even wired up an external voltage divider and still get the same low result (roughly 3.8-3.9 volts when it should be around 4.2).

I measured actual voltages at the A7 pin (when using the internal divider from the Featherwing adapter), and I get the expected 2.1v reading.

I grabbed the example code from the FeatherOLED and modified it slightly (since the micro isn't recognized, it would default to an "unknown feather" message). I also pulled out all of the code relating to the OLED to make sure something odd wasn't happening there.

I pulled out all of the if statements that determine the feather type, and just defined the battery pin as A7 (the center of the voltage divider). I even modified it to serial print each step of the battery voltage calculation, and the raw reading is coming in low.

My gut is telling me that I am missing a #define statement that would tell the code that this is a teensy 3.2, or there is something amiss with my analog reference voltage. The AREF pin reads 3.3v when I check it. Alternately, I could have a solder issue, but I inspected the solder joints under a microscope and can't see anything that looks "off".

I also ran a separate test the does an analogwrite() which slowly increments in value and an analogwrite() reads those values (connecting A14/DAC to A0). That works perfectly fine (raw values of the read are close to the write value), so I think this is a glitch in my code below.

Finally, I also ran the "battery" example from the FeatherOLED library "as-is" on a Feather328 with the same OLED plugged into it and it gave accurate battery voltage values.

What am I missing here?

I copied a sequence of the serial output below the code. The values are very similar if using my external resistor divider, too (pin A0).

Code:
// Adafruit OLED FeatherWing Battery Example
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Written by Todd Treece for Adafruit Industries
// Copyright (c) 2016 Adafruit Industries
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.



// integer variable to hold current counter value
int count = 0;

void setup()
{
  Serial.begin(115200);
  //analogReadResolution(12);

}

void loop()
{

  float battery = getBatteryVoltage();


  // increment the counter by 1
  count++;

  // delay 1 second (1 second == 1000 milliseconds)
  delay(1000);

}
  #define VBATPIN A7
  #define EXTVBATPIN A0

  float getBatteryVoltage() {

    float measuredvbat = analogRead(EXTVBATPIN);
    Serial.print(measuredvbat);Serial.print(" ");
    measuredvbat *= 2;    // we divided by 2, so multiply back
    Serial.print(measuredvbat);Serial.print(" ");
    measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
    Serial.print(measuredvbat);Serial.print(" ");
    measuredvbat /= 1024; // convert to voltage
    Serial.println(measuredvbat);
    return measuredvbat;

  }

Serial Output Example:
Code:
598.00 1196.00 3946.80 3.85
567.00 1134.00 3742.20 3.65
602.00 1204.00 3973.20 3.88
589.00 1178.00 3887.40 3.80
556.00 1112.00 3669.60 3.58
583.00 1166.00 3847.80 3.76
596.00 1192.00 3933.60 3.84
589.00 1178.00 3887.40 3.80
582.00 1164.00 3841.20 3.75
571.00 1142.00 3768.60 3.68
587.00 1174.00 3874.20 3.78
599.00 1198.00 3953.40 3.86
588.00 1176.00 3880.80 3.79
596.00 1192.00 3933.60 3.84
595.00 1190.00 3927.00 3.83
599.00 1198.00 3953.40 3.86
564.00 1128.00 3722.40 3.64
596.00 1192.00 3933.60 3.84
582.00 1164.00 3841.20 3.75
580.00 1160.00 3828.00 3.74
586.00 1172.00 3867.60 3.78
587.00 1174.00 3874.20 3.78
588.00 1176.00 3880.80 3.79
 
I'm not an EE, but the schematic does show a diode hanging off of VBAT --- that would be about a 0.4v drop.
 
Thanks for the response.

I am not an EE, either, and I see that in the schematic, too. That appears to be a reverse polarity protection schottky diode.

What I am measuring with a voltmeter, I get voltage values that I would expect to see when probing at the Vbat and at Pin A7 (half of Vbat).
 
I recall when I first got the Featherwing adapter that I did some measurements between the Featherwing adapter comparing it to the Onehorse lipo charger. It took some digging, but it was in this post:

I'm a computer programmer, not an EE, but the featherwing does not depend on the VUSB->VIN trace being cut like some of the other chargers (like Onehorse's) do. I believe this means, that internally, the featherwing has a MOSFET that enables drawing power from the battery when there is no power on VIN, while on chargers that require the VUSB->VIN trace being cut, the power always goes through the charger before getting to the Teensy. The featherwing charger does have to draw some power to check the battery voltage level, and apply charging.
 
I recall when I first got the Featherwing adapter that I did some measurements between the Featherwing adapter comparing it to the Onehorse lipo charger. It took some digging, but it was in this post:

I'm a computer programmer, not an EE, but the featherwing does not depend on the VUSB->VIN trace being cut like some of the other chargers (like Onehorse's) do. I believe this means, that internally, the featherwing has a MOSFET that enables drawing power from the battery when there is no power on VIN, while on chargers that require the VUSB->VIN trace being cut, the power always goes through the charger before getting to the Teensy. The featherwing charger does have to draw some power to check the battery voltage level, and apply charging.

Thanks! I think I found the relevant post:
https://forum.pjrc.com/threads/4523...add-on-for-3-2?p=159836&viewfull=1#post159836

I have two questions:
- For that feather adapter, were you measuring the voltage (with a meter) on the Vin Pin of the Teensy? From the schematic, this looks like it would be on the other side of diode D4 relative to the Vbat pin.
- Have you ever tried running code similar to what i had in the OP? The "battery" example from the FeatherOLED library that i adapted it from would state "Unknown Feather" in the stock form.

It just seems odd that they would build that voltage divider into this adapter board which is specifically designed to allow adaptation of Teensy to use the other featherwings (including the OLED). This makes me think I am just not coding this correctly, or I am missing something that should be super-obvious.

The fact that I can run code that perfectly reads the output of the DAC with analogRead commands (albeit on a different pin) makes me think that there is nothing wrong with the teensy. Maybe I just have an odd solder bridge that I just can't see.
 
Thanks! I think I found the relevant post:
https://forum.pjrc.com/threads/4523...add-on-for-3-2?p=159836&viewfull=1#post159836

I have two questions:
- For that feather adapter, were you measuring the voltage (with a meter) on the Vin Pin of the Teensy? From the schematic, this looks like it would be on the other side of diode D4 relative to the Vbat pin.
- Have you ever tried running code similar to what i had in the OP? The "battery" example from the FeatherOLED library that i adapted it from would state "Unknown Feather" in the stock form.
It's been a year or two since I did the measurements, so I don't remember. But I'm about to solder up another featherwing for use with my 3.6, so if I think about it, I will try to re-measure it.

I have never read A7 to get the battery voltage. I just have marks in my large spreadsheet to avoid A7 with the featherwing.

It just seems odd that they would build that voltage divider into this adapter board which is specifically designed to allow adaptation of Teensy to use the other featherwings (including the OLED). This makes me think I am just not coding this correctly, or I am missing something that should be super-obvious.

They actually build a voltage divider into all feather boards that have more than one analog input. Here is a table comparing the various feather devices that I have in my large microprocessor spreadsheet. Once you have opened it, go to the "Feather" or "Featherwing" sheets:

The fact that I can run code that perfectly reads the output of the DAC with analogRead commands (albeit on a different pin) makes me think that there is nothing wrong with the teensy. Maybe I just have an odd solder bridge that I just can't see.
Perhaps.
 
Wow - that's a cool spreadsheet - I filed that one away for future reference!

I am still second guessing myself and the code. I forgot until just now that I tried the code using 2 different pins (A7 and A0 with my external divider) for the analogRead and got the same result, so I am thinking it isn't a solder bridge. But I will do some more tinkering and try to troubleshoot some more.
 
With a Teensy 3.2 running the blink program with a featherwing adapter, a Teensy prop shield attached, no USB, and a freshly charged li-po battery:
  • The battery itself measured 4.1 volts;
  • The VIN pin on the Teensy measured 3.9 volts;
  • The 3.3v pin on the Teensy measured 3.25 volts;
  • The 3.3v pin on the featherwing adapter measured 3.25 volts (2nd pin on the 16 pin side);
  • The battery pin on the featherwing adapter measured 4.1 volts (1st pin on the 12 pin side);
  • The USB pin on the featherwing adapter measured 3.9 volts (3rd pin on the 12 pin side);
  • The Teensy A7 pin measures 2.05 volts (sometimes 2.04).

So on my featherwing adapter at least, the voltage divider did measure roughly 1/2 of the battery voltage. The voltage pin read the same voltage. The VIN pin to the Teensy read 3.9 volts, which is presumably from the MOSFET that prevents the battery from providing power if there is already power on the VIN pin.

On an Adafruit feather 4 Express (ATSAMD51J19 chip inside), using the same battery, I get:
  • The 3.3v pin (2nd pin on the 16-pin side) measured 3.25 volts;
  • The battery pin (1st pin on the 12-pin side) measured 4.1 volts;
  • The USB pin (3rd pin on the 12-pin side) measured 3.6 volts.

Just to be clear, I used a voltage meter to measure the voltage. I did not do an analogRead on the A7 (Teensy). As far as I can tell, the M4 Express does not have an analog pin with a voltage divider.
 
Just to be clear, I used a voltage meter to measure the voltage. I did not do an analogRead on the A7 (Teensy). As far as I can tell, the M4 Express does not have an analog pin with a voltage divider.

The M4 express does have a divider on A6 (VDIV).

I see no MOSFET on adafruit teensy feather adapter schematic
https://raw.githubusercontent.com/a...-3.x-Feather-Adapter-PCB/master/schematic.png

i'm assuming we're talking about this adapter
https://www.adafruit.com/product/3200
(I don't have one to test ...)
Since post #1 sketch is using Serial.print, I assume both USB and lipo battery are attached.
 
Last edited:
I see no MOSFET on adafruit teensy feather adapter schematic

Correct - all that is there is the D4 diode, which I don't think should cause a voltage drop unless you are measuring Vbus (instead of Vbat).

Just to re-iterate what I am seeing, all voltages (when checked with a meter) are as I would expect them. Fully charged lipo is reading about 4.19 V, and the center of BOTH of the voltage dividers reads half of that battery voltage (A7 pin on teensy, which is connected to the internal divider, and the A0 pin, which I made the external divider with another pair of 100k resistors).

The analogread is what is acting up. Last night I was probing the 3.3 v line and the ground line of the teensy with the A0 pin running the same code as above. When doing this, I would get the expected readings of 1023 on 3.3v and 0 (or 1) on ground. So the analog read is working fine there.

As another test I programmed a second Teensy with the same code, which wasn't on a feather adapter. I plugged the battery into the feather adapter mounted teensy, connected the grounds of the two teensy's together, and measured the voltage on the divider with a jumper from the "loose" teensy to the battery feather Teensy. Exact same results - the analogread values are running low.

So I am thinking that there is something screwy in my soldering job. I am going to try a similar test using the loose teensy and an extra teensy adapter board with nothing plugged into it but the battery (no teensy connected to it) and probe the voltages with analogread that way. I think this will let me rule out a soldering issue on the current assembly I have
 
So i did one more check with a meter to double check a few things...

I checked the Vbus pin without the USB connection (battery only) and I get about .2 volts less than the reading from Vbat - which makes sense based on the schematic linked above - that schottky diode should drop about .2V.

I also disconnected my external resistor divider just to make sure that wasn't throwing things off. I think I am just stumped at this point until I can get my hands on another teensy adapter on monday to try the experiment i described above with a standalone adapter and separate teensy. If that one works "normally" and I get reasonable values for the analogread values, I will just chalk it up to a bad board or a bad solder joint.

If the same thing continues to happen, I will be even more baffled by this behavior!

EDIT: One last thing. The same code runs perfectly on my Feather 328P with the OLED featherwing (with the divider pin changed from A7 to A6).

This is the latest code I am running (for the Teensy):

Code:
// Adafruit OLED FeatherWing Battery Example
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Written by Todd Treece for Adafruit Industries
// Copyright (c) 2016 Adafruit Industries
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_FeatherOLED.h>

Adafruit_FeatherOLED oled = Adafruit_FeatherOLED();

// integer variable to hold current counter value
int count = 0;
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

void setup()
{
  Serial.begin(115200);
  //analogReference(EXTERNAL);
  //analogReadResolution(12);
  oled.init();
  oled.setBatteryVisible(true);
    // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop()
{

  // clear the current count
  oled.clearDisplay();

  // get the current voltage of the battery from
  // one of the platform specific functions below
  float battery = getBatteryVoltage();
  //Serial.println(battery);
  // update the battery icon
  oled.setBattery(battery);
  oled.renderBattery();

  // print the count value to the OLED
  oled.print("count: ");
  oled.println(count);

  // update the display with the new count
  oled.display();

  // increment the counter by 1
  count++;

  // delay 1 second (1 second == 1000 milliseconds)
  delay(1000);

}
  #define VBATPIN A7
  #define EXTVBATPIN A0

  float getBatteryVoltage() {
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(VBATPIN);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  float raw = average ;//* 2 * 3.3 /1024;
  float divider = raw * 3.3 / 1024;
  float measuredvbat = raw * 2 * 3.3 / 1024;
  // send it to the computer as ASCII digits
  Serial.print("Raw: ");
  Serial.println(raw);
  //Serial.print(" ");
  Serial.print("Divider ");
  Serial.print(divider);Serial.println(" V");
  Serial.print("Battery: ");
  Serial.print(measuredvbat);Serial.println(" V");Serial.println("");
  delay(1);        // delay in between reads for stability
  return measuredvbat;
  }

And a copy of the serial output from the Teensy (meter values for the Vbat and Divider were about 2.07 and 4.15 when this was output):
Code:
Raw: 573.00
Divider 1.85 V
Battery: 3.69 V

Raw: 570.00
Divider 1.84 V
Battery: 3.67 V

Raw: 566.00
Divider 1.82 V
Battery: 3.65 V

Raw: 562.00
Divider 1.81 V
Battery: 3.62 V

Raw: 563.00
Divider 1.81 V
Battery: 3.63 V

Raw: 561.00
Divider 1.81 V
Battery: 3.62 V

Raw: 561.00
Divider 1.81 V
Battery: 3.62 V
 
Last edited:
Well, I had a chance to try my latest experiment...

I just took a Teensy which is not mounted to a feather adapter, and a separate Teensy Feather adapter, plugged a lipo into the adapter.

I used the same code as above, and then connected the ground of the teensy to the ground of the adapter board, and ran a jumper from Teensy A7 to the pin location on the adapter board that would be connected if the Teensy was mounted.

I get virtually identical voltage values out of the Teensy with this setup when compared to the above values. I checked the voltage at this same point and it reads 2.08 with a meter (and the battery checks 4.16 volts).

So now I have no clue what is wrong here. The code properly reads the 3.3 volt signal from the 3.3 volt pins on the teensy and zero for the ground pin.

I made no modifications to this Teensy (other than soldering pin headers to it), and the adapter is brand new with no changes or soldering at all. So is this a code issue? Or a Teensy issue?? I am completely stumped at this point.

If anyone has any ideas, I am all ears!

Thanks!

EDIT: This Teensy actually has an oscillator for the RTC clock added. I don't recall if the first one had the RTC oscillator installed.
 
strange. can you post a photo of your post #12 setup ?
What version of IDE and teensyduino are you running?
 
strange. can you post a photo of your post #12 setup ?
What version of IDE and teensyduino are you running?

I will do that shortly. On a whim, I just used the same setup (minus the feather adapter) to check the voltage of a AA battery, and it reported 1.40 volts on the serial monitor (confirmed with a volt meter).

This makes me think there is something odd happening with the feather adapter. I may rig up something with the lipo and a standalone voltage divider to take the adapter out of the equation.
 
Here is a photo of the setup from #12. I had to put in a generic 128 x 64 OLED since I didn't have the featherwing OLED with me today.

The 1.84 value shown on screen is the voltage calculated at the divider center (between the 100K resistors in the schematic) (analogRead(A7) * 3.3 / 1024). The voltage shown next to the battery icon is double that voltage.

The versions I am using are:
ArduinoIDE: 1.8.8
TeensyDuino: 1.45

I tried reading the values of the two surface mount resistors on the adapter board, and they are 100k, but the Fluke meter takes a LONG time to read the values (one of them will start high - like 150k, and then slowly drop down). Is this due to the other components (some of the capacitors charging as I take the measurement)? Could this lead to the erroneous reading?

I tried a second time, and bypassed the feather adapter completely. Photo of this arrangement is shown as well (100k resistors use for the divider). SAME RESULT. I replaced the Lipo with a AA: the reading was low again. When I moved the A7 jumper to measure the full voltage drop across the pair of 100k resistors, then the reading (before the double) was accurate (1.40V).

So this is all leading me down the path of measuring the resistor values and making sure I don't have a poorly matched pair. I will post findings on this later. Obviously the values on the feather adapter can't be easily modified, but my standalone values can.
 

Attachments

  • 20190304_105827.jpg
    20190304_105827.jpg
    85.2 KB · Views: 93
  • 20190304_111724.jpg
    20190304_111724.jpg
    80.5 KB · Views: 113
I just measured the two 100k resistors at 99.0k and 98.6k, so they were close.

Just for grins, I threw a pair of 22k resistors in, and the value was much closer to the correct battery voltage (2.06 measured at the divider, and 4.13 calculated for the battery -- when it is 4.16 with a meter).

This is getting into EE territory now, but why would the divider using lower value resistors give a better reading??
 
I just measured the two 100k resistors at 99.0k and 98.6k, so they were close.

Just for grins, I threw a pair of 22k resistors in, and the value was much closer to the correct battery voltage (2.06 measured at the divider, and 4.13 calculated for the battery -- when it is 4.16 with a meter).

This is getting into EE territory now, but why would the divider using lower value resistors give a better reading??

If the divider is intended to provide a fraction of the signal voltage to an ADC input, then there is another concern in the design: In SAR converters, for a fixed sample rate, there is a maximum allowed external impedance connected on ADC input; in order to charge the sample capacitor with the proper voltage before the next sample. Otherwise, the measurement is useless. In this case, the impedance (resistance) is formed by the parallel of two divider resistors (Thevenin).
from https://electronics.stackexchange.c...o-choose-value-of-resistor-in-voltage-divider

analogReadAveraging(1);
might improve accuracy slightly
 
Interesting. I think you nailed it.

This might explain why the Teensy behaves differently than the Feather 328P that reads properly with the 100k divider - the analog pin might have different characteristics between the two architectures. I might have to do a bit of research around this when I get some free time. I just used a small electrolytic cap between ground and pin A7 (with the 100k resisitors) and this brought the reading up to where i would expect it to be. I found this after a bit of searching for "max impedance on ADC inputs for Teensy".

And my code above actually does a manual bit of analogReadAveraging (with 10 samples). I didn't realize that the Teensy had this capability built in. That makes for a much cleaner piece of code!

Thanks!
 
Problem solved! I put a small (1uF) on the board between pin A7 and ground, and that give me dead-on voltage values from the battery now. It does seem that the 100k resistors are just too high of a value for the Teensy 3.2.

Not my prettiest soldering work, but it gets the job done and I can stop thinking about this issue.
 

Attachments

  • my_photo-6.jpg
    my_photo-6.jpg
    81.6 KB · Views: 67
The Adafruit Feather M4 Express has this same problem. The 100K resistors in the voltage divider were fine for slower processors, but these newer chips are so fast that the sample and hold capacitor in the A/D converter doesn't have time to charge through the 100K resistor. Adding a capacitor on the input to the A/D solves that problem as does using smaller resistors in the voltage divider.
 
Status
Not open for further replies.
Back
Top