Touchscreen library with different ADC resolutions

Hi,
i was posting a message into the adafruit forum https://forums.adafruit.com/viewtopic.php?f=47&t=109704 about using one of their touchscreens (3.5" TFT with ILI9341) with a Teensy 3.2 with 16bit instead of the standard 10bit ADC resolution. And i think it is usefull to link that here too...
The problem is that the adafruit touchscreen library works with the ADC and "thinks" that the resolution is always 10bit. So their data types and even used constants are optimized for 10bit too. But i am using 16bit ADC resolution in a critical timer-task and need to use the touchscreen at the same time. But the touchscreen functions return wrong values (negative values and 16bit-integer overflows (-32K<->32K) in the middle of the display). So i decided to change the touchscreen library so i can use it optimized for a special resolution or generally with 16bit ADC resolution as in the code below:

(If you want to use another resolution you only have to change _DATATYPE, _DATATYPE_MAX and _MAXDIFFERENCE as you need.)


touchscreen.h
Code:
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// (c) ladyada / adafruit
// Code under MIT License

#ifndef _ADAFRUIT_TOUCHSCREEN_H_
#define _ADAFRUIT_TOUCHSCREEN_H_
#include <stdint.h>

#define _DATATYPE uint16_t
#define _DATATYPE_MAX 65535 //1023 @ 10bit, 4095 @ 12bit, 65535 @ 16bit 
#define _MAXDIFFERENCE 256  //4 @ 1024(10bit), 16 @ 4096(12bit), 256 @ 65535(16bit)

class TSPoint {
 public:
  TSPoint(void);
  TSPoint(_DATATYPE x, _DATATYPE y, _DATATYPE z);
  
  bool operator==(TSPoint);
  bool operator!=(TSPoint);

  _DATATYPE x, y, z;
};

class TouchScreen {
 public:
  TouchScreen(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym);
  TouchScreen(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym, uint16_t rx);

  bool isTouching(void);
  _DATATYPE pressure(void);
  _DATATYPE readTouchY();
  _DATATYPE readTouchX();
  TSPoint getPoint();
  _DATATYPE pressureThreshhold;

private:
  uint8_t _yp, _ym, _xm, _xp;
  _DATATYPE _rxplate;
};

#endif

touchscreen.cpp
Code:
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// (c) ladyada / adafruit
// Code under MIT License

#include "Arduino.h"
#include "pins_arduino.h"

#ifdef __AVR
  #include <avr/pgmspace.h>
#elif defined(ESP8266)
  #include <pgmspace.h>
#endif
#include "TouchScreen_multiADC.h"

// increase or decrease the touchscreen oversampling. This is a little different than you make think:
// 1 is no oversampling, whatever data we get is immediately returned
// 2 is double-sampling and we only return valid data if both points are the same
// 3+ uses insert sort to get the median value.
// We found 2 is precise yet not too slow so we suggest sticking with it!

#define NUMSAMPLES 2

TSPoint::TSPoint(void) {
  x = y = 0;
}

TSPoint::TSPoint(_DATATYPE x0, _DATATYPE y0, _DATATYPE z0) {
  x = x0;
  y = y0;
  z = z0;
}

bool TSPoint::operator==(TSPoint p1) {
  return  ((p1.x == x) && (p1.y == y) && (p1.z == z));
}

bool TSPoint::operator!=(TSPoint p1) {
  return  ((p1.x != x) || (p1.y != y) || (p1.z != z));
}

#if (NUMSAMPLES > 2)
static void insert_sort(_DATATYPE array[], uint8_t size) {
  uint8_t j;
  _DATATYPE save;
  
  for (int i = 1; i < size; i++) {
    save = array[i];
    for (j = i; j >= 1 && save < array[j - 1]; j--)
      array[j] = array[j - 1];
    array[j] = save; 
  }
}
#endif

