Arduino titkok - (Belső) feszültség- és hőfokmérés

Régi problémát jár körbe ez a cikk: az analóg jelek feldolgozását, mérését - nem a megszokott módon. Egy-egy probléma felvetése során kiderül, hogy gyorsabb-egyszerűbb módja is van feladat megoldásának - csak  nem teljesen triviális vagy a nyelv/kontroller által kínált különleges megoldást alkalmazhatunk.
A cikkben két ilyen lehetóséget járunk körbe: a saját feszültség mérését és a belső hőmérséklet követését. De lássuk  sorjában...

Saját feszültség mérése

A mikrokontroller rendszerek sok esetben elemről/akkumulátorról járnak. Ezek kimerülését legjobban a kapocsfeszültségük mérésével lehet nyomonkövetni. Külső alkatrészekkel a rendszer tápfeszültségét egyszerűen megmérhetjük:

// Minták száma
#define NUM_SAMPLES 10

int sum = 0;                    // Eddigi minták
unsigned char sample_count = 0; // Jelenlegi minta
float voltage = 0.0;            // Kalkulált feszültség

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    // Annyi mintát veszünk, amennyi a méréshez szükséges
    while (sample_count < NUM_SAMPLES) {
        sum += analogRead(A0);
        sample_count++;
        delay(10);
    }
    // Feszültségszámítás, 5V referenciafeszültséggel
    // a valódi feszültséggel korrigálva (4.950)
    voltage = ((float)sum / (float)NUM_SAMPLES * 4.950) / 1024.0;
    // Az eredményi kiíratjuk, felszorozva az osztó osztásarányával
    // Az osztó pontos aránya 5.555
    Serial.print(voltage * 5.555);
    Serial.println (" V");
    sample_count = 0;
    sum = 0;
}

Azonban a külső ellenállásháló ehhez a méréshez szükséges. Viszont van legalább kétféle feszültségünk a rendszerben: A tápfeszültség és a belső referenciafeszültség. Mi lenne, ha a Tápfeszültség lenne a mérés maximumértéke (referenciája) és a belső referenciát mérnénk meg? Nem lenne más a mérés mint egyszerű aránypár:

Vcc : Vref = 1023 : mérés

Ehhez kicsit ki kell nyúlni az Arduino keretrendszerből átkombinálni az ADC bemenetválasztást.

long readVcc() {
  long result;
  // 1.1V referenciafeszültség mérése, a max. referencia: AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Vref beállási idő
  ADCSRA |= _BV(ADSC); // Mérés
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1100L * 1024L / result; // AVcc kiszámítása [mV]
  //1100 mV Vref * 1024 ADC felbontás
  return result;
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println( readVcc(), DEC ); //Eredmény kiírás
  delay(1000);
}

A kapott eredményt millivoltban kapjuk meg. Így az 5000 az 5V tápfeszültség, a 3300 pedig a 3.3V.

Fontos! A saját feszültség mérése nem minden AVR chipen lehetséges. A támogatott chipek: ATMega168, ATMega328, ATMega328P, ATMega1280, ATMega2560, ATTiny24, ATTiny44, ATTiny84, ATTiny25, ATTiny45, ATTiny85, ATMega16U4 és ATMega32U4.

Hogyan működik a belső referenciafeszültséggel a külső feszültség mérése?

Az Arduino lapkák ATMega328 illetve ATMega168 chippel szerelt változata 1.1V referenciafeszültségű, míg az ATMega2560 1.1V és 2.56V feszültségű dupla referenciát tartalmaz. Ezt analóg mérésekre lehet használni - de legtöbbször e belső helyett a Vcc feszültség a referencia (hiszen így tudunk a teljes tápfeszültségtartományban mérni). A chip azonban egy belső multiplexert (kapcsolót) tartalmaz, melynek segítségével kiválaszthatjuk, hogy melyik analóg kivezetést akarjuk mérni. Ám a belső kapcsolónak maradtak még szabad kivezetései, melyre hasznos dolgok lettek rákötve. Például a belső referenciafeszültség kiválasztható.

 

Kép, az adatlap 251. oldaláról

Minthogy az 1.1V referenciafeszültsége ismert, így a Vcc feszültség ebból már könnyen kiszámítható. Az aránypár: 

