Teensy 3.2 and reference voltages

Status
Not open for further replies.

sremick

Member
First , I knew nothing.
Then I read a lot, and felt I understood.
Then I read more, and became more uncertain/confused than ever.

So I appeal to help here.

I have a Teensy 3.2 I'm using for this project. It wants 5VDC in but its logic runs at 3.3V. This makes me confused about the reference voltage options.

For analogReference()...

DEFAULT... normally this would be Vin, however Vin is 5V which is out of bounds for the Teensy 3.2's ADC and AREF which must be 3.3V or lower. So is "DEFAULT" 3.3V? How accurate and how stable is the Teensy's 3.3V voltage converter?

INTERNAL... I believe this is 2.56V on the Teensy 3.2, correct? How stable and accurate is this? How is this even relevant considering everything else on the Teensy is working w/ 3.3V? Is the assumption that if you choose "INTERNAL" that you are then externally limiting the range being read on the ADC pin to 0-2.56V?

EXTERNAL... all I'm certain here is that it must be 3.3V or lower. I thought I understood how to use this but no longer, and perhaps I don't need to if DEFAULT (possibly) or INTERNAL (unlikely) end up being good enough for me. At first I thought I could just send it the 3.3V from my external voltage converter, but it seems that one also needs to use a resistor/diode/shunt or something. But it's the external 3.3V that is providing the voltage through the stuff that the ADC pin is reading so maybe I should really try to use this as my external AREF.

For all of the above... what's the way in code to read and use the measured reference voltage, regardless of source? That way if it's at least STABLE, if not "accurate", that can be compensated for. I found this code, but it gets into mux-voodoo that is above my current expertise. It does not run as-is and I don't know what'd be necessary to fix it:

Code:
// Read the analog value of an external voltage at the AREF pin.
//
// Warning: Do no use this sketch !
//
// This sketch is when an external voltage is supplied to the AREF pin.
// That is a very rare situation.
//
// Warning: using an external voltage at AREF might cause an
// internal shortcut when analogRead() is called before the
// reference is set to external.
//

void setup() {
  Serial.begin (9600);
  Serial.println ("\nRead voltage at AREF pin");

  analogReference (EXTERNAL);
}

void loop() {
  float voltage = readAref();
  Serial.println(voltage); 
  delay(1000);
}


//
// Function readAref
//
// Reads AREF (when external voltage is supplied).
// When the AREF pin is open, a value of 1.1V is returned.
// This function is only valid for a voltage at AREF of 1.1 to 5V.
//
// The calculations can be translated for integers to prevent
// use of float.
// Only for the Arduino Uno, Nano, Pro Micro at this moment.
// Experimental, no guarantees.
// public domain
//
float readAref (void) {
  float volt;

#if defined (__AVR_ATmega8__)
#elif defined (__AVR_ATmega168__)
#elif defined (__AVR_ATmega168A__)
#elif defined (__AVR_ATmega168P__)
#elif defined (__AVR_ATmega328__)
#elif defined (__AVR_ATmega328P__)

  // set reference to AREF, and mux to read the internal 1.1V
  // REFS1 = 0, REFS0 = 0, MUX3..0 = 1110
  ADMUX = _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
 
  // Enable the ADC
  ADCSRA |= _BV(ADEN);

  // Wait for voltage to become stable after changing the mux.
  delay(20);

  // Start ADC
  ADCSRA |= _BV(ADSC);

  // wait for the ADC to finish
  while (bit_is_set(ADCSRA,ADSC));

  // Read the ADC result
  // The 16-bit ADC register is 'ADC' or 'ADCW'
  unsigned int raw = ADCW;

  // Calculate the Aref.
  volt = 1.1 / (float) raw * 1024.0;

#elif defined (__AVR_ATmega32U4__)
#elif defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__)
#endif


  // Try to return to normal.
  analogReference(EXTERNAL);
  analogRead(A0);            // the mux is set, throw away ADC value
  delay(20);                 // wait for voltages to become stable

  return volt;
}
Source: https://forum.arduino.cc/index.php?topic=267827.0

And finally: is bumping the resolution to 12 bits really as simple as using analogReadRes(12)? (from what I read, 13-bit isn't reliable?). But analogReadAveraging() only works w/ 8 or 16-bits, right? So if I wanted to average at 12 bits, do I read and average at 16 bits and discard the last 4 bits?
 

I did see that page but only a bit was applicable. It doesn't mention the Teensy 3.2, only the 3.1, 3.0, 2.0 and 1.0. And I've already learned that the 3.2 is different in important and notable ways than the 3.1 and earlier.

Trust me, I did do a lot of forum searching. That's how I've learned the amount that I think I do know at this point and I know a ton more about reference voltages, Teensy pins and general electronics than I did 24h ago. But despite combing through the 30+ some odd threads I read through, specific questions remain and some things are unclear for me, hence this post. It's important to ask, since a lot about using AREF can destroy your Teensy if you do it wrong.
 
I did see that page but only a bit was applicable. It doesn't mention the Teensy 3.2, only the 3.1, 3.0, 2.0 and 1.0. And I've already learned that the 3.2 is different in important and notable ways than the 3.1 and earlier.

Trust me, I did do a lot of forum searching. That's how I've learned the amount that I think I do know at this point and I know a ton more about reference voltages, Teensy pins and general electronics than I did 24h ago. But despite combing through the 30+ some odd threads I read through, specific questions remain and some things are unclear for me, hence this post. It's important to ask, since a lot about using AREF can destroy your Teensy if you do it wrong.

For ref - the Teensy 3.2 IS a Teensy 3.1 - the only real world diff was changing the onboard LDO for higher current IIRC - that and I think the bootloader chip was changed to a new common more available family unit.

But from a user and functional perspective - the MCU and nothing about it changed. Any notes ( except notes above ) for T_3.1 apply to the T_3.2 ( and vice versa ).
 
For ref - the Teensy 3.2 IS a Teensy 3.1 - the only real world diff was changing the onboard LDO for higher current IIRC - that and I think the bootloader chip was changed to a new common more available family unit.

But from a user and functional perspective - the MCU and nothing about it changed. Any notes ( except notes above ) for T_3.1 apply to the T_3.2 ( and vice versa ).

That's great information, thank you
 
Not quite done with this yet. Still need some assistance.

So I had been giving AREF the 3.3V from the same source that was going into the resistors I was measuring (as a template). I was getting moderate accuracy but from what I learned, I was using AREF wrong and probably didn't need to use it at all. So I changed from analogReference(EXTERNAL) to analogReference(DEFAULT) which from what I understand should still be a 3.3V value, but now my numbers for resistance are WAY off. So basically, doing it "wrong" gave me good numbers, doing it "right" gives me bad numbers. I'm missing something fundamental here. :(

And the pending question remains: is there a way to read the actual reference voltage to then use that value within the code? This would be important and helpful (and in this case, very useful to double-check that "DEFAULT" is really giving me 3.3 and not something unexpected).

Here's the relevant code segment:
Code:
  aReadVal = analogRead(A10) * (refV / 1024.0); //this produced the voltage
  aReadVal = 5000 * (1/((refV/aReadVal)-1)); // resistor 2 value. First # is R1 value.
  
  Serial.println(aReadVal);

refV is
Code:
#define refV 2.56
earlier.

These formulas came from studying the exercise at: https://arduino.stackexchange.com/q...ion-about-resistance-measurement-with-arduino
...and had been providing closely-accurate values when just idiotically sending 3.3V straight into AREF with no diode or anything.
 
Status
Not open for further replies.
Back
Top