LTC2440 A/D mysteeri

No niin!

Miksiköhän LTC2440 antaa mielestäni hiukka ihmeellisiä
lukemia? Tulopuolella jännite on noin 8000 uV, ja LTC
näyttää lukemia noin 120000-130000 uV. Tulopuolella on
PT100 + 3x100R sillassa. Neljällä 100R kiinteällä vastuksella
LTC:n antama lukema on hyvin lähellä nollaa, joten itse
laitteisto tuntuisi toimivan. Mikäköhän tässä mättää?
Referenssijännite on 5V, sama vastussillalle sekä Ref+.

Käytän seuraavaa John Bealen koodia (hän ei myöntänyt
itse koodissa olevan vikaa, kun asiasta kysyin). Tosin John
käyttää alustana 328:a, mulla on tässä Mega 2560.

/*
  Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC
  Oct. 24 2012 John Beale

   LTC2440  <---------->  Arduino
   10: /EXT : ground (use external serial clock)
   11: /CS <- to digital pin 10  (SS pin)
   12: MISO -> to digital pin 12 (MISO pin)
   13: SCLK <- to digital pin 13 (SCK pin)
   15: BUSY -> to digital pin 9 (low when result ready)

   1,8,9,16: GND :  all grounds must be connected
   2: Vcc :   +5V supply
   3: REF+ :  +5V reference
   4: REF- :  GND
   5: IN+  :  Input+
   6: IN-  :  Input-
   7: SDI  : +5V  (select 6.9 Hz output rate, or GND for 880 Hz rate)
   14: Fo : GND  (select internal 9 MHz oscillator)

*/

#include <SPI.h>  // include the SPI library
#include <digitalWriteFast.h> // from http://code.google.com/p/digitalwritefast/downloads/list
// I had to update the WriteFast library for Arduino 1.0.1: replace "#include wiring.h" and "#include WProgram.h"
//   with "#include <Arduino.h>"  in libraries/digitalwritefast/digitalWriteFast.h

#define VREF (5.0)    // ADC voltage reference
#define PWAIT (198)   // milliseconds delay between readings
#define SLAVESELECT 10  // digital pin 10 for CS/
#define BUSYPIN 9     // digital pin 9 for BUSY or READY/


const int nsamples = 50;  // how many ADC readings to average together

// SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

void setup() {
 
Serial.begin(115200);  // set up serial comm to PC at this baud rate
   
 pinMode (SLAVESELECT, OUTPUT);
 pinMode (BUSYPIN, INPUT);
 digitalWriteFast(SLAVESELECT,LOW);   // take the SS pin low to select the chip
 delayMicroseconds(1);
 digitalWriteFast(SLAVESELECT,HIGH);   // take the SS pin high to start new ADC conversion

 SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals
 SPI.setBitOrder(MSBFIRST);  // data is clocked in MSB first
 SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
 SPI.setClockDivider(SPI_CLOCK_DIV16);  // set SPI clock at 1 MHz. Arduino xtal = 16 MHz, LTC2440 max = 20 MHz
 Serial.println("# LTC2440 v1.1 Oct.25 2012  jpb");  
Serial.println("min,uVolts,pkpk,stdev");
 for (int i=0;i<2;i++) {  // throw away the first few readings, which seem to be way off
  SpiRead();
 }
} // end setup()

// =============================================================================
// Main Loop:
// acquire 'nsamples' readings, convert to units of volts, and send out on serial port