Vcc : Vref = 1024 : ADCeredmény 

Ezt egy kicsit átrendezve, ismerve, hogy a Aref 1.1V (1100mV), így:

Vcc = (Vref * 1024)/ADCeredmény = (1100*1024)/ADCeredmény = 1128000L/ADCeredmény

A 1128000L írásmód pedig jelzi, hogy long típusú változót kívánunk létrehozni. Innentől a program jól követhető. Azonban az egész eljárást eldugtuk a ReadVcc() eljárásba. Ennek kisebb kivővítésével egyidőben az összes ismert chip is megszólítható, vagy akár külső eljáráskönyvtárba is kiszervezhető.

Hőmérsékletmérés

Azok az Arduino lapkák, amelyek ATMega328P chippel szereltek, azok belső hőmérőt is tartalmaznak. Ez az UNO illetve a Duemilanove / Diecimila. De tartamaz még hőmérőt az ATMega32U4 chip is (Leonardo lapka). Azonban az ATMega2560 chip nem (így az Arduino Mega lapka nem alkalmas a kísérlethez).

A mintaprogram UNO / Diecimila / Duemilanove (ATMega328 chiphez):

long readTemp() {
  long result;
  // Hőmérés , 1V1 belső referenciával
  ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
  delay(2); // Tranziensek lefutása
  ADCSRA |= _BV(ADSC); // Konverzió
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = (result - 125) * 1075;
  return result;
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println( readTemp(), DEC );
  delay(1000);
}

Az eredményt a hőfok 10000-szereseként kapjuk vissza. Azaz a 250000 jelenti a 25°C chiphőmérsékletet. A hőfok számításakor a tizedes formában is kiírathatnánk, azonban a törtszámok kezelése erőforrásigényes (flashmemória és program futásidő is).

Hogyan működik a belső hőmérséklet mérése?

Az ATMega328 illetve ATMega168 chippel szerelt változata 1.1V referenciafeszültségű. Ezt az analóg mérésekre lehet használni, de legtöbbször e helyett a Vcc feszültség a referencia (így tudunk a teljes tápfeszültségtartományban mérni). A chip belső kapcsolót tartalmaz, melynek segítségével kiválaszthatjuk, hogy melyik analóg kivezetést akarjuk mérni. A belső kapcsolónak maradtak ki kivezetései, melyre hasznos dolgok lettek rákötve. Például a belső hőmérő kiválasztható.



Kép, az adatlap 251. oldaláról (Hőmérő a bementválasztó multiplexer felső részén)

A hőmérőszenzor nem túl nagy pontosságú. 10 fokos szórása van a kontroller adatlapja szerint. De, ha egyszer ez kalibrálásra került, akkortól a pontossága már általános feladatokra megfelel (~1 fokos pontosságú standard méréskor, precíziós mérésként 0,1 fok is elérhető).

Fontos! A hőmérő az ATMega328, ATMega32U4 chipben érhető el. Az ATMega168, ATMega8 illetve ATMega2560 esetén nem használható.  Kalibráció nélkül csak tendenciák követésére használáható, kalibrálva azonban egyszerűbb hőfokmérésre is alkalmas.

Tipp: A referencafeszültség állításakor figyelemmel kell lenni több tényezőre:

  1. A Vref kivezetésen a referenciafeszültséget illik 100nF kondenzátorral szűrni. Azonban, ha a refernciafeszültséget átállítjuk, akkor a kondenzátor feszültségének ezt követnie kell - ezért nem lehet azonnal a referencia átállítása után mérni. A mintaprogramokban a késleltetés 2msec. Ha a mérés ugrál/bizonytalan, akkor 10msec-ig növelhető ez a várakozás.
  2. Ha külső feszültségreferenciát használunk, akkor SOHA ne állítsunk be belső 1.1V/2.56V vagy Vcc referenciafeszültséget az Arduino rendszerben! Ekkor ugyanis a belső, kiválasztott feszültségreferencia megjelenik az ARef kivezetésen. Így sikerül az általunk beépített feszültségreferenciát összekötni a belső érzékeny feszültséggenerátorral! Ennek az álmoskönyv szerint melegedés illetve tönkremenetel lesz az eredménye.

Mellékletben a kombinált, összes AVR chipet támogató megoldás is megtalálható.

 

TavIR-Facebook