TSPoint TouchScreen::getPoint(void) {
  _DATATYPE x, y, z;
  _DATATYPE samples[NUMSAMPLES];
  uint8_t i, valid;
  
#if defined(ARDUINO_ARCH_SAM)
    Pio* xp_port = digitalPinToPort(_xp);
    Pio* yp_port = digitalPinToPort(_yp);
    Pio* xm_port = digitalPinToPort(_xm);
    Pio* ym_port = digitalPinToPort(_ym);
    
    uint32_t xp_pin = digitalPinToBitMask(_xp);
    uint32_t yp_pin = digitalPinToBitMask(_yp);
    uint32_t xm_pin = digitalPinToBitMask(_xm);
    uint32_t ym_pin = digitalPinToBitMask(_ym);
#elif defined(ARDUINO_ARCH_SAMD)
    PortGroup* xp_port = digitalPinToPort(_xp);
    PortGroup* yp_port = digitalPinToPort(_yp);
    PortGroup* xm_port = digitalPinToPort(_xm);
    PortGroup* ym_port = digitalPinToPort(_ym);
    
    uint32_t xp_pin = digitalPinToBitMask(_xp);
    uint32_t yp_pin = digitalPinToBitMask(_yp);
    uint32_t xm_pin = digitalPinToBitMask(_xm);
    uint32_t ym_pin = digitalPinToBitMask(_ym);
#else
    uint8_t xp_port = digitalPinToPort(_xp);
    uint8_t yp_port = digitalPinToPort(_yp);
    uint8_t xm_port = digitalPinToPort(_xm);
    uint8_t ym_port = digitalPinToPort(_ym);

    uint8_t xp_pin = digitalPinToBitMask(_xp);
    uint8_t yp_pin = digitalPinToBitMask(_yp);
    uint8_t xm_pin = digitalPinToBitMask(_xm);
    uint8_t ym_pin = digitalPinToBitMask(_ym);
#endif


  valid = 1;

  pinMode(_yp, INPUT);
  pinMode(_ym, INPUT);
  
  *portOutputRegister(yp_port) &= ~yp_pin;
  *portOutputRegister(ym_port) &= ~ym_pin;
  //digitalWrite(_yp, LOW);
  //digitalWrite(_ym, LOW);
   
  pinMode(_xp, OUTPUT);
  pinMode(_xm, OUTPUT);
  //digitalWrite(_xp, HIGH);
  //digitalWrite(_xm, LOW);
  *portOutputRegister(xp_port) |= xp_pin;
  *portOutputRegister(xm_port) &= ~xm_pin;
   
#ifdef __arm__
  delayMicroseconds(20); // Fast ARM chips need to allow voltages to settle
#endif
   for (i=0; i<NUMSAMPLES; i++) {
     samples[i] = analogRead(_yp);
   }
#if NUMSAMPLES > 2
   insert_sort(samples, NUMSAMPLES);
#endif
#if NUMSAMPLES == 2
   // Allow small amount of measurement noise, because capacitive
   // coupling to a TFT display's signals can induce some noise.
   if (samples[0] - samples[1] < -_MAXDIFFERENCE || samples[0] - samples[1] > _MAXDIFFERENCE) {
     valid = 0;
   } else {
     samples[1] = (samples[0] + samples[1]) >> 1; // average 2 samples
   }
#endif
   x = (_DATATYPE_MAX-samples[NUMSAMPLES/2]);

   pinMode(_xp, INPUT);
   pinMode(_xm, INPUT);
   *portOutputRegister(xp_port) &= ~xp_pin;
   //digitalWrite(_xp, LOW);
   
   pinMode(_yp, OUTPUT);
   *portOutputRegister(yp_port) |= yp_pin;
   //digitalWrite(_yp, HIGH);
   pinMode(_ym, OUTPUT);
  
#ifdef __arm__
   delayMicroseconds(20); // Fast ARM chips need to allow voltages to settle
#endif
   for (i=0; i<NUMSAMPLES; i++) {
     samples[i] = analogRead(_xm);
   }

#if NUMSAMPLES > 2
   insert_sort(samples, NUMSAMPLES);
#endif
#if NUMSAMPLES == 2
   // Allow small amount of measurement noise, because capacitive
   // coupling to a TFT display's signals can induce some noise.
   if (samples[0] - samples[1] < -_MAXDIFFERENCE || samples[0] - samples[1] > _MAXDIFFERENCE) {
     valid = 0;
   } else {
     samples[1] = (samples[0] + samples[1]) >> 1; // average 2 samples
   }
#endif

   y = (_DATATYPE_MAX-samples[NUMSAMPLES/2]);

   // Set X+ to ground
   pinMode(_xp, OUTPUT);
   *portOutputRegister(xp_port) &= ~xp_pin;
   //digitalWrite(_xp, LOW);
  
   // Set Y- to VCC
   *portOutputRegister(ym_port) |= ym_pin;
   //digitalWrite(_ym, HIGH); 
  
   // Hi-Z X- and Y+
   *portOutputRegister(yp_port) &= ~yp_pin;
   //digitalWrite(_yp, LOW);
   pinMode(_yp, INPUT);
  
   int z1 = analogRead(_xm); 
   int z2 = analogRead(_yp);

   if (_rxplate != 0) {
     // now read the x 
     float rtouch;
     rtouch = z2;
     rtouch /= z1;
     rtouch -= 1;
     rtouch *= x;
     rtouch *= _rxplate;
     rtouch /= (_DATATYPE_MAX+1);
     
     z = rtouch;
   } else {
     z = (_DATATYPE_MAX-(z2-z1));
   }

   if (! valid) {
     z = 0;
   }

   return TSPoint(x, y, z);
}

