Re: Peripetie s termočlánky (Vianocna list..

Miroslav Mraz mrazik na volny.cz
Středa Prosinec 25 11:34:45 CET 2024


Koukal jsem na to a trochu si hrál s překladačem a jak definovat 
polynomy. Zkusil jsem 3 způsoby

static constexpr int coeff [] = {1,2,3,4,5};
// default optimize -Os
int poly_a (const int x) {
   int y = coeff[4];
   int t = x;
   y += coeff[3] * t;  t *= x;
   y += coeff[2] * t;  t *= x;
   y += coeff[1] * t;  t *= x;
   y += coeff[0] * t;
   return y;
}
int poly_b (const int x) {
   return  ((((coeff[0]  * x)
             + coeff[1]) * x
             + coeff[2]) * x
             + coeff[3]) * x
             + coeff[4];
}
[[using gnu: optimize("O3")]] // unroll loop
int poly_c (const int x) {
   int y = 0;
   for (auto c : coeff) { y *= x; y += c; }
   return y;
}

Způsob a) je podobný kódu, co poslal balu, odděleně počítá mocninu 
argumentu, což není příliš efektivní. Způsob b) vyplyne z toho, pokud 
polynom napíšeme podle definice a uvědomíme si, že x je z toho možné 
povytýkat, ozávovorkovat to a je to jednodušší. A nakonec způsob c) 
jednoduchou smyčkou umožní to celé napsat jednodušeji.

Ale proč to píšu. Uvědomil jsem si jak chytré jsou moderní překladače. 
Když donutím překladač, aby smyčku rozvinul, výsledný kód pro b) a c) 
jsou (pro RISC-V, ale zřejmě i jinde) naprosto stejné. Překladač pozná, 
že první násobení 0 je zbytečné a vyhodí ho. A nejen to - pozná i 
zbytečnost násobení 1 (1. koeficient, je konstatní), neprovádí ho.

Mrazík

On 24. 12. 24 16:13, Daniel Valuch wrote:
> poslane sukromne...
> 
> Ano, ja som to tiez minuly rok studoval spracovanie signalov od RTD a 
> termoclankov cele vianoce. Zaujimava problematika. Dokumenty priamo z 
> BIPM na temu ITS-90 a tabulky koeficientov pre RTD aj termoclanky od 
> NISTu su velmi dobry zaklad a su velmi informativne.
> 
> Prikladam vycuc z kodu
> 
>    if (MeasureTC1) {
>        // measure cold junction temperature first
>        RColdJunction = (float)ADCavrgCJ / (float)ADCavrgRef * R0; // 
> scaling of cold junction and reference cancels out
>        TemperatureCJ = 
> RTDpolynomial(WCorrection(RColdJunction/R0nominal)); // calculate cold 
> junction temperature
> 
>        VCJ = ThermoCoupleK_TtoE(TemperatureCJ - 273.16); // equivalent 
> Cold Junction voltage
>        VTC1raw = (float)ADCavrgTC1 * QueueBitShift * LSBmV * 
> TC1InvGain;  // convert measured ADC number to voltage in mV
>        VTC1raw = VTC1raw - 
> TC1offsetVoltage;                              // suppress analogue 
> offset (e.g. from the op-amp)
>        VTC1comp = VTC1raw + 
> VCJ;                                          // cold junction voltage 
> added to measured voltage
>        TemperatureTC1 = ThermoCoupleK_EtoT(VTC1comp);
>        // 0=Celsius, 1=Kelvin, 2=Farenheit, 3=Ohm, 4=microVolt
>        if (unit == 0) {
>          PrepareText(TemperatureTC1, 0);
>        } else if (unit == 1) {
>          PrepareText(TemperatureTC1 + 273.15, 1);
>        } else if (unit == 2) {
>          PrepareText(TemperatureTC1 * 1.8 + 32.0, 2);
>        } else if (unit == 3) {
>          PrepareText(VTC1raw, 4);
>        }
>      }
> 
> 
> float ThermoCoupleK_EtoT(float e) {
>    // type K ITS-90 polynomial
>    // https://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html
>    const float d0m = 0.0e0;
>    const float d1m = 2.5173462e1;
>    const float d2m = -1.1662878e0;
>    const float d3m = -1.0833638e0;
>    const float d4m = -8.9773540e-1;
>    const float d5m = -3.7342377e-1;
>    const float d6m = -8.6632643e-2;
>    const float d7m = -1.0450598e-2;
>    const float d8m = -5.1920577e-4;
> 
>    const float d0p = 0.000000e0;
>    const float d1p = 2.508355e1;
>    const float d2p = 7.860106e-2;
>    const float d3p = -2.503131e-1;
>    const float d4p = 8.315270e-2;
>    const float d5p = -1.228034e-2;
>    const float d6p = 9.804036e-4;
>    const float d7p = -4.413030e-5;
>    const float d8p = 1.057734e-6;
>    const float d9p = -1.052755e-8;
> 
>    float E = 0.0;
>    float t90 = 0.0;
> 
>    E = e;
> 
>    if (e < 0.00) {  // negative temperature
>      t90 = t90 + d1m * E;
>      E = E * e;
>      t90 = t90 + d2m * E;
>      E = E * e;
>      t90 = t90 + d3m * E;
>      E = E * e;
>      t90 = t90 + d4m * E;
>      E = E * e;
>      t90 = t90 + d5m * E;
>      E = E * e;
>      t90 = t90 + d6m * E;
>      E = E * e;
>      t90 = t90 + d7m * E;
>      E = E * e;
>      t90 = t90 + d8m * E;
>    } else if (e >= 0 && e < 20.644) {  // positive temperature <500 C
>      t90 = t90 + d1p * E;
>      E = E * e;
>      t90 = t90 + d2p * E;
>      E = E * e;
>      t90 = t90 + d3p * E;
>      E = E * e;
>      t90 = t90 + d4p * E;
>      E = E * e;
>      t90 = t90 + d5p * E;
>      E = E * e;
>      t90 = t90 + d6p * E;
>      E = E * e;
>      t90 = t90 + d7p * E;
>      E = E * e;
>      t90 = t90 + d8p * E;
>      E = E * e;
>      t90 = t90 + d9p * E;
>    } else {
>      t90 = -273.0;
>    }
> 
>    return t90;
> }
> 
> 


Další informace o konferenci Hw-list