void loop() {

int i;
long secs;
float mins;
long in; // incoming serial 32-bit word 
float uVolts;  // average reading in microvolts

float datSum;  // accumulated sum of input values
float sMax;
float sMin;
long n;            // count of how many readings so far
float x,mean,delta,sumsq,m2,variance,stdev,pp;  // to calculate standard deviation   

  sMax = -VREF;  // set max to minimum possible reading
  sMin = VREF;   // set min to max possible reading
  sumsq = 0; // initialize running squared sum of differences
  n = 0;     // have not made any ADC readings yet
  datSum = 0;  // accumulated sum of readings starts at zero
  mean = 0; // start off with running mean at zero
  m2 = 0;
  
  for (i=0; i<nsamples; i++) {
    x = SpiRead();
    datSum += x;
    if (x > sMax) sMax = x;
    if (x < sMin) sMin = x;
                      // from http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
    n++;
    delta = x - mean;
    mean += delta/n;
    m2 += (delta * (x - mean));

  } // end for (i..)

  variance = m2/(n-1);  // (n-1):Sample Variance  (n): Population Variance
  stdev = 1E6*sqrt(variance);  // Calculate standard deviation in microvolts
  pp = 1E6 * (sMax - sMin);   // peak-to-peak difference of readings, in uV
  
  uVolts = datSum * (1E6) / n;

mins = (float) millis() / 60000;   // elapsed time in minutes
Serial.print(mins,3); 
Serial.print(", ");
Serial.print(uVolts,3);
Serial.print(", ");
Serial.print(pp,3);
Serial.print(", ");
Serial.print(stdev,3);
Serial.println();

} // end main loop


// =================================================================
// SpiRead() -- read 4 bytes from LTC2440 chip via SPI, return Volts
// =================================================================

float SpiRead(void) {

  long result = 0;
  byte sig = 0;    // sign bit
  byte b;
  float v;
  
  while (digitalReadFast(BUSYPIN)==HIGH) {}  // wait until ADC result is ready
  
  digitalWriteFast(SLAVESELECT,LOW);   // take the SS pin low to select the chip
  delayMicroseconds(1);  // probably not needed, only need 25 nsec delay
 
  b = SPI.transfer(0xff);   // B3
  if ((b & 0x20) ==0) sig=1;  // is input negative ?
  b &=0x1f;    // discard bits 25..31
  result = b;
  result <<= 8;  
  b = SPI.transfer(0xff);   // B2
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B1
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B0
  result |= b;
   
  digitalWriteFast(SLAVESELECT,HIGH);   // take the SS pin high to bring MISO to hi-Z and start new conversion
  
  if (sig) result |= 0xf0000000;    // if input is negative, insert sign bit (0xf0.. or 0xe0... ?)        
  v = result;
  v = v / 16.0;                             // scale result down , last 4 bits are "sub-LSBs"
  v = v * VREF / (2 * 16777216); // +Vfullscale = +Vref/2, max scale (2^24 = 16777216)
  return(v);  
}

En ehdi nyt koodia katsoa, mutta kokeile mitata useita eri jännitteitä, jotta tiedät mitä ohjelma tekee. 5 V referenssillä tuo mittaa ±2,5V. Kokeile mitata oikosulkua ja vaikkapa 1,5V patteria molemmin päin. Jos nuo saat oikein, koodi toimii luultavasti OK. Onko tuo 8000 uV eli 8 mV yleismittarilla saatu vai mistä tiedät sen oikeaksi? Millainen on keskihajonta oikosulussa, tuota 8000 uV mitatessa ja patteria mitatessa?

Tuon lukeminen on varsin helppoa. Itse tein oman koodin alusta saakka. Ehkä sinunkin kannattaa, jotta tiedät varmasti mitä koodi tekee.

Morjens,

Haista kuule jmaja vittu. Tai ehkä vain haaveilet siitä.

Ei ihme. että tällä foorumilla on hiukka hiljaista, kun
tuollaiset kusipäät antavat hienoja “neuvojaan”. Testaa
sinä oma ADHD-muuntimesi työntämällä verkkopiuha
hanuriisi ja käännä nappulaa. Jos sattuu, niin koodi on
todennäköisesti oikein.

Ja itse asiaan.

LTC2440 ottaa max. 300mV jännite-eron inputtina hajoamatta.

Ensin ajo Wheatsonen sillalla, kiinteät 100R vastukset
0,1% toleranssilla. Viimeinen luku on keskihajonta uV.
Ei huonoja lukuja, eli aika stabiili on minusta.