TouchScreen::TouchScreen(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym) {
  _yp = yp;
  _xm = xm;
  _ym = ym;
  _xp = xp;
  _rxplate = 0;
  pressureThreshhold = 10;
}


TouchScreen::TouchScreen(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym,
			 uint16_t rxplate) {
  _yp = yp;
  _xm = xm;
  _ym = ym;
  _xp = xp;
  _rxplate = rxplate;

  pressureThreshhold = 10;
}

_DATATYPE TouchScreen::readTouchX(void) {
   pinMode(_yp, INPUT);
   pinMode(_ym, INPUT);
   digitalWrite(_yp, LOW);
   digitalWrite(_ym, LOW);
   
   pinMode(_xp, OUTPUT);
   digitalWrite(_xp, HIGH);
   pinMode(_xm, OUTPUT);
   digitalWrite(_xm, LOW);
   
   return (_DATATYPE_MAX-analogRead(_yp));
}


_DATATYPE TouchScreen::readTouchY(void) {
   pinMode(_xp, INPUT);
   pinMode(_xm, INPUT);
   digitalWrite(_xp, LOW);
   digitalWrite(_xm, LOW);
   
   pinMode(_yp, OUTPUT);
   digitalWrite(_yp, HIGH);
   pinMode(_ym, OUTPUT);
   digitalWrite(_ym, LOW);
   
   return (_DATATYPE_MAX-analogRead(_xm));
}


_DATATYPE TouchScreen::pressure(void) {
  // Set X+ to ground
  pinMode(_xp, OUTPUT);
  digitalWrite(_xp, LOW);
  
  // Set Y- to VCC
  pinMode(_ym, OUTPUT);
  digitalWrite(_ym, HIGH); 
  
  // Hi-Z X- and Y+
  digitalWrite(_xm, LOW);
  pinMode(_xm, INPUT);
  digitalWrite(_yp, LOW);
  pinMode(_yp, INPUT);
  
  _DATATYPE z1 = analogRead(_xm); 
  _DATATYPE z2 = analogRead(_yp);

  if (_rxplate != 0) {
    // now read the x 
    float rtouch;
    rtouch = z2;
    rtouch /= z1;
    rtouch -= 1;
    rtouch *= readTouchX();
    rtouch *= _rxplate;
    rtouch /= (_DATATYPE_MAX+1);
    
    return rtouch;
  } else {
    return (_DATATYPE_MAX-(z2-z1));
  }
}

If you find it helpfull please test it with different displays and ADC resolutions or please post optimizations.
Thanks.
 
Interesting. I thought 16 bit mode was only really usable in differential mode. The touch library I've beeb using with the PJRC QVGAtouch has raw position values up to 3800 or so so it must use 12 bit mode.
 
Since i measure two lines against the same ground it is something like a differential measurement...
I want to measrue the resistance of a cryo-temperature-diode. It is connected with only two wires (standard way would be 2 wires for supply current and 2 for voltage measurement). So i have to measure the current through a 100.3kOhm resistor in series with the diode (gives ~15µA) and the supply voltage for the series. Then i can calculate the resistance of the Diode and then the Temperature of the diode. Only problem is that i always get nearly twice the resistance of the diode - don't know why...

Here are my calibration values:
#define TS_MINX 8500
#define TS_MINY 5200
#define TS_MAXX 59500
#define TS_MAXY 60300

With 10bit ADC i get negative values and the touchscreen GetPoint-function thinks that it is unvalid and return z-value of 0. So i did not have any indicator for touching...
 
I found my error there is a 16 bit single ended mode but they only guarantee the accuracy listed in the charts in differential mode. Single ended effective number of bits is at best about 13 bits using 16 bit single ended mode. For what I'm doing on a 2.x" screen 12 bit is far more resolution than what I need considering the display under it is only 320 pixels wide. That's over 10 counts per pixel. Good luck, sorry I couldn't help any. A thought I have and don't know the answer is it possible to just change back and forth from 16 bit to 12 bit resolution as needed?
 
