Analog voltage reading incorrect voltage on custom hardware

Hi Everyone, I'm hoping to get some help diagnosing some odd behavior. I have a custom PCB using the ATSAM3X8E and am using the arduino IDE to test functionality compiling for an arduino DUE. I am trying to troubleshoot a coolant temperature sensor. It is just a 10k thermistor with a simple voltage divider circuit where R1 = 4.99K and R2 is the thermistor.

I am getting odd behavior, even different between identical boards, in that for some reason on one board for example I read 2048 ( 1.65V) when the voltage is actually 3.3V and when I ground the wire I read 0. On another board I read 4092 (3.3V) when the input voltage to the analog pin is 3.3V but It reads 2300 (1.85V) when it is grounded. No resistor values seem to change the voltage reading, it is either 3.3V, 1.65V, or 0V depending on the board I'm testing. For instance, on the board which reads 3.3V when there is actually 3.3V on the pin, I added a 5k resistor for R2, which should give a 1.65V input to the pin but instead there was no change at all, still reading 3.3V

I'm including the schematics of the board and the code used to test. I would really appreciate any insight here, I'm pretty stumped.


Temp Sensor Test 1

#include <Arduino.h>
#include "config.h"

int Vo;
float R1 = 10000;
float logR2, R2, T;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

uint32_t timer;


void setup() 
{
    delay(3000); 
    SERIALCONSOLE.begin(115200);
    SERIALCONSOLE.println("Starting up!");
    
    timer = millis();
    
    pinMode(A7, INPUT);
    analogReadResolution(12);
}

void checkCoolantTemp() {
  int coolantTemp;
  Vo = analogRead(A7);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2*logR2*logR2));
  T = T - 273.15;
  coolantTemp = (int)T + 40;
  SERIALCONSOLE.print("Algorithm Measurement: ");
  SERIALCONSOLE.println(coolantTemp);
  SERIALCONSOLE.println("");
}

