#include "main.h" /********************************************************************************* * Měření teploty s nějakou lepší přesností není zase tak jednoduché. Nakonec byl * jako čidlo zvolen NTC termistor polské výroby, kde výrobce zaručuje přesnost * odporu a beta parametru 1%. Ten beta parametr je celkem použitelný v malém rozsahu * teplot (10 - 70°C), z tabulky se ale dají spočítat koeficienty Steinhart-Hartových * vzorců, které sedí ve větším rozsahu (viz adresář compute). * Vlastní měření je celkem jednoduché - stačí udělat odporový dělič z napájecího * napětí na zem pomocí přesného rezistoru (zde také 1%) 10k a NTC 10k (při 25°C) * a jeho střed připojit na vstup ADC. Pak lze spočítat závislost teploty na * hodnotě ADC jako funkci, pro inverzní funkci udělat aproximaci pomocí kubických splajnů * a máme fakticky hotovo. Výhoda je, že to nezávisí na napájecím (referenčním) napětí. * * Protože tento procesor nemá koprocesor pohyblivé řádové čárky, dodělal jsem do toho * potřebnou aritmetiku v pevné čárce (tedy v celých číslech). Protože koeficienty * polynomů se liší o mnoho řádů, bylo potřeba udělat bitové posuny poměrně variabilní. * A celé to otestovat, jestli to někde nepřetéká. Pak lze zobazit teplotu na RS485 * na dvě desetinná místa a protože se teplota mění pomalu a je použit plovoucí průměr, * zobrazení je stabilní. * * Aniž bych to nějak kalibroval, zdá se, že teplota celkem sedí na +/- 0.5°C. * Ve vodě s ledem to ukazuje 0.50°C, moje tělesná teplota je pak 36.6°C. * * NOTE : Budič RS485 je pětivoltový, takže jeho výstup Rx data jsem připojil pro jistotu * k procesoru přes odpor 1k. S tím, že záchytné diody přepětí nějak požerou. * Ukazuje se, že to sice funguje, ale ADC pak dost kecá - nějak mu tam to zvýšené * napětí proniká. Stačí pak přizemnit Rx procesoru (PA3) přes odpor 1.5 až 2k a problém * zmizí. **********************************************************************************/ static constexpr Pair measured [] = { // pár hodnota ADC, teplota ve °C { +133.9, 125.000 }, { +152.2, 120.000 }, { +198.3, 110.000 }, { +260.0, 100.000 }, { +343.6, 90.000 }, { +456.9, 80.000 }, { +609.9, 70.000 }, { +814.5, 60.000 }, { +1082.6, 50.000 }, { +1421.2, 40.000 }, { +2047.5, 25.000 }, { +2729.0, 10.000 }, { +3139.8, 0.000 }, { +3472.7, -10.000 }, { +3715.6, -20.000 }, { +3876.9, -30.000 }, { +3960.2, -38.000 }, { +3976.0, -40.000 }, }; /*********************************************************************************/ static FIFO termring; static const GpioClass led (GPIOB, 8); static Usart serial (57600); static RealOut cout; static AdcDma adc; static Average avg (termring); static const SPLINE spline (measured, false); int main () { led << true; adc.attach(avg); cout += serial; int passcnt = 0; for (;;) { uint32_t value; if (termring.Read (value)) { // value je de facto posunuta doleva o 7, potřebujeme o 16 - rozdíl je tedy 9 const int32_t ivalue = static_cast(value << 9); const real temperature = spline.interpolate(real(ivalue)); cout << "t = " << temperature << " °C\r\n"; const bool b = passcnt & 1; led << b; passcnt += 1; } } return 0; }