Mercurial > templog
changeset 319:9621436cfa07
Add eeprom stuff
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 19 May 2012 23:59:12 +0800 |
parents | 31199b2941f6 |
children | cff7a4459dc9 |
files | Makefile main.c simple_ds18b20.c |
diffstat | 3 files changed, 231 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sat May 19 21:47:09 2012 +0800 +++ b/Makefile Sat May 19 23:59:12 2012 +0800 @@ -79,6 +79,10 @@ flash: all $(AVRDUDE) -U flash:w:main.hex:i +checkprog: + $(AVRDUDE) -v + + fuse: $(AVRDUDE) $(FUSES)
--- a/main.c Sat May 19 21:47:09 2012 +0800 +++ b/main.c Sat May 19 23:59:12 2012 +0800 @@ -6,17 +6,20 @@ #include <stdio.h> #include <string.h> +#include <stddef.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <util/delay.h> #include <avr/pgmspace.h> +#include <avr/eeprom.h> #include <util/crc16.h> // for DWORD of get_fattime() #include "integer.h" #include "simple_ds18b20.h" +#include "onewire.h" // configuration params // - measurement interval @@ -28,6 +31,9 @@ #define SLEEP_COMPARE 32 #define MEASURE_WAKE 60 +#define VALUE_NOSENSOR -9000 +#define VALUE_BROKEN -8000 + #define COMMS_WAKE 3600 #define BAUD 19200 @@ -37,16 +43,16 @@ #define DDR_LED DDRC #define PIN_LED PC4 -#define NUM_MEASUREMENTS 300 +#define NUM_MEASUREMENTS 100 +#define MAX_SENSORS 5 int uart_putchar(char c, FILE *stream); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); -static uint8_t n_measurements = 0; -// stored as 1/5 degree above 0 -static uint8_t measurements[NUM_MEASUREMENTS]; -static uint8_t internal_measurements[NUM_MEASUREMENTS]; +static uint16_t n_measurements = 0; +// stored as decidegrees +static int16_t measurements[MAX_SENSORS][NUM_MEASUREMENTS]; // boolean flags static uint8_t need_measurement = 0; @@ -59,6 +65,20 @@ static uint8_t measure_count = 0; static uint16_t comms_count = 0; +// 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)) +#define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst)) +#define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size)) +#define eeprom_write(src, eeprom_field) { eeprom_write_from(&src, eeprom_field, sizeof(src)); } + +#define EXPECT_MAGIC 0x67c9 + +struct __attribute__ ((__packed__)) __eeprom_data { + uint16_t magic; + uint8_t n_sensors; + uint8_t sensor_id[MAX_SENSORS][8]; +}; + #define DEBUG(str) printf_P(PSTR(str)) static void deep_sleep(); @@ -112,12 +132,19 @@ cmd_fetch() { uint16_t crc = 0; - int i; + uint16_t sens; + eeprom_read(sens, n_sensors); + printf_P(PSTR("%d measurements\n"), n_measurements); - for (i = 0; i < n_measurements; i++) + for (uint16_t i = 0; i < n_measurements; i++) { - printf_P(PSTR("%3d : %d\n"), i, measurements[i]); - crc = _crc_ccitt_update(crc, measurements[i]); + printf_P(PSTR("%3d :"), i); + for (uint8_t s = 0; s < sens; s++) + { + printf_P(PSTR(" %6d"), measurements[s][i]); + crc = _crc_ccitt_update(crc, measurements[s][i]); + } + putchar('\n'); } printf_P(PSTR("CRC : %d\n"), crc); } @@ -148,11 +175,147 @@ cmd_sensors() { uint8_t ret = simple_ds18b20_start_meas(NULL); - printf("All sensors, ret %d, waiting...\n", ret); + printf_P(("All sensors, ret %d, waiting...\n"), ret); _delay_ms(DS18B20_TCONV_12BIT); simple_ds18b20_read_all(); } +// 0 on success +static uint8_t +get_hex_string(const char *hex, uint8_t *out, uint8_t size) +{ + uint8_t upper; + uint8_t o; + for (uint8_t i = 0, z = 0; o < size; i++) + { + uint8_t h = hex[i]; + if (h >= 'A' && h <= 'F') + { + // lower case + h += 0x20; + } + uint8_t nibble; + if (h >= '0' && h <= '9') + { + nibble = h - '0'; + } + else if (h >= 'a' && h <= 'f') + { + nibble = 10 + h - 'a'; + } + else if (h == ' ' || h == ':') + { + continue; + } + else + { + printf_P(PSTR("Bad hex 0x%x '%c'\n"), hex[i], hex[i]); + return 1; + } + + if (z % 2 == 0) + { + upper = nibble << 4; + } + else + { + out[o] = upper | nibble; + o++; + } + + z++; + } + + if (o != size) + { + printf_P(PSTR("Short hex\n")); + return 1; + } + return 0; +} + +static void +add_sensor(uint8_t *id) +{ + uint8_t n; + eeprom_read(n, n_sensors); + if (n < MAX_SENSORS) + { + cli(); + eeprom_write_from(id, sensor_id[n], 8); + n++; + eeprom_write(n, n_sensors); + sei(); + printf_P(PSTR("Added sensor %d : "), n); + printhex(id, 8); + putchar('\n'); + } + else + { + printf_P(PSTR("Too many sensors\n")); + } +} + +static void +cmd_add_all() +{ + uint8_t id[OW_ROMCODE_SIZE]; + uint8_t sp[DS18X20_SP_SIZE]; + printf_P("Adding all\n"); + ow_reset(); + for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; ) + { + diff = ow_rom_search( diff, &id[0] ); + if( diff == OW_PRESENCE_ERR ) { + printf_P( PSTR("No Sensor found\r") ); + return; + } + + if( diff == OW_DATA_ERR ) { + printf_P( PSTR("Bus Error\r") ); + return; + } + add_sensor(id); + } +} + +static void +cmd_add_sensor(const char* hex_addr) +{ + uint8_t id[8]; + uint8_t ret = get_hex_string(hex_addr, id, 8); + if (ret) + { + return; + } + add_sensor(id); + +} + +static void +cmd_init() +{ + printf_P(PSTR("Resetting sensor list\n")); + uint8_t zero = 0; + cli(); + eeprom_write(zero, n_sensors); + sei(); + printf_P(PSTR("Done.\n")); +} + +static void +check_first_startup() +{ + uint16_t magic; + eeprom_read(magic, magic); + if (magic != EXPECT_MAGIC) + { + printf_P(PSTR("First boot, looking for sensors...\n")); + cmd_init(); + cmd_add_all(); + } +} + static void read_handler() { @@ -176,6 +339,18 @@ { cmd_sensors(); } + else if (strncmp_P(readbuf, PSTR("adds "), strlen("adds ")) == 0) + { + cmd_add_sensor(readbuf + strlen("adds ")); + } + else if (strcmp_P(readbuf, PSTR("addall"))== 0) + { + cmd_add_all(); + } + else if (strcmp_P(readbuf, PSTR("init")) == 0) + { + cmd_init(); + } else { printf_P(PSTR("Bad command\n")); @@ -275,7 +450,8 @@ // 10mV/degree // scale to 1/5 degree units above 0C int temp = (res_volts - 2.73) * 500; - measurements[n_measurements] = temp; + // XXX fixme + //measurements[n_measurements] = temp; // XXX something if it hits the limit // measure AVR internal temperature against 1.1 ref. @@ -289,7 +465,8 @@ // 1mV/degree int internal_temp = (internal_volts - 2.73) * 5000; - internal_measurements[n_measurements] = internal_temp; + // 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); @@ -301,9 +478,39 @@ static void do_measurement() { - printf("do_measurement\n"); - need_measurement = 0; + uint8_t n_sensors; + eeprom_read(n_sensors, n_sensors); + + uint8_t ret = simple_ds18b20_start_meas(NULL); + printf_P(("Read all sensors, ret %d, waiting...\n"), ret); + _delay_ms(DS18B20_TCONV_12BIT); + + if (n_measurements == NUM_MEASUREMENTS) + { + printf_P(PSTR("Measurements overflow\n")); + n_measurements = 0; + } + for (uint8_t n = 0; n < MAX_SENSORS; n++) + { + int16_t decicelsius; + if (n >= n_sensors) + { + decicelsius = VALUE_NOSENSOR; + } + else + { + uint8_t id[8]; + eeprom_read_to(id, sensor_id[n], 8); + + uint8_t ret = simple_ds18b20_read_decicelsius(id, &decicelsius); + if (ret != DS18X20_OK) + { + decicelsius = VALUE_BROKEN; + } + } + measurements[n_measurements][n] = decicelsius; + } //do_adc_335(); } @@ -348,6 +555,7 @@ PORT_LED |= _BV(PIN_LED); } +#if 0 static void long_delay(int ms) { @@ -358,6 +566,7 @@ _delay_ms(100); } } +#endif ISR(BADISR_vect) { @@ -375,11 +584,6 @@ sei(); } -static void -dump_ds18x20() -{ -} - int main(void) { set_2mhz(); @@ -391,6 +595,9 @@ uart_on(); fprintf_P(&mystdout, PSTR("hello %d\n"), 12); + + check_first_startup(); + uart_off(); // turn off everything except timer2 @@ -401,18 +608,16 @@ sei(); -#if 0 // set up counter2. // COM21 COM20 Set OC2 on Compare Match (p116) // WGM21 Clear counter on compare - TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); + TCCR2A = _BV(COM2A1) | _BV(COM2A0);// | _BV(WGM21); // CS22 CS21 CS20 clk/1024 TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); // set async mode ASSR |= _BV(AS2); // interrupt TIMSK2 = _BV(OCIE2A); -#endif for (;;) {
--- a/simple_ds18b20.c Sat May 19 21:47:09 2012 +0800 +++ b/simple_ds18b20.c Sat May 19 23:59:12 2012 +0800 @@ -163,7 +163,6 @@ simple_ds18b20_read_all() { uint8_t id[OW_ROMCODE_SIZE]; - uint8_t sp[DS18X20_SP_SIZE]; for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; ) { diff = ow_rom_search( diff, &id[0] );