void loop() 
{
    if(millis() - timer > 2000){
      int reading = analogRead(A7);
      SERIALCONSOLE.print("Raw Sensor Reading: ");
      SERIALCONSOLE.println(reading);

      SERIALCONSOLE.print("Voltage Reading: ");
      SERIALCONSOLE.println(((float)reading / 4095.0)  * 3.3);

      SERIALCONSOLE.print("Calculated Resistance: ");
      SERIALCONSOLE.println( ((((float)reading / 4095)*3.3)*4999)/(3.3-((((float)reading / 4095)*3.3)))  ) ;
      SERIALCONSOLE.println("");

      //checkCoolantTemp();
      timer = millis();
      
    }

Which pin on your schematic is this referring to and is the sensor in a potential divider network ?

A7 is pin PA2 labeled "Coolant _Temp" in the schematic. On the accessory connector on the PCB, the Coolant_Temp trace is mapped to pin 4 and ground on pin 7 with a 4.99k pullup between PA2 and pin 4 on the connector.

I'm not entirely sure what you mean by divider network, but the sensor serves as R2 in a voltage divider circuit between pin PA2, 4.99k 3.3V pullup, and Ground.

For testing purposes I am not even using the actual thermistor, I am using known value resistors which should give me known voltage readings on PA2 but they are not working correctly.

Here is another find. This time i am reading all analog inputs and grounding the A7 pin and notice that the reading changes on both A7 and A11, both incorrect, but how are those pins related? Pin PB20 (A11) is unconnected on my PCB.
temp sensor test 3

If you have off board circuitry related to that input, please document it visually for us as well. Have you confirmed the input voltage at A7 with a DMM?

The only off board circuitry is the two wires which connect to Pins 4 and 7 on J104 which is a 10 pin molex mini-fit jr. I am using these two wires to manipulate what should be R2 between them both by just shorting them together which should get a 0 reading on PA2 or by using physical known value resistors to measure what PA2 reads vs what i know it should be based on the voltage divider.

I have confirmed with DMM that when all wires are unconnected (no connection between PA2 and Gnd) PA2 has 3.311V applied to it and reads 3.30V. When PA2 is grounded through pins 4 and 7 on J104, The voltage reading is 0.000V but the microcontroller is reading a value of 2300 or 2.47V

Am i missing some sort of internal pull up that could be causing an issue?

Or you have the wrong pins entirely... :slight_smile:

The Arduino documentation, from what I can tell, maps PA2 to Analog In 7. The ATSAM3X8E datasheet maps PA2 to pin 85 on the microcontroller which is how the PCB was made so unless I am missing something obvious, I'm not sure what you mean by the wrong pins entirely. I also physically ohmed out each pin counting up from #73 which is on the top left corner and confirmed that pin 85 was in fact the pin being used as PA2.

This appears to be the effective circuit of your sensor on PA2 so the mid point voltage is what is to be expected:

That is what I would expect but that is not what the MCU reads. If i place a 4.7k resistor in place of R2 (closest thing I have to 5k) I read 1.609V with the DMM but the MCU reads 3.3V.

R2 is meant to be a temperature sensor but I am using resistors for testing purposes.

temp test 6

I'm a bit confused. The code that you have posted in the OP appears to have generated this:
image
There is no specific label for A7 in that code.

EDIT
This looks like an open circuit where the sensor should be so the resistance is calculated to be as near infinity as the calculation allows:

image

Put in a pot wired 3v3/wiper to AI/gnd and use that as tester. no pullups or downs. just verify basic 0-4095 input

Also I don't like your math. I think you might be having an unplanned INT conversion happening in the middle of your computation.

Precompute the scale and multiply instead of dividing in the computation.

const float voltsPerBit = 3.3 / 4096.0;

then your math becomes:

Serial.print(analogRead(A7) * voltsPerBit);

Sorry, those readings were from two different boards exhibiting different behavior with identical setups. I should have made that more clear.

I don't have a pot to use like that on hand, but i am able to utilize the voltage divider circuit as designed with various R2 values and measure the behavior both on the MCU reading and with a DMM. So updated the code per your suggestions. and took 3 measurements, Open circuit, R2 value of 4.7k, and short to gnd / R2 value of 0.

Open circuit the DMM measurement is 3.311V at pin PA2. The MCU reads the following:
temp test open circuit

With a 4.7k R2 resistor, the DMM measures 1.609V at pin PA2. The MCU measures the following:
temp test 4.7k R2

With a short to gnd, or 0ohm R2, the DMM measures 0.000V at pin PA2 with continuity to ground. The MCU measures the following:
temp test Short to Gnd

Updated Code:

#include <Arduino.h>
#include "config.h"

int Vo;
float R1 = 10000;
float logR2, R2, T;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
const float voltsPerBit = 3.3 / 4096.0;
uint32_t timer;
int reading;
float voltage, resistance;


void setup() 
{
    delay(3000); 
    SERIALCONSOLE.begin(115200);
    SERIALCONSOLE.println("Starting up!");
    
    timer = millis();
    pinMode(A7, INPUT);
    analogReadResolution(12);
}

//void checkCoolantTemp() {
//  int coolantTemp;
//  Vo = analogRead(A7);
//  R2 = R1 * (1023.0 / (float)Vo - 1.0);
//  logR2 = log(R2);
//  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2*logR2*logR2));
//  T = T - 273.15;
//  coolantTemp = (int)T + 40;
//  SERIALCONSOLE.print("Algorithm Measurement: ");
//  SERIALCONSOLE.println(coolantTemp);
//  SERIALCONSOLE.println("");
//}

void loop() 
{
  if(millis() - timer >1000){
      reading = analogRead(A7);
      voltage = reading * voltsPerBit;
      resistance = (voltage*4999)/(3.3-voltage);
      SERIALCONSOLE.print("Raw Sensor Reading A7: ");
      SERIALCONSOLE.println(reading);

      SERIALCONSOLE.print("Voltage Reading: ");
      SERIALCONSOLE.println(voltage);

      SERIALCONSOLE.print("Calculated Resistance: ");
      SERIALCONSOLE.println(resistance);
      SERIALCONSOLE.println("");

      timer = millis();
      
    }
}

I was able to find a potentiometer to test with. I left the voltage divider R1 in place because its going to be difficult to remove and replace with the hot air station i currently have.

Sweeping the pot from 80kohm which is its max value down to zero resulted in a voltage reading of 3.3V at all times until the resistance dropped below 40hm in which case the MCU returned a value of 1.85V from 4 ohm to 0ohm.

Measuring the voltage at PA2 with the DMM i see a nice clean sweep from 3.3V to 0V.

I'm not sure what would cause the MCU to only return 2 values regardless of the voltage input.

VDDANA (pin 73)
Powers the ADC and DAC cells; voltage ranges from 2.0V to 3.6V.

I'd begin to suspect a grounding problem. The ADC has its own ground pin GNDANA (pin74) and maybe the soldering is not good. But also Check VDDANA (pin 73)

image

Because it thinks its a DI. what happens if you comment out the PINMODE(A7, INPUT) statement?

No change if I comment out that line.

3.3V on VDDANA

Good Ground on GNDANA (0.0ohm )

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.