Last edited:
I checked the ADC specs for the T3.2 in the datasheet and it states the input resistance of the ADC is typically 2K and max of 5K. With this very low resistance for the ADC load, I don't think you can accurately measure the voltage across the diode given the 103k series resistor. You didn't mention using the T3.2s ADC PGA and differential mode so I assume you weren't. But if you were, that increases the input impedance to between 32K and 128k, depending upon the PGA Gain setting. This is much better, but still not good enough for accurate readings. You need a high impedance, unity gain op amp circuit between the diode and the ADC.
 
At low temperatures the diode has about 100kOhm too so this voltage divider is round about symmetrical and should be easy to measure even if some current sinks to the ADC. Moreover i measured the voltages with a multimeter and they seem to be ok. That unfortunately does not explain a measured resitance of ~200kOhm instead of ~100kOhm... Maybe i completely think wrong but this is such a simple thing...
The next problem is that i did not expected such problems (as always ;) ) and the PCB is nearly finished... So i maybe could change a resistor or capacitor value or add one or two little components but not a op amp (or a voltage-to-frequency-converter?) with half a dozen components around ....
I think i have to rebuild a simple version of that all and check if i am thinking wrong...
 
Last edited:
The 100K resistance of the cryodiode nicely matches the 103K series resistor- that part is all fine. But when the ADC is connected across the diode, its 2-5K input resistance is in parallel with the diode, so that will have a big effect on your reading accuracy.
When you take a reading with a multimeter, I am assuming you are referring to a digital multimeter, and those generally have an input resistance of 10 megohms (10^7 ohms). The multimeter will therefore not affect the accuracy of the reading.
If you are switching the ADC between different channels, then the ADC might only be connected across the diode for a short percentage of the time- in which case, if you put a good quality, low leakage capacitor across the diode, then the ADC should be able to read more accurately, as the capacitor will be able to drive the low impedance ADC for the short time that the ADC is actually switched onto the pin connected to the diode. I suspect a 0.1 uf capacitor, or at most a 1 uf capacitor should work OK.
FYI- I didn't look closely at your code- maybe an error there. I just focused on the fact that the low resistance of the ADC is bound to affect the measurement of a high resistance source like your cryodiode.
 
I'm using a 100k 100k resistor divider to measure some batteries and a .1 uf cap changed the read voltage to something much closer to reality. Even with analogReadAveraging(32) the best I could get was about 10 effective number of bits even with the cap. I am not sure you will get what you need from the built in ADC in 16 bit mode.
 
Last edited:
@ DaQue I've only used differential mode with PGA and measuring a low impedance source. With this I only got about 12 ENOBs and I was averaging between 8 and 32 samples, like you, as I recall. The datasheet only claims 12-14 bits in similar conditions, so it makes sense
. But the datasheet clearly says that ADC input resistance is only 5k in single ended mode. So I can't see how one could get readings of any accuracy with 100k /100k divider except that the cap would act as a reservoir since the ADC is only sampling for a tiny fraction of the time. Apart from the 10 bits resolution, when you tried your measurement without the addition of the cap, were you getting a reading anywhere near correct? I would think it would be way off.
 
I was reading a 4v battery about 0.4 volts low without the cap. There was so much noise it was hard to guess closer than the that average was about 10% low, it could have been more. The min/max was all over the place. The ADC reading using 2*( adc/1023*3.3) was very close to the reading on my Fluke DVM with the 0.1 if cap installed and varied only a couple counts at most. I fully agree you need a good size cap and a op amp buffer would be even better. I think I read somewhere that the impedance of the voltage source your reading should be under 10k. Do you think he will be able to get the ENOB he evidently needs without averaging hundreds of readings?

Edit:
I had everything right at hand so I just ran a simple sketch to get some real numbers with and without the cap.

Average of 1000 readings without cap 566 with cap 650
With cap min and max readings 650.
Without cap min 550 max 582.
 
Last edited:
@daQue: Thanks for performing the tests. The wide variations in min/max without the cap are what I would expect. The fact that the values drop when the cap is not there is also expected. However, I was surprised it didn't drop by much more. In theory, that 5K ADC input resistance is in parallel with the lower 100K resistor- during the conversion time. So, I expected the readings to be much lower than you got (without cap). But, I didn't consider that there is a small amount of internal capacitance within the ADC circuit itself. This must be enough to store the charge long enough to supply the 5K resistance of the ADC for the conversion time. Of course, with such a small reservoir, the accuracy would be poor, like you saw. I would guess that if you ramped up the conversion rste to a high value, or used continuous conversion,that the ADC reading would go even lower than you got.
I don't remember seeing how many ENOBs the original poster wanted, but I agree with you that he might not get it even if he took a large number of readings and averaged it. But, adding a good quality 0.1 to 1 uf cap should help a lot, given that he can't/ won't change the PCB to accommodate an op amp buffer.
 