# LTC2440 v1.1 Oct.25 2012  jpb
min,uVolts,pkpk,stdev
0.124, 787.220, 32.857, 6.434
0.246, 788.430, 31.367, 6.573
0.367, 786.377, 35.129, 7.919
0.489, 783.233, 36.992, 8.021
0.610, 782.496, 32.596, 7.022
0.732, 785.352, 36.359, 8.532
0.853, 784.699, 28.275, 6.384
0.975, 785.255, 30.249, 7.294
1.097, 786.764, 32.037, 6.874
1.218, 786.582, 25.891, 6.285
1.340, 788.507, 31.628, 6.920
1.461, 790.259, 31.888, 7.248

Tässä seuraavassa yhtenä oksana A-luokan
PT100. Häiriöt ovat hieman isompia, mutta
siedettäviä. Huonelämpötila noin 21 astetta
ja sillan jännite noin 80mV. Referenssinä
LT2021-5 voltin versio. LTC:n lukemat kuitenkin
hieman ihmeellisiä.

Ai niin, jmaja, en kaipaa sinun opastustasi,
mutta asialliset kommentit tervetulleita.
Koodia olen tehnyt parikymmentä vuotta
työkseni, ja jos jostain löydän valmiin aihion,
niin käytän sitä enkä yritä keksiä pyörää uudestaan.

min,uVolts,pkpk,stdev
0.124, 129363.718, 77.829, 22.996
0.246, 129370.101, 128.791, 35.116
0.367, 129214.343, 124.350, 32.280
0.489, 129213.226, 62.287, 12.048
0.610, 129146.726, 133.514, 38.417
0.732, 129062.273, 50.515, 12.116
0.853, 129054.179, 61.169, 14.314

Datalehden mukaan LTC2440 mittaa -0.5 * Vref - +0.5 * Vref välisen jännitteen (absoluuttinen mini 0.3 alle GND ja maksimi 0.3 yli Vcc), kuten jmaja sanoi. Mielestäni hän antoi erittäin hyviä vihjeitä, jolla voidaan poissulkea mahdollinen ohjelmistovika. Vahvan ohjelmistotaustasi vuoksi voidaan näin olettaa, että vika on rautapuolella ja kun olet varmuuden välttämäkseksi kuitenkin varmistanut paristolla ja oikosululla, niin piirrä kytkentäsi ja laita vaikka johonkin kuvapalveluun. Tarkastellaan sitten lähemmin sitä.

Ps. Mielestäni olisit kyllä anteeksipyynnön velkaa jmaja:lle :slight_smile:

Myös minä olisin ensimmäisenä lähtenyt ohjelmistovirheestä. Se kun on, niin kuin ilmeisesti varsin hyvin tiedät, varsin helppo tehdä. Varsinkin kun koodi ei ole omaa. Toisen ohjelmointi- ja osaamistaustasta kun on varsin vaikea sanoa yhtään mitään. Itselläni kun ei ainakaan ole Ruuvipenkki.fi -foorumin käyttäjätunnuksia ja CV:itä yhdistettynä mihinkään päänsisäiseen rekisteriin.

+1

Mitäs jos lukisit datasheetin, opettelisit miten tuo toimii ja antaisit oikeat lähtötiedot sen sijaan, että haistattelet asiallisista neuvoista? Jos olet noin kauan ohjelmoinut, osaat varmasti hetkessä katsoa toimiiko käyttämäsi koodi oikein vai ei.

LTC2440 kestää inputtiin -0,3 V - VCC+0,3 V GND-pinniin nähden. Sillä voi siis aivan hienosti mitata 1,5 V patterin, kunhan se kelluu GND:hen nähden tai ei ainakaan ole - -navastaan kytketty +VCC tai + -navastaan GND. Ja olen tuon tehnyt juuri ko. piirillä lukuisia kertoja.

Nyt syötät 5 V 100 ohmin siltaan eli PT100:n läpi menee n. 25 mA eli 0,06 W. Tietysti se lämpeää siitä. Mittaamasi 129 mV vastaa n. 28 C lämpötilaa. Oletko siis mitannut yleismittarilla, että LTC+koodi mittaa väärin vai oletatko vain, että pitäisi olla 21 C, jolla ko. silta pitäisi olla 98 mV eikä 80 mV?

