# HG changeset patch # User Matt Johnston # Date 1340716869 -28800 # Node ID d4c9c360448f5a00f0ba243c476a480142c3f4a2 # Parent daad73f65c0f0115f99b0cd33ad5e865539fc870# Parent 3db118498b97cd51f8c11a249ce822c8e493bc1c merge diff -r 3db118498b97 -r d4c9c360448f main.c --- a/main.c Tue Jun 26 08:08:48 2012 +0800 +++ b/main.c Tue Jun 26 21:21:09 2012 +0800 @@ -8,6 +8,7 @@ #include #include #include +#include #include // for DWORD of get_fattime() @@ -61,7 +62,7 @@ int uart_putchar(char c, FILE *stream); static void long_delay(int ms); static void blink(); -static void adc_internal(uint16_t *millivolt_vcc, uint16_t *int_temp); +static uint16_t adc_vcc(); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); @@ -72,7 +73,14 @@ // convenience static FILE *crc_stdout = &_crc_stdout; +// ---- Atomic guards required accessing these variables +static uint32_t clock_epoch; +static uint16_t comms_count; +static uint16_t measure_count; +// ---- End atomic guards required + static uint16_t n_measurements; + // stored as decidegrees static int16_t measurements[NUM_MEASUREMENTS][MAX_SENSORS]; static uint32_t first_measurement_clock; @@ -80,6 +88,8 @@ // samples static uint32_t last_measurement_clock; +static uint32_t last_comms_clock; + // boolean flags static uint8_t need_measurement; static uint8_t need_comms; @@ -92,10 +102,6 @@ static char readbuf[30]; static uint8_t have_cmd; -static uint16_t measure_count; -static uint16_t comms_count; - -static uint32_t clock_epoch; // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/ #define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size)) @@ -256,23 +262,28 @@ uint8_t n_sensors; eeprom_read(n_sensors, n_sensors); - uint16_t millivolt_vcc, int_temp; + uint16_t millivolt_vcc = adc_vcc(); - adc_internal(&millivolt_vcc, &int_temp); + uint32_t epoch_copy; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + epoch_copy = clock_epoch; + } - fprintf_P(crc_stdout, PSTR("START\n")); - fprintf_P(crc_stdout, PSTR("now=%lu\n" + fprintf_P(crc_stdout, PSTR("START\n" + "now=%lu\n" "time_step=%hu\n" "first_time=%lu\n" "last_time=%lu\n" + "comms_time=%lu\n" "voltage=%hu\n" - "avrtemp=%hu\n"), - clock_epoch, + ), + epoch_copy, (uint16_t)MEASURE_WAKE, first_measurement_clock, last_measurement_clock, - millivolt_vcc, - int_temp + last_comms_clock, + millivolt_vcc ); fprintf_P(crc_stdout, PSTR("sensors=%u\n"), n_sensors); for (uint8_t s = 0; s < n_sensors; s++) @@ -307,7 +318,10 @@ static void cmd_btoff() { - comms_count = 0; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + comms_count = 0; + } printf_P(PSTR("off:%hu\n"), COMMS_WAKE); _delay_ms(100); comms_timeout = 0; @@ -581,7 +595,6 @@ comms_count = 0; need_comms = 1; } - } DWORD get_fattime (void) @@ -607,97 +620,41 @@ sleep_mode(); } -static void -adc_internal(uint16_t *millivolt_vcc, uint16_t *int_temp) +static uint16_t +adc_vcc() { PRR &= ~_BV(PRADC); - // ADPS2 = /16 prescaler, 62khz at 1mhz clock + // /16 prescaler ADCSRA = _BV(ADEN) | _BV(ADPS2); // set to measure 1.1 reference ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); - ADCSRA |= _BV(ADSC); - loop_until_bit_is_clear(ADCSRA, ADSC); - uint8_t low_11 = ADCL; - uint8_t high_11 = ADCH; - uint16_t f_11 = low_11 + (high_11 << 8); - - float res_volts = 1.1 * 1024 / f_11; - *millivolt_vcc = 1000 * res_volts; + // average a number of samples + uint16_t sum = 0; + uint8_t num = 0; + for (uint8_t n = 0; n < 20; n++) + { + ADCSRA |= _BV(ADSC); + loop_until_bit_is_clear(ADCSRA, ADSC); - // measure AVR internal temperature against 1.1 ref. - ADMUX = _BV(MUX3) | _BV(REFS1) | _BV(REFS0); - ADCSRA |= _BV(ADSC); - loop_until_bit_is_clear(ADCSRA, ADSC); - uint8_t low_temp = ADCL; - uint8_t high_temp = ADCH; - uint16_t res_internal = low_temp + (high_temp << 8); - float internal_volts = res_internal * (1.1 / 1024.0); - // millivolts - *int_temp = internal_volts * 1000; - - PRR |= _BV(PRADC); - ADCSRA = 0; -} - -#if 0 -// untested -static void -do_adc_335() -{ - //PRR &= ~_BV(PRADC); - - ADMUX = _BV(ADLAR); + uint8_t low_11 = ADCL; + uint8_t high_11 = ADCH; + uint16_t val = low_11 + (high_11 << 8); - // ADPS2 = /16 prescaler, 62khz at 1mhz clock - ADCSRA = _BV(ADEN) | _BV(ADPS2); - - // measure value - ADCSRA |= _BV(ADSC); - loop_until_bit_is_clear(ADCSRA, ADSC); - uint8_t low = ADCL; - uint8_t high = ADCH; - uint16_t f_measure = low + (high << 8); - - // set to measure 1.1 reference - ADMUX = _BV(ADLAR) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); - ADCSRA |= _BV(ADSC); - loop_until_bit_is_clear(ADCSRA, ADSC); - uint8_t low_11 = ADCL; - uint8_t high_11 = ADCH; - uint16_t f_11 = low_11 + (high_11 << 8); - - float res_volts = 1.1 * f_measure / f_11; + if (n >= 4) + { + sum += val; + num++; + } + } + ADCSRA = 0; + PRR |= _BV(PRADC); - // 10mV/degree - // scale to 1/5 degree units above 0C - int temp = (res_volts - 2.73) * 500; - // XXX fixme - //measurements[n_measurements] = temp; - // XXX something if it hits the limit - - // measure AVR internal temperature against 1.1 ref. - ADMUX = _BV(ADLAR) | _BV(MUX3) | _BV(REFS1) | _BV(REFS0); - ADCSRA |= _BV(ADSC); - loop_until_bit_is_clear(ADCSRA, ADSC); - uint16_t res_internal = ADCL; - res_internal |= ADCH << 8; + float res_volts = 1.1 * 1024 * num / sum; - float internal_volts = res_internal * (1.1 / 1024.0); - - // 1mV/degree - int internal_temp = (internal_volts - 2.73) * 5000; - // XXX fixme - //internal_measurements[n_measurements] = internal_temp; - - printf_P("measure %d: external %d, internal %d, 1.1 %d\n", - n_measurements, temp, internal_temp, f_11); - - n_measurements++; - //PRR |= _BV(PRADC); + return 1000 * res_volts; } -#endif static void do_measurement() @@ -706,7 +663,9 @@ eeprom_read(n_sensors, n_sensors); simple_ds18b20_start_meas(NULL); - _delay_ms(DS18B20_TCONV_12BIT); + // sleep rather than using a long delay + deep_sleep(); + //_delay_ms(DS18B20_TCONV_12BIT); if (n_measurements == NUM_MEASUREMENTS) { @@ -734,11 +693,14 @@ measurements[n_measurements][s] = decicelsius; } - if (n_measurements == 0) + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - first_measurement_clock = clock_epoch; + if (n_measurements == 0) + { + first_measurement_clock = clock_epoch; + } + last_measurement_clock = clock_epoch; } - last_measurement_clock = clock_epoch; n_measurements++; //do_adc_335(); @@ -748,6 +710,10 @@ do_comms() { // turn on bluetooth + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + last_comms_clock = clock_epoch; + } set_aux_power(1); uart_on();