Thanks for the tip with the 0.1µF capacitor - i will check this out...

Meanwhile i checked the datasheet and as you wrote the chip has 2K-5KOhm input RESISTANCE (i was hoping they mean impedance...). I am not sure why they do so, because they even use a SAR ADC with sample and hold input - so why they need such a low resistance??? They mentioned that they were using an 8 Ohm!!! supply for their ADC measurements - who has this low output resistance??? - so it seems the whole ADC is not usable for simple solder-a-pin-and-go measurements - but:
I indeed used a digital multimeter and i hope it is measuring correct. And when the DMM measure the same values that the ADC produces everything should be fine - whatever they do internally on the chip?.?. Or am i thinking wrong?
Next: the touchscreen is working fine and precise too in 16bit mode (maybe due to the pins A1..A4 that i use for???) and they only accumulate two measurements in single ended mode with a x-side-by-side resistance of ~240Ohm. I think it would be not that precise when the ADC returns totally wrong values?.?.
Moreover i tried the 10bit mode and the result was nearly the same as in 16bit mode so i could use that mode too.
But all that brings me to the opinion that something is wrong with my hardware... I will check this next...


BTW the code above was only for a replacement for the adafruit touchscreen library as they only support 10bit ADCs.
So here is my code for the measurement:
Code:
#define cryo_analog_pin A10
#define cryo_digital_pin 7
#define cryo_5V_pin A12

void setup()
{
analogReference(EXTERNAL);
analogReadRes(16);
....
}

...
measure(cryo_digital_pin,cryo_analog_pin,cryo_5V_pin,1000);
...


double measure(int input_digital_pin, int input_analog_pin, int input_5V_pin, int input_num_accus)
{
double mean_diode;
double mean_voltage;
double diode_current = 0.0;
double diode_resistance = 0.0;

digitalWrite(input_digital_pin,HIGH);   //5V on
for (int i=0;i<input_num_accus;i++)
    {
    mean_diode   += 1.0*analogRead(input_analog_pin);   //accumulate and convert from uint16_t to double
    mean_voltage += 1.0*analogRead(input_5V_pin);
    }
digitalWrite(input_digital_pin,LOW);  //5V off

diode_current    =  (((mean_diode   / input_num_accus) / 65535.0) * 3.300) / 100300.0;  //I=U/R ; max(16bit)=3.3V=65535 ; 100300kOhm series resistance
diode_resistance = ((((mean_voltage / input_num_accus) / 40000.0) * 4.000) / diode_current) - 100300.0;  //4.0V = 40000

return diode_resistance;
}
 
I tried the tip with the capacitor: i added a 1µF and even a 100µF in parallel with the resistor i want to measure the voltage over. It increases the voltage a bit but not much (should be ~2.2V but increases from 0.25V to 0.45V). I tried out to sample only once, use 12bit ADC mode, have 1s setteling time between the two channels and measure only every 10s... Its terrible... a 100kOhm voltage divider seems not to be measureable a simple way...
Last hope is to find a configuration for a differential measurement...

Does anybody know why the µC has such a low input resistance (the ADC itselfs should have several MOhm)???
 
If you use the differential mode/PGA ,the input resistance goes up to around 128K (at a PGA gain of 1). This is much higher and may work for you. But, if I recall correctly, only A9,10,11,12 are hooked to the PGAs, and these are (mostly) not on the T3.2s 28 pin footprint, but on the inner bottom pins.
SAR ADCs themselves are usually low input resistance (impedance), so this isn't unusual. If they are higher, then there could be an internal buffer providing this higher impedance. The dual slope integrator ADC in your digital meter is different- it does have a very high input resistance by design.
 
