From 6bac41b4e2bdae952987aec8b7d1c3bc32ca6c7c Mon Sep 17 00:00:00 2001 From: Paul Goeser Date: Fri, 8 Apr 2011 23:37:47 +0200 Subject: [PATCH] added filter-file, some rewrites, compiles, not tested --- firmware/slavechip/Makefile | 2 +- firmware/slavechip/filter.c | 102 +++++++++++++++++++++++ firmware/slavechip/filter.h | 17 ++++ firmware/slavechip/main.c | 152 +++++++++++------------------------ firmware/slavechip/mcp_adc.c | 9 +-- firmware/slavechip/mcp_adc.h | 6 +- firmware/slavechip/muxer.c | 19 ++++- firmware/slavechip/muxer.h | 2 + 8 files changed, 193 insertions(+), 116 deletions(-) create mode 100644 firmware/slavechip/filter.c create mode 100644 firmware/slavechip/filter.h diff --git a/firmware/slavechip/Makefile b/firmware/slavechip/Makefile index f59158b..8d11541 100644 --- a/firmware/slavechip/Makefile +++ b/firmware/slavechip/Makefile @@ -4,7 +4,7 @@ DEFINES += -DF_CPU=8000000 COMPILE = avr-gcc $(CFLAGS) $(DEFINES) -OBJECTS = main.o mcp_adc.o i2c_simple.o softtimer.o spi_proto.o spi.o spi_pointers.o muxer.o debug.o +OBJECTS = main.o mcp_adc.o i2c_simple.o softtimer.o spi_proto.o spi.o spi_pointers.o muxer.o debug.o filter.o # symbolic targets: all: firmware.hex diff --git a/firmware/slavechip/filter.c b/firmware/slavechip/filter.c new file mode 100644 index 0000000..a2658be --- /dev/null +++ b/firmware/slavechip/filter.c @@ -0,0 +1,102 @@ + +#include "filter.h" +#include + +#define CHANNELCOUNT 8 + +float avg_cumul[CHANNELCOUNT]; +float avg_lastval[CHANNELCOUNT]; +uint8_t avg_count[CHANNELCOUNT]; +float avg_noise[CHANNELCOUNT]; + +void filter_average_input(uint8_t channel, float value) { + avg_cumul[channel] += value; + float noisetmp = avg_lastval[channel] - value; + avg_noise[channel] += noisetmp * noisetmp; + avg_count[channel] += 1; +} + +uint8_t filter_average_done(uint8_t channel, uint8_t samples){ + if(avg_count[channel] >= samples){ + return(1); + } + return 0; +} + +float filter_average_temp_result(uint8_t channel){ + float out = avg_cumul[channel]; + out /= avg_count[channel]; + return out; +} + +float filter_average_result(uint8_t channel){ + float out = filter_average_temp_result(channel); + avg_lastval[channel] = out; + avg_cumul[channel] = 0; + avg_noise[channel] = 0; + avg_count[channel] = 0; + return out; +} + +float filter_average_noise(uint8_t channel){ + float noise = avg_noise[channel]; + noise /= avg_count[channel]; + return noise; +} + +uint16_t filter_float_to_decimal8(float f){ + return( (uint16_t)(f / 256.) ); +} + +//uint16_t calc_temp(int16_t val, uint8_t channel) { +// float mV = ((float) avg_temp(val, channel))/1000000; +float filter_voltage_to_temp(float mV){ + float temp = 0; + if(mV < 0) { + /* t in mV + E = sum(i=0 to n) c_i t^i. ; n=10 + */ + const static float coef[] = { + 0.000000000000E+00, + 0.394501280250E-01, + 0.236223735980E-04, + -0.328589067840E-06, + -0.499048287770E-08, + -0.675090591730E-10, + -0.574103274280E-12, + -0.310888728940E-14, + -0.104516093650E-16, + -0.198892668780E-19, + -0.163226974860E-22 + }; + for(int i=0; i<11; i++) { + temp += coef[i] * pow(mV, i); + } + } else { + /* + t in mV + E = sum(i=0 to n) c_i t^i + a0 exp(a1 (t - a2)^2). ; n = 9 + */ + const static float coef[] = { + -0.176004136860E-01, + 0.389212049750E-01, + 0.185587700320E-04, + -0.994575928740E-07, + 0.318409457190E-09, + -0.560728448890E-12, + 0.560750590590E-15, + -0.320207200030E-18, + 0.971511471520E-22, + -0.121047212750E-25 + }; + const static float a[] = {0.118597600000E+00, -0.118343200000E-03, 0.126968600000E+03}; + for(int i=0; i<10; i++) { + temp += coef[i]*pow(mV, i); + } + // ich glaube das summenzeichen erstreckt sich nicht auf das exp + temp += a[0] * pow(exp(a[1]*(mV - a[2])), 2); + + } + return temp; +} + diff --git a/firmware/slavechip/filter.h b/firmware/slavechip/filter.h new file mode 100644 index 0000000..2bbf978 --- /dev/null +++ b/firmware/slavechip/filter.h @@ -0,0 +1,17 @@ + +#include + +void filter_average_input(uint8_t channel, float value); + +uint8_t filter_average_done(uint8_t channel, uint8_t samples); + +float filter_average_temp_result(uint8_t channel); + +float filter_average_result(uint8_t channel); + +float filter_average_noise(uint8_t channel); + +uint16_t filter_float_to_decimal8(float f); + +float filter_voltage_to_temp(float mV); + diff --git a/firmware/slavechip/main.c b/firmware/slavechip/main.c index b5106ff..edccbcc 100644 --- a/firmware/slavechip/main.c +++ b/firmware/slavechip/main.c @@ -4,13 +4,11 @@ #include "i2c_simple.h" #include "mcp_adc.h" #include "debug.h" -#include "math.h" +#include +#include "filter.h" uint16_t timertmp; uint16_t temperatures[4]; -uint8_t sensor_active[4]; -int32_t temp_avg_cumul[4]; -int16_t temp_avg_count[4]; /* pinout * - i2c: @@ -26,70 +24,6 @@ int16_t temp_avg_count[4]; * amp 0 is on muxer channel 2 */ -#define MUXER_CHANNEL_0 2 -#define MUXER_CHANNEL_1 0 -#define MUXER_CHANNEL_2 1 -#define MUXER_CHANNEL_3 3 - - -int32_t avg_temp(int16_t val, uint8_t channel) { - int32_t temp = temp_avg_cumul[channel]; - temp /= temp_avg_count[channel]; - temp_avg_count[channel] = 0; - temp_avg_cumul[channel] = 0; - return (temp * 625); // nV -} - -uint16_t calc_temp(int16_t val, uint8_t channel) { - float mV = ((float) avg_temp(val, channel))/1000000; - uint16_t temp = 0; - if(mV < 0) { - /* t in mV - E = sum(i=0 to n) c_i t^i. ; n=10 - */ - float coef[] = { - 0.000000000000E+00, - 0.394501280250E-01, - 0.236223735980E-04, - -0.328589067840E-06, - -0.499048287770E-08, - -0.675090591730E-10, - -0.574103274280E-12, - -0.310888728940E-14, - -0.104516093650E-16, - -0.198892668780E-19, - -0.163226974860E-22 - }; - for(int i=0; i<11; i++) { - temp += coef[i] * pow(mV, i); - } - } else { - /* - t in mV - E = sum(i=0 to n) c_i t^i + a0 exp(a1 (t - a2)^2). ; n = 9 - */ - float coef[] = { - -0.176004136860E-01, - 0.389212049750E-01, - 0.185587700320E-04, - -0.994575928740E-07, - 0.318409457190E-09, - -0.560728448890E-12, - 0.560750590590E-15, - -0.320207200030E-18, - 0.971511471520E-22, - -0.121047212750E-25 - }; - float a[] = {0.118597600000E+00, -0.118343200000E-03, 0.126968600000E+03}; - for(int i=0; i<10; i++) { - temp += coef[i]*pow(mV, i) - } - // ich glaube das summenzeichen erstreckt sich nicht auf das exp - temp += a[0] * pow(exp(a[1]*(mV - a[2])), 2); - - } - return temp; -} /* initializes the hardware */ void hardinit() { @@ -114,50 +48,60 @@ void softinit() { int __attribute__((noreturn)) main(void) { - hardinit(); - softinit(); + hardinit(); + softinit(); - muxer_set(MUXER_CHANNEL_0); + muxer_set(0); - for(;;){ + uint8_t active_sensor = 0; + + for(;;){ - SOFTTIMER(1,10) { - for(int i=0; i<4; i++) { - if(sensor_active[i] && mcpadc_has_new_data(i)) { - temperatures[i] = calc_temp( mcpadc_get_data(i), i ); - temp_avg_cumul[i] += temperatures[i]; - temp_avg_count[i] += 1; + SOFTTIMER(1,10) { + if(mcpadc_has_new_data()) { + int16_t data = mcpadc_get_data(); + float f = filter_voltage_to_temp( + ((float)data) * 0.000625 ); + // total gain is 100 (50 from INA, 2 from ADC) + // full signed range on ADC is +-2.048V + // with 16bit, 1LSB is worth 0.0625mV + // with the gain added in that's 0.000625 + + filter_average_input(active_sensor, f); + if(filter_average_done(active_sensor,16)){ + float noise = filter_average_noise(active_sensor); + float temp = filter_average_result(active_sensor); + dbgLog("temp: %3.3f°C (lastval %i), noise: %3.5f",temp, data, noise); + } } - } - } + } - SOFTTIMER(2,500){ - for(int i=0; i<4; i++) { - if(sensor_active[i]) { - int32_t temp = temp_avg_cumul[i]; - temp /= temp_avg_count[i]; - temp_avg_count[i] = 0; temp_avg_cumul[i] = 0; - int32_t nV = (temp * 625); - int32_t mK = nV/39; - dbgLog("temp-%i: %6li (%li µV, %li mK)\n",i,temp,nV/1000, mK); +/* SOFTTIMER(2,500){ + for(int i=0; i<4; i++) { + if(sensor_active[i]) { + int32_t temp = temp_avg_cumul[i]; + temp /= temp_avg_count[i]; + temp_avg_count[i] = 0; temp_avg_cumul[i] = 0; + int32_t nV = (temp * 625); + int32_t mK = nV/39; + dbgLog("temp-%i: %6li (%li µV, %li mK)\n",i,temp,nV/1000, mK); + } } } - } - - SOFTTIMER(3,4000){ - static uint8_t toggle; - if(toggle){ - offset_measure_start(0); - toggle=0; - dbgLog("measuring offset\n"); - } else { - offset_measure_stop(); - toggle=1; - dbgLog("stopping offset-measuring\n"); +*/ + SOFTTIMER(3,4000){ + static uint8_t toggle; + if(toggle){ + offset_measure_start(0); + toggle=0; + dbgLog("measuring offset\n"); + } else { + offset_measure_stop(); + toggle=1; + dbgLog("stopping offset-measuring\n"); + } } - } - - } + } } diff --git a/firmware/slavechip/mcp_adc.c b/firmware/slavechip/mcp_adc.c index 1c6856a..4027426 100644 --- a/firmware/slavechip/mcp_adc.c +++ b/firmware/slavechip/mcp_adc.c @@ -42,10 +42,8 @@ void mcpadc_init(uint8_t mode) curmode = mode; } -uint8_t mcpadc_has_new_data(uint8_t channel) +uint8_t mcpadc_has_new_data() { - // TODO: implement channel - /* this assumes that the first RDY bit read after the sample data indicates the old/new state of the sample we just read */ if(unread_data_available){ // we already have new data, don't overwrite that by reading more @@ -71,9 +69,8 @@ uint8_t mcpadc_has_new_data(uint8_t channel) } #if ADC_ENABLE_18_BIT_MODE -int32_t mcpadc_get_data(uint8_t channel) +int32_t mcpadc_get_data() { - // TODO: implement channel if(!unread_data_available){ return 0; } @@ -89,7 +86,7 @@ int32_t mcpadc_get_data(uint8_t channel) return value; } #else -int16_t mcpadc_get_data(uint8_t channel) +int16_t mcpadc_get_data() { if(!unread_data_available){ return 0; diff --git a/firmware/slavechip/mcp_adc.h b/firmware/slavechip/mcp_adc.h index 33cf987..3b50229 100644 --- a/firmware/slavechip/mcp_adc.h +++ b/firmware/slavechip/mcp_adc.h @@ -26,15 +26,15 @@ void mcpadc_init(uint8_t mode); /* tests if the adc has a new sample * returns nonzero if new data is aviable, 0 otherwise */ -uint8_t mcpadc_has_new_data(uint8_t channel); +uint8_t mcpadc_has_new_data(); /* returns the most recent sample result of the adc * !! return type depends on defines */ #if ADC_ENABLE_18_BIT_MODE -int32_t mcpadc_get_data(uint8_t channel); +int32_t mcpadc_get_data(); #else -int16_t mcpadc_get_data(uint8_t channel); +int16_t mcpadc_get_data(); #endif /* instructs the adc to take a new sample now diff --git a/firmware/slavechip/muxer.c b/firmware/slavechip/muxer.c index 39c3a3d..fcf2493 100644 --- a/firmware/slavechip/muxer.c +++ b/firmware/slavechip/muxer.c @@ -4,29 +4,44 @@ void muxer_init(){ DDRC |= (_BV(0)|_BV(1)|_BV(2)|_BV(3)); // conf as outputs PORTC |= _BV(3); // inhibit + // for good measure call the offset init, calling it twice doesn't hurt + offset_measure_init(); } void muxer_set(uint8_t channel){ + uint8_t selectbits = muxer_channel_to_selectbits(channel); PORTC |= _BV(3); // engage inhibit PORTC &= ~(0x07); //mask - PORTC |= channel & 0x07; //set + PORTC |= selectbits & 0x07; //set PORTC &= ~(_BV(3)); // disengage inhibit //TODO: delays, check everything, mask in register } +uint8_t inline muxer_channel_to_selectbits(uint8_t channel){ + static uint8_t table[] = {2,0,1,3}; + if(channel>=4){ + return 0; + } + return(table[channel]); +} + void offset_measure_init(){ DDRD |= 0x0f; // first 4 pins as output // PORTD = 0x00; // turn everything off } void offset_measure_start(uint8_t channel){ - if(channel >3){ + if(channel > 3){ return; } PORTD |= (1<