78 lines
3.6 KiB
C++
78 lines
3.6 KiB
C++
|
#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<uint32_t, FIFOLEN> termring;
|
||
|
static const GpioClass led (GPIOB, 8);
|
||
|
static Usart serial (57600);
|
||
|
static RealOut cout;
|
||
|
static AdcDma adc;
|
||
|
static Average avg (termring);
|
||
|
static const SPLINE<array_size(measured)> 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<int32_t>(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;
|
||
|
}
|