Kohinaa on 30-kertaisesta datasheetin typicaliin, joten aika kaukana optimaalista on kytkentäsi. Ei siitä kuitenkaan helposti tule mV-luokan virheitä.

Pyydän anteeksi jmaja.

Tämä alkaa vaan pikku hiljaa raskaasti v-tuttamaan itseäni!

Anteenksi myös muut hermostumiseni.

Silta antaa yleismittarilla noin 73 mV huoneenlämmössä.
Sitten kun pistää kaikki vastukset samaan arvoon (100R),
niin saan nolla mV ja LTC näyttää myös nollaa.

Raudassa siis tuskin on vikaa.

Mikä tämmöisen kuprun voi tehdä?

Ydinkoodi on alla:

[code] b = SPI.transfer(0xff); // B3
if ((b & 0x20) ==0) sig=1; // is input negative ?
b &=0x1f; // discard bits 25…31
result = b;
result <<= 8;
b = SPI.transfer(0xff); // B2
result |= b;
result = result<<8;
b = SPI.transfer(0xff); // B1
result |= b;
result = result<<8;
b = SPI.transfer(0xff); // B0
result |= b;

  digitalWriteFast(SLAVESELECT,HIGH);   // take the SS pin high to bring MISO to hi-Z and start new conversion
 
  if (sig) result |= 0xf0000000;    // if input is negative, insert sign bit (0xf0.. or 0xe0... ?)       
  v = result;
  v = v / 16.0;                             // scale result down , last 4 bits are "sub-LSBs"
  v = v * VREF / (2 * 16777216); // +Vfullscale = +Vref/2, max scale (2^24 = 16777216)
  return(v); [/code]

Varsin ärsyttävä ongelma. koodi näyttää melko simppeliltä joten sen ei pitäisi olla pielessä.

Tarkasta kytkennät. ADC saa varmasti sähköä, mitattava jännite tulee oikein ADC:lle kytkentä mikrokoiralle on kunnossa.

En tunne 2560 paremmin, mutta voiko kurjuus olla SPI palikassa? se konffaisi itsensä väärin tai jotain.

Toinen tapa lähestyä voisi olla jos saat mittaustuloksen, mV arvon ja tuosta käsin mitatusta arvosta laskisi käsin mitä pitäisi tulla. Silloin voisi vian syy näkyä. Tämän jälkeen vian korjaaminenkin voisi olla helpompaa.

Noita AD muuntimen arvoja kannattaa katsella varmaan heksana jos näkyisi jotain fiksua kaavaa miten ne menevät pieleen.

Jos olet varma, ettei raudassa kerran ole vikaa, niin silloinhan sen on oltava softassa. Suosittelisin tuota paristotestiä nyt ensimmäisenä…

Olethan tarkistanut, että referenssi on tosiaan 5 V? Varmista se yleismittarilla. Vaikka referenssillä ei sinänsä ole merkitystä ko. mittaustavassa, se vaikuttaa todelliseen jännitteeseen johon vertaat. Nythän kuormitat referenssiä melko suurella virralla (ainakin 50 mA) ja refenssit vaativat yleensä melko suuren dropoutin. Millä jännitteellä syötät referenssiä?

Jos et halua tai helposti pysty mittaamaan paristoa, oikosulje tuo PT100 johdolla (huomaa, että tällöin toinen vastus kuumenee 0,25 W teholla). Silloin pitäisi näyttää 2,5V riippumatta referenssistä. Sitten voit vaikka oikosulkea tuon PT100:n yleismittarin virtamittauksella eri skaaloilla (tai 1-1000 ohm vastuksilla PT100:n rinnalla), jolloin sinun pitäisi saada eri arvoja 2,5V -> 0 V. Vastaavasti tekemällä sama operaatio viereiselle vastukselle, saat -2,5 V -> 0 V, mutta et tietystikään tasan -2,5 V, koska PT100 ei ole tasan 100 ohm huoneenlämmössä.