Thanks for the tip!
Now i use the differential mode (pins 12,13 on ADC1) with PGA=1. That brings up the voltage to ~1.1V@100kOhm. It should be ~2.1V... And as i tested the setup with an Arduino Mega 2560 everything works fine... So i could use an Arduino for measuring and transfer the data via SPI...
However. With that larger voltage i decided to determine a correction function for my Teensy-ADC. I took a 100kOhm potentiometer with ~30kOhm fix resistor in series and measured the voltages while changing the resistance from 30k..130k. Then i was creating a simple 100k/100k voltage divider on http://www.falstad.com/circuit/circuitjs.html and wrote down the voltages as they should be for the same resistances. Next i was plotting Vshouldbe vs. Vmeasured and did a exponential fit on the plot so i have a mathematical expression for that function. (you simply could do a linear interpolation with the data too). And with this expression i can correct the values i measure...

Here is the code for the initialisation of the ADC1:
Code:
void init_measurement(uint16_t input_NumDataPoints)
{
Serial.print("Initialising Measurement...");
pinMode(cryo_digital_pin,OUTPUT);    //pin 7
digitalWrite(cryo_digital_pin, LOW);
pinMode(cryo_analog_p_pin,INPUT);  //A12
pinMode(cryo_analog_n_pin,INPUT);  //A13
pinMode(cryo_5V_pin,INPUT);          //A10

adc->setReference(ADC_REF_3V3, ADC_1);    //i have a 3.30V external reference ic on the board
adc->setAveraging(1, ADC_1); 
adc->setResolution(13, ADC_1); 
adc->setConversionSpeed(ADC_HIGH_SPEED, ADC_1); 
adc->setSamplingSpeed(ADC_HIGH_SPEED, ADC_1);
adc->enablePGA(1, ADC_1);              //for having more input resistance into the ADC, else it would be 2kOhm only!!!!!!!!!!!!!!!!!!!!!!!!

NumDataPoints = input_NumDataPoints;
Data = (double*)malloc( NumDataPoints * sizeof(double) );
for (int i=0;i<NumDataPoints;i++) { Data[i] = 0; }
Serial.println("Init measurement done.");
}

...and this is the code for measuring:
Code:
double measure_temperature(int input_num_accus)
{
double Vdiode = 0.0;
double Vres = 0.0;
double Vcc = 0.0;
double Ires = 0.0;
double Rres = 100100.0;   //fixed resistor in series with the temperature-measurement-diode
double Rdiode = 0.0;
float diode_temperature = 0.0;
int i;

digitalWrite(cryo_digital_pin,HIGH);
delay(10);                //current/voltage settling time
noInterrupts();
for (i=0;i<input_num_accus;i++)
    {
    Vcc  += 1.0 * adc->analogRead(cryo_5V_pin, ADC_1);
    Vres += 1.0 * adc->analogReadDifferential(cryo_analog_p_pin, cryo_analog_n_pin, ADC_1);
    }
interrupts();
digitalWrite(cryo_digital_pin,LOW);

Vres = (1.0 * (Vres / input_num_accus)*3.3/adc->getPGA(ADC_1)/adc->getMaxValue(ADC_1)) ;  
Vcc  = (Vcc  / input_num_accus)*4.0/adc->getPGA(ADC_1)/2500;    //4:2500 because i have a potentiometer in front of the ADC for being able to put in higher voltages than 3.3V - in this case 5V driving voltage for the diode/100100k-resistor voltage divider

Vres = 4.213 - (4.802 * exp(-0.723*Vres) ); //corr. function measured with potentiometer and calculated with http://www.falstad.com/circuit/circuitjs.html

Vdiode = Vcc - Vres;

Ires   = Vres   / Rres;   //I=U/R
Rdiode = Vdiode / Ires;   //Ires=Idiode=Icc

for (i=0;i<array_size;i++) { if (diode_resistances[i] <= Rdiode) {break;} }
if ((i>0)&&(i<array_size))   //resistances and temperatures in arrays , from diode datasheet
    {
    //linear interpolation
    diode_temperature = diode_temperatures[i-1] 
        + ( (diode_temperatures[i]-diode_temperatures[i-1]) / (diode_resistances[i]-diode_resistances[i-1]) * (Rdiode - diode_resistances[i-1]) );
    }
else {diode_temperature = 0.0;}

if (Serial)
    {
    char text[100];
    sprintf(text,"Vr=%fV\tVd=%fV\tVcc=%fV\tIres=%fA\tRd=%fOhm\t%fK\n",Vres,Vdiode,Vcc,Ires,Rdiode,diode_temperature);
    Serial.print(text);
    }

return (diode_temperature);
}

For me that works but for the next time i know this nasty "feature" of the teensy ADC and will include a voltage follower in front of the ADC lines in the circuit.
Thanks for the help!
 
Back
Top