added filter-file, some rewrites, compiles, not tested

master
Paul Goeser 15 years ago committed by paul
parent 08c5d5e834
commit 6bac41b4e2

@ -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

@ -0,0 +1,102 @@
#include "filter.h"
#include <math.h>
#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;
}

@ -0,0 +1,17 @@
#include <stdint.h>
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);

@ -4,13 +4,11 @@
#include "i2c_simple.h"
#include "mcp_adc.h"
#include "debug.h"
#include "math.h"
#include <math.h>
#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");
}
}
}
}
}
}

@ -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;

@ -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

@ -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<<channel);
}
void offset_measure_start_all(){
PORTD |= 0x0f;
}
void offset_measure_stop(){
PORTD &= ~0x0f;
}

@ -4,7 +4,9 @@
void muxer_init();
void muxer_set(uint8_t channel);
uint8_t muxer_channel_to_selectbits(uint8_t channel);
void offset_measure_init();
void offset_measure_start(uint8_t channel);
void offset_measure_start_all();
void offset_measure_stop();

Loading…
Cancel
Save