Kokeile myös oikosulkea sillan mittauskohta eli ADC:n sisääntulo (ei GND:iin, ainoastaan toisiinsa). Tällöin ulostulon pitäisi olla 0 V vähintään muutaman uV:n tarkkuudella.

Vertasin nopeasti koodia omaani tuon ADC:n osalta. Hiukan eri tavalla tehty, mutta heti en ainakaan löytänyt mitään virhettä. Merkin käsittely oli selkeästi erilainen. Onko tuo koodi todettu toimivaksi juuri LTC2440:lla? Eri LTC24XX-mallien välillä on eroja, joista tulee helposti yhden bittipaikan ero eli 2X tai 0,5X tulos.

Koodissasi ihmetetty kohta, jossa pari ensimmäistä muunnosta heitetään pois, koska ne poikkeavat muista. LTC2440 antaa heti ensimmäisen muunnoksen yhtä tarkkana. Joko koodissa on vikaa tai sitten kyse on vastusten lämpenemisestä. Mielestäni ajat turhan suurta virtaa PT100:aan. Laita vaikkapa yksi noita 100 ohm tarkkuusvastuksia molemmille puolille siltaa, jolloin virtaa tippuu kolmasosaan ja PT100:n teho yhdeksäsosaan. Tosin silloin joudut laskemaan lämpötilan hiukan monimutkaisemmalla kaavalla ellet siirrä myös referenssiä vastusten sillan puolelle.

LT2021:stä en löytänyt, mutta tarkoittanet LT1021. Sille sanotaan maksimivirraksi 10 mA. Nyt syötät sillä 100 ohm siltaa 5 V:llä, jolloin virta on 50 mA (+ mahdolliset muut kuormat) eli 5-kertaisesti speksin verran! Sisääntulojännitteeksi tuolla sanotaan epäsuorasta vähintään 7,2 V.

Terve taas kaikki!

Ja pahoitteluni vielä eilisestä kiukusta - ja sen väärästä
kanavoimisesta. Yritän olla ihmisiksi— käämi taisi kärähtää!

Epäilykseni kohdistuvat nyt jmajan ja muidenkin vinkeistä
referenssiin, tai lähinnä siihen, että syötän rerefenssillä myös
100R vastussiltaa. LT1021 max. 10mA ei tosiaan riitä. Itse asiassa
koko piiri voi jo olla rikki.

Testaan huomenna 5V regulaattorilla (400mA), ja katson mitä
lukuja tulee. Jos tulee järkeviä, niin sitten vaan uusi referenssi
ja sen perään boosti transistorilla. LT1021 datalehdellä oli
parikin kytkentäesimerkkiä.

Jos olet mittaamassa vain lämpötilaa eli PT100:n vastusarvoa, et tarvitse tarkkaa referenssipiiriä mihinkään. Pienikohinainen regulaattori riittää aivan mainiosti. Mittaustapa on ratiometrinen eli mikään ei muutu, vaikka regulaattorin jännite olisi voltin pielessä. Tietysti absoluuttinen siltajänniite (yleismittarin mittaama) muuttuu, mutta ADC antaa saman koodin ja ohjelmasi laskee saman vastusarvon ja lämpötilan.

Jotta mittaustapa toimii ratiometrisesti, pitää sillan syöttö (tai silta + etuvastukset) ja ADC:n referenssijännite tulla samasta lähteestä. Tarkkuus siis menetetään, jos syötät siltaa regulaattorilla, mutta ADC:n referenssiä referenssipiirillä.

Yes!

Jmaja oli oikeassa…

Eli laitoin referenssiksi MCP1702500E -halpisregulaattorin,
samasta paikasta vastussillalle +5. Ja kun tehot (500mA)
riittävät, myös AD-muuntimen jännite.

Yleismittari näyttää nyt (huoneenlämpö) lukemaa
182 mV, koodi 181.xx mV joten linjassa mennään.

Tästä on hyvä viritellä eteenpäin.

