From 4a1f9d06d27fc5e76bfdd6d533f7c7fa9103473f Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Tue, 3 Nov 2015 22:34:40 +0000 Subject: f4: proper float/int temp readings --- tests/adc-power/adc-power.c | 84 ++++++++++++++++++++---------------- tests/adc-power/main-stm32f4-disco.c | 6 +-- 2 files changed, 49 insertions(+), 41 deletions(-) (limited to 'tests') diff --git a/tests/adc-power/adc-power.c b/tests/adc-power/adc-power.c index 4214c05..4b591a6 100644 --- a/tests/adc-power/adc-power.c +++ b/tests/adc-power/adc-power.c @@ -19,6 +19,28 @@ // TODO - stick this in libopencm3? #define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +// Still have some bad shit to deal with... +#if defined(STM32F3) +#define SAMPLE_TIME_BASIC ADC_SMPR1_SMP_19DOT5CYC +#elif defined(STM32F4) +#define SAMPLE_TIME_BASIC ADC_SMPR_SMP_28CYC +#define SAMPLE_TIME_TEMP ADC_SMPR_SMP_144CYC +#define SAMPLE_TIME_VREF SAMPLE_TIME_TEMP +#define ADC_CHANNEL_TEMP ADC_CHANNEL_TEMP_F40 +#define SEPARATE_VREF 0 +#elif defined(STM32L1) +#define SAMPLE_TIME_BASIC ADC_SMPR_SMP_24CYC +#define SAMPLE_TIME_TEMP ADC_SMPR_SMP_192CYC +#define SAMPLE_TIME_VREF SAMPLE_TIME_TEMP +#define SEPARATE_VREF 0 +#else +#error "no sample time for your target yet?!" +#endif + +#ifndef SEPARATE_VREF +#define SEPARATE_VREF 1 +#endif + void adc_power_init(void) { @@ -29,10 +51,12 @@ void adc_power_init(void) rcc_adc_prescale(RCC_CFGR2_ADCxPRES_PLL_CLK_DIV_1, RCC_CFGR2_ADCxPRES_PLL_CLK_DIV_1); adc_enable_regulator(ADC1); adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR1_SMP_19DOT5CYC); - adc_set_sample_time(ADC1, ADC_CHANNEL_TEMP, ADC_SMPR1_SMP_181DOT5CYC); #else rcc_periph_clock_enable(RCC_ADC1); - adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28CYC); + adc_set_sample_time_on_all_channels(ADC1, SAMPLE_TIME_BASIC); + adc_set_sample_time(ADC1, ADC_CHANNEL_TEMP, SAMPLE_TIME_TEMP); + adc_set_sample_time(ADC1, ADC_CHANNEL_TEMP, SAMPLE_TIME_VREF); + #if 0 // DANGER DANGER! doing this without DMA is dum. // but... we're busy polling, we should be right... right? @@ -45,7 +69,10 @@ void adc_power_init(void) #endif adc_enable_temperature_sensor(); +#if (SEPARATE_VREF == 1) adc_enable_vrefint(); +#endif + /* * We're going to setup a timer to run at top speed, so... "fast" * but we don't actually care about the rate itself. We just @@ -68,28 +95,16 @@ static uint16_t read_adc_naiive(uint8_t channel) return adc_read_regular(ADC1); } -static uint16_t compensate_vref(uint16_t adc_count, uint16_t vref_count) { - uint32_t ret = adc_count * ST_VREFINT_CAL; - return (ret / vref_count); +static float adc_calc_tempf(unsigned int ts_v, unsigned int vref) { + float adjusted_vtemp = ts_v * ST_VREFINT_CAL * 1.0 / vref * 1.0; + float slope = (110-30) * 1.0 / (ST_TSENSE_CAL2_110C - ST_TSENSE_CAL1_30C) * 1.0; + return slope * (adjusted_vtemp - ST_TSENSE_CAL1_30C) + 30; } -static int work_temp(unsigned int ts_v, unsigned int vref) { - // This is important! as the calibration values are give us a slope in mv/C - int raw_temp_mv = compensate_vref(ts_v, vref); - // millivolts gives millcentigrade - float slope = raw_temp_mv - (ST_TSENSE_CAL1_30C * 1.0) / (ST_TSENSE_CAL2_110 * 1.0) - ST_TSENSE_CAL1_30C; - int temp_mc = (110 - 30) * slope + 30.0; - return temp_mc / 10; -} - -static float adc_calculate_temp(unsigned int ts_v) { -#if 0 - float factor = (110-30) / ((ST_TSENSE_CAL1_30C * 1.0) - (ST_TSENSE_CAL2_110 * 1.0)); - return (factor * (ts_v - ST_TSENSE_CAL2_110)) + 30.0; -#else - float factor = (110-30) / ((ST_TSENSE_CAL2_110 * 1.0) - (ST_TSENSE_CAL1_30C * 1.0)); - return (factor * (ts_v - ST_TSENSE_CAL1_30C)) + 30.0; -#endif +static float adc_calc_tempi(uint16_t ts, uint16_t vref) { + int adjusted_vtemp = ts * ST_VREFINT_CAL / vref; + int slope = (110-30) / (ST_TSENSE_CAL2_110C - ST_TSENSE_CAL1_30C); + return slope * (adjusted_vtemp - ST_TSENSE_CAL1_30C) + 30; } void adc_power_task_up(void) { @@ -100,30 +115,23 @@ void adc_power_task_up(void) { /* just for kicks, let's time some sequences too.... * I mean, we're going to do some conversions right? */ adc_set_single_conversion_mode(ADC1); -#if 0 - uint8_t channels[2] = { 0, 1 }; - adc_set_regular_sequence(ADC1, ARRAY_SIZE(channels), channels); - TIM_CNT(TIMER) = 0; - adc_start_conversion_regular(ADC1); - while (!adc_eoc(ADC1)); - unsigned int v1 = adc_read_regular(ADC1); - while (!adc_eoc(ADC1)); - unsigned int v2 = adc_read_regular(ADC1); - unsigned int tconv = TIM_CNT(TIMER); -#else TIM_CNT(TIMER) = 0; unsigned int v1 = read_adc_naiive(1); unsigned int v5 = read_adc_naiive(5); unsigned int temp_adc = read_adc_naiive(ADC_CHANNEL_TEMP); unsigned int vref_adc = read_adc_naiive(ADC_CHANNEL_VREF); - // TODO - use vref to adjust temp_adc for non-3v readings! - float temp = adc_calculate_temp(temp_adc); - int tempi = 100 * temp; unsigned int tconv = TIM_CNT(TIMER); -#endif + TIM_CNT(TIMER) = 0; + float tempf = adc_calc_tempf(temp_adc, vref_adc); + int tconvf = TIM_CNT(TIMER); + TIM_CNT(TIMER) = 0; + int tempi = adc_calc_tempi(temp_adc, vref_adc); + int tconvi = TIM_CNT(TIMER); printf("ton: %u, tconv: %u, ch1: %u, ch5: %u\n", td, tconv, v1, v5); - printf("\tTemperature: %f (raw count: %u)\n", temp, temp_adc); + printf("\tTemperature: %f (tc %d) or %d (tc %d) (raw ts: %d, raw vref: %d)\n", + tempf, tconvf, tempi, tconvi, temp_adc, vref_adc); + //printf("\tT1-30 %d, t2-110 %d, vrefcal: %d\n", ST_TSENSE_CAL1_30C, ST_TSENSE_CAL2_110C, ST_VREFINT_CAL); } void adc_power_task_down() diff --git a/tests/adc-power/main-stm32f4-disco.c b/tests/adc-power/main-stm32f4-disco.c index f02e610..47a0b3f 100644 --- a/tests/adc-power/main-stm32f4-disco.c +++ b/tests/adc-power/main-stm32f4-disco.c @@ -31,19 +31,19 @@ int main(void) rcc_periph_clock_enable(RCC_GPIOA); gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0); - gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1); + gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO5); adc_power_init(); while (1) { adc_power_task_up(); gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN); - for (i = 0; i < 0x1000000; i++) { /* Wait a bit. */ + for (i = 0; i < 0x800000; i++) { /* Wait a bit. */ __asm__("NOP"); } adc_power_task_down(); gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN); - for (i = 0; i < 0x1000000; i++) { /* Wait a bit. */ + for (i = 0; i < 0x800000; i++) { /* Wait a bit. */ __asm__("NOP"); } } -- cgit