V předchozím příspěvku byly představeny NTC termistory a základní matematiku, na které jsou postaveny. V tomto příspěvku bude představen způsob, jakým je možné změřit odpor termistoru a převést ho na teplotu. Většina technik v článku popisovaných je dostatečně obecných, aby je bylo možné využít s libovolným procesorem. Konkrétní implementace bude předvedena na platformě STM32F103.
Parametry NTC termistoru, se kterým bude celý test prováděn jsou:
- beta = 3470
- R0 = 10 000 / 25°C
Předtím, než se programátor pustí do vlastního programování je vždy dobré, když si rozmyslí, co a jak vlastně bude dělat. Dnešní úkol je vcelku snadný, změřit napětí na odporovém děliči, přepočítat na odpor a následně na teplotu. Tuto teplotu následně vytisknout, případně něco jiného.
V předchozím zápisku byl představen vzorec, pomocí kterého je možné tento přepočet provést. Jak si ale ověřit, že je tento vzorec správný ? Vhodné je využít nějakého již existujícího nástroje – například calc, případně octave. Níže je uveden krátký skript pro octave.
beta=3470; rref=10000; kelvin=273.15; tref=(kelvin + 25); rtemp = 10000; beta / log(rtemp / (rref * exp(-beta/tref))) - kelvin
Ze skriptu je šikovné zmínit především proměnnou rtemp, je to myšlený odpor, pro který chceme zjistit teplotu. Pro vybraný NTC termistor platí, že při teplotě 25 °C bude mít odpor přesně 10 000 ohmů. Vzorec je správný a nyní stačí napsat vlastní program pro daný mikroprocesor.
void adcSetup(void) { RCC_ADCCLKConfig(RCC_PCLK2_Div2); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_InitTypeDef ntcAdcSettings; ntcAdcSettings.ADC_Mode = ADC_Mode_Independent; ntcAdcSettings.ADC_ScanConvMode = DISABLE; ntcAdcSettings.ADC_ContinuousConvMode = DISABLE; ntcAdcSettings.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ntcAdcSettings.ADC_DataAlign = ADC_DataAlign_Right; ntcAdcSettings.ADC_NbrOfChannel = 1; ADC_RegularChannelConfig(ADC1, this->adcChannel, 1, ADC_SampleTime_41Cycles5); ADC_Init(ADC1, &ntcAdcSettings); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)) {} ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)) {} }
V následujícím odstavci bude popsána inicializace AD převodníku.
- Nastavit hodiny pro AD periferii
- Nastavit přístup k AD periferii – číst pouze jeden kanál, pouze na vyzvání a to právě jednou
- Zapnutí jednoho kanálu na AD periferii
- Vlastní nahrání konfigurace do AD periferie
- Spuštění AD periferie a kalibrace
Pro více informací k jednotlivým řádkům zdrojového kódu lze vyčíst z dokumentace knihovny pro STM. Inicializace ADC je pouze prvním krokem, tím druhým je vyčtení napětí, jeho převod a přepočet na teplotu.
double getTemperature() { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != SET){} ADC_ClearFlag(ADC1, ADC_FLAG_EOC); uint16_t voltage = (ADC_GetConversionValue(ADC1) * VREF) / 0xFFF; int resistance = ((VREF - voltage) * 1000 / ((voltage / R0) * 1000.0)); return (BETA / log(resistance / (R0 * exp(-(BETA / T0))))) - KELVIN; }
V této části kódu se nejprve spustí převod na AD periferii a následně čeká, než se vyčtení dokončí. Následně je vhodné vyčistit flag, který poukazuje, že AD převod byl dokončen. Doba převodu je specifikována v inicializační části parametrem ADC_SampleTime_41Cycles5. Následující část kódu je už pak pouhý přepočet AD hodnoty na napětí.
Závěrem lze zmínit i to, že by samozřejmě bylo možné použít již existující knihovny, například z Arduino projektu. Tento přístup by nám ale zastínil celou řadu možných potíží, které jsou s touto problematikou spojeny.