# LTC2440 v1.1 Oct.25 2012  jpb
min,uVolts,pkpk,stdev
0.245, 183542.515, 309.542, 89.526
0.488, 183354.921, 130.534, 34.687
0.731, 183835.359, 1291.633, 277.865
0.973, 184752.078, 490.651, 172.562
1.216, 184359.734, 758.067, 236.768
1.459, 183683.000, 716.448, 185.685

Nyt ongelmana on sitten enää liian suuri virta ja ehkä liian suuri kohina. 182 mV tarkoittaa 116 ohmia eli n. 41 C. Jos tuo on huoneenlämmössä testattu, on poikkeama varsin suuri. Nyt tuosta menee läpi 5/(100+116)=23 mA eli PT100:aan jää 62 mW teho. Esimerkiksi tälle http://www.vishay.com/docs/28762/28762.pdf pintaliitos PT100:lle ilmoitetaan paikallaan olevassa ilmassa 0,9K/mW itselämpeneminen eli siitä tulisi jo 56 C virhe. Sinulla ei sentään ole noin paha tilanne, mutta ymmärrät varmaan, että virta on aivan liian suuri.

Heitä se siltakytkentä roskikseen ja laita vain lämpötilakompensoitu (=0,1 tai 0,01%) etuvastus kuten tämän ADC:n datasheetin kuvassa 38 http://cds.linear.com/docs/en/datasheet/2400fa.pdf
Koska 2440:n kohina on alempi, voit ehkä käyttää vielä tuotakin suurempaa etuvastusta. Tuo kytkentä vertaa kahta vastusta toisiinsa eli on ratiometrinen eli ei vaadit tarkkaa referenssiä (pienikohinaisen kyllä). Tuolla 12,1K vastuksella virta tippuu 0,4 mA tasolle, jolloin PT100:n teho on enää 0,016 mW. Samalla tuloimpedanssi pysyy pienenä eli ADC toimii tarkasti.

Kurkkaa myös seuraava kuva (kuva 39) ja niihin liittyvät selitysosiot.

Kuva 39 on hyvä. Kiitos Kelmi.

Haluaisin käyttää 2440 kahdella sisääntulolla: kuva 38 tarjoaa
vain positiivisen sisääntulon, kuvassa 39 on kallis opamppi
AD:n edessä. Voisiko siihen opampin tilalle pistää suoraan
LTC2440:n?

Jatkan harjoituksia. Muutoin menee hyvin, mutta sillan
tai vastusjaon virta pitää rajoittaa alla 1 mA…

Voit kytkeä LTC2440:n kuvan 38 mukaisesti siten, että laitat REF- GND, REF+ VCC, IN+ RTD:n yläpuolelle ja IN- RTD alapuolelle eli GND. Tuo kytkentä sinun on helppo tehdä nykyiseen kytkentääsi. Sillasta pitää poistaa yksi vastus, toinen muuttaa oikosuluksi ja kolmas kasvattaa 100->12,1k.

Juuri noilla arvoilla 0,01 C vastaa 1,6uV muutosta eli et tarvitse tuohon operaatiovahvistinta kunhan suunnittelet piirilevyn hyvin. Suhdetta voit muuttaa etuvastuksen valinnalla. 1 mA tulee 4,9k vastuksella, jolla 0,01 C vastaa 3,9 uV. Tuolla voit siis tehdä kompromissin resoluution ja itselämpiämisen välille.

Tässä vielä LTC2410:n datasheetistä kuva 50 http://cds.linear.com/docs/en/datasheet/2410fs.pdf, jossa on lähes identtinen kytkentä edellisen viestini kuvaukseen. Ainoa ero on REF- kytkentä RTD:n toiselle puolelle. Erolla ei ole käytännön merkitystä kytkennän toimivuuteen, mutta se vaikuttaa kaavaan, jolla lämpötila lasketaan. Tuo LTC2410 on toiminnaltaan identtinen LTC2440:n kanssa, mutta 2440:n kohina on pienempi ja sillä saa suurempia nopeuksia.