comparison main.c @ 80:1e2068c5413a

- store settings in eeprom - change TICK to 6 secs (and fix timing bug) - measurement memory is used by all sensors - "awake" command - avoid float maths calculating vcc
author Matt Johnston <matt@ucc.asn.au>
date Tue, 10 Jul 2012 23:48:09 +0800
parents eb532c2a447d
children 4a2a82d6302c
comparison
equal deleted inserted replaced
79:eb532c2a447d 80:1e2068c5413a
21 // - measurement interval 21 // - measurement interval
22 // - transmit interval 22 // - transmit interval
23 // - bluetooth params 23 // - bluetooth params
24 // - number of sensors (and range?) 24 // - number of sensors (and range?)
25 25
26 // 1 second. we have 1024 prescaler, 32768 crystal. 26 // TICK should be 8 or less (8 untested). all timers need
27 #define SLEEP_COMPARE 32 27 // to be a multiple.
28 // limited to uint16_t 28
29 #define MEASURE_WAKE 140 29 #define TICK 6
30 // we have 1024 prescaler, 32768 crystal.
31 #define SLEEP_COMPARE (32*TICK-1)
30 32
31 #define VALUE_NOSENSOR 0x07D0 // 125 degrees 33 #define VALUE_NOSENSOR 0x07D0 // 125 degrees
32 #define VALUE_BROKEN 0x07D1 // 125.0625 34 #define VALUE_BROKEN 0x07D1 // 125.0625
33
34 // limited to uint16_t
35 #define COMMS_WAKE 3600 // XXX testing
36 // limited to uint8_t
37 #define WAKE_SECS 30 // XXX testing
38 35
39 #define BAUD 19200 36 #define BAUD 19200
40 #define UBRR ((F_CPU)/8/(BAUD)-1) 37 #define UBRR ((F_CPU)/8/(BAUD)-1)
41 38
42 #define PORT_LED PORTC 39 #define PORT_LED PORTC
45 42
46 #define PORT_SHDN PORTD 43 #define PORT_SHDN PORTD
47 #define DDR_SHDN DDRD 44 #define DDR_SHDN DDRD
48 #define PIN_SHDN PD7 45 #define PIN_SHDN PD7
49 46
50 // limited to uint16_t 47 // total amount of 16bit values available for measurements.
51 // XXX - increasing this to 300 causes strange failures, 48 // adjust emperically, be sure to allow enough stack space too
52 // not sure why 49 #define TOTAL_MEASUREMENTS 840
53 #define NUM_MEASUREMENTS 280 50
54 // limited to uint8_t 51 // each sensor slot uses 8 bytes
55 #define MAX_SENSORS 3 52 #define MAX_SENSORS 6
56 53
57 // fixed at 8, have a shorter name 54 // fixed at 8, have a shorter name
58 #define ID_LEN OW_ROMCODE_SIZE 55 #define ID_LEN OW_ROMCODE_SIZE
59 56
60 // #define HAVE_UART_ECHO 57 // #define HAVE_UART_ECHO
61 58
62 int uart_putchar(char c, FILE *stream); 59 // eeprom-settable parameters. all timeouts should
63 static void long_delay(int ms); 60 // be a multiple of TICK (6 seconds probably)
64 static void blink(); 61 static uint16_t measure_wake = 120;
65 static uint16_t adc_vcc(); 62 static uint16_t comms_wake = 3600;
66 63 static uint8_t wake_secs = 30;
67 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
68 _FDEV_SETUP_WRITE);
69
70 uint16_t crc_out;
71 static FILE _crc_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
72 _FDEV_SETUP_WRITE);
73 // convenience
74 static FILE *crc_stdout = &_crc_stdout;
75 64
76 // ---- Atomic guards required accessing these variables 65 // ---- Atomic guards required accessing these variables
77 static uint32_t clock_epoch; 66 static uint32_t clock_epoch;
78 static uint16_t comms_count; 67 static uint16_t comms_count;
79 static uint16_t measure_count; 68 static uint16_t measure_count;
80 // ---- End atomic guards required 69 // ---- End atomic guards required
81 70
82 static uint16_t n_measurements; 71 static uint16_t n_measurements;
83 72
84 // stored as 73 // calculated at startup as TOTAL_MEASUREMENTS/n_sensors
85 static uint16_t measurements[NUM_MEASUREMENTS][MAX_SENSORS]; 74 static uint16_t max_measurements;
75
76 static uint16_t measurements[TOTAL_MEASUREMENTS];
86 static uint32_t first_measurement_clock; 77 static uint32_t first_measurement_clock;
87 // last_measurement_clock is redundant but checks that we're not missing 78 // last_measurement_clock is redundant but checks that we're not missing
88 // samples 79 // samples
89 static uint32_t last_measurement_clock; 80 static uint32_t last_measurement_clock;
90 81
92 83
93 // boolean flags 84 // boolean flags
94 static uint8_t need_measurement; 85 static uint8_t need_measurement;
95 static uint8_t need_comms; 86 static uint8_t need_comms;
96 static uint8_t uart_enabled; 87 static uint8_t uart_enabled;
88 static uint8_t stay_awake;
97 89
98 // counts down from WAKE_SECS to 0, goes to deep sleep when hits 0 90 // counts down from WAKE_SECS to 0, goes to deep sleep when hits 0
99 static uint8_t comms_timeout; 91 static uint8_t comms_timeout;
100 92
101 static uint8_t readpos; 93 static uint8_t readpos;
102 static char readbuf[30]; 94 static char readbuf[30];
103 static uint8_t have_cmd; 95 static uint8_t have_cmd;
104 96
105 uint8_t n_sensors; 97 static uint8_t n_sensors;
106 uint8_t sensor_id[MAX_SENSORS][ID_LEN]; 98 static uint8_t sensor_id[MAX_SENSORS][ID_LEN];
99
100
101 int uart_putchar(char c, FILE *stream);
102 static void long_delay(int ms);
103 static void blink();
104 static uint16_t adc_vcc();
105
106 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
107 _FDEV_SETUP_WRITE);
108
109 static uint16_t crc_out;
110 static FILE _crc_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
111 _FDEV_SETUP_WRITE);
112 // convenience
113 static FILE *crc_stdout = &_crc_stdout;
114
107 115
108 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/ 116 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/
109 #define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size)) 117 #define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size))
110 #define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst)) 118 #define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst))
111 #define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size)) 119 #define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size))
114 #define EXPECT_MAGIC 0x67c9 122 #define EXPECT_MAGIC 0x67c9
115 123
116 struct __attribute__ ((__packed__)) __eeprom_data { 124 struct __attribute__ ((__packed__)) __eeprom_data {
117 // XXX eeprom unused at present 125 // XXX eeprom unused at present
118 uint16_t magic; 126 uint16_t magic;
127 uint16_t measure_wake;
128 uint16_t comms_wake;
129 uint8_t wake_secs;
119 }; 130 };
120
121 #define DEBUG(str) printf_P(PSTR(str))
122 131
123 static void deep_sleep(); 132 static void deep_sleep();
124 133
125 // Very first setup 134 // Very first setup
126 static void 135 static void
173 } 182 }
174 else 183 else
175 { 184 {
176 PORT_SHDN |= _BV(PIN_SHDN); 185 PORT_SHDN |= _BV(PIN_SHDN);
177 } 186 }
187 }
188
189 static void
190 set_measurement(uint8_t sensor, uint16_t measurement, uint16_t reading)
191 {
192 measurements[sensor*max_measurements + measurement] = reading;
193 }
194
195 static uint16_t
196 get_measurement(uint8_t sensor, uint16_t measurement)
197 {
198 return measurements[sensor*max_measurements + measurement];
178 } 199 }
179 200
180 static void 201 static void
181 setup_tick_counter() 202 setup_tick_counter()
182 { 203 {
275 "last_time=%lu\n" 296 "last_time=%lu\n"
276 "comms_time=%lu\n" 297 "comms_time=%lu\n"
277 "voltage=%hu\n" 298 "voltage=%hu\n"
278 ), 299 ),
279 epoch_copy, 300 epoch_copy,
280 (uint16_t)MEASURE_WAKE, 301 measure_wake,
281 first_measurement_clock, 302 first_measurement_clock,
282 last_measurement_clock, 303 last_measurement_clock,
283 last_comms_clock, 304 last_comms_clock,
284 millivolt_vcc 305 millivolt_vcc
285 ); 306 );
294 for (uint16_t n = 0; n < n_measurements; n++) 315 for (uint16_t n = 0; n < n_measurements; n++)
295 { 316 {
296 fprintf_P(crc_stdout, PSTR("meas%hu="), n); 317 fprintf_P(crc_stdout, PSTR("meas%hu="), n);
297 for (uint8_t s = 0; s < n_sensors; s++) 318 for (uint8_t s = 0; s < n_sensors; s++)
298 { 319 {
299 fprintf_P(crc_stdout, PSTR(" %04hx"), measurements[n][s]); 320 fprintf_P(crc_stdout, PSTR(" %04hx"), get_measurement(s, n));
300 } 321 }
301 fputc('\n', crc_stdout); 322 fputc('\n', crc_stdout);
302 } 323 }
303 fprintf_P(crc_stdout, PSTR("END\n")); 324 fprintf_P(crc_stdout, PSTR("END\n"));
304 fprintf_P(stdout, PSTR("CRC=%hu\n"), crc_out); 325 fprintf_P(stdout, PSTR("CRC=%hu\n"), crc_out);
316 { 337 {
317 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 338 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
318 { 339 {
319 comms_count = 0; 340 comms_count = 0;
320 } 341 }
321 printf_P(PSTR("off:%hu\n"), COMMS_WAKE); 342 printf_P(PSTR("off:%hu\n"), comms_wake);
322 _delay_ms(100); 343 _delay_ms(100);
323 comms_timeout = 0; 344 comms_timeout = 0;
324 } 345 }
325 346
326 static void 347 static void
347 printf_P(PSTR("All sensors, ret %d, waiting...\n"), ret); 368 printf_P(PSTR("All sensors, ret %d, waiting...\n"), ret);
348 long_delay(DS18B20_TCONV_12BIT); 369 long_delay(DS18B20_TCONV_12BIT);
349 simple_ds18b20_read_all(); 370 simple_ds18b20_read_all();
350 } 371 }
351 372
352 #if 0
353 // 0 on success
354 static uint8_t
355 get_hex_string(const char *hex, uint8_t *out, uint8_t size)
356 {
357 uint8_t upper;
358 uint8_t o;
359 for (uint8_t i = 0, z = 0; o < size; i++)
360 {
361 uint8_t h = hex[i];
362 if (h >= 'A' && h <= 'F')
363 {
364 // lower case
365 h += 0x20;
366 }
367 uint8_t nibble;
368 if (h >= '0' && h <= '9')
369 {
370 nibble = h - '0';
371 }
372 else if (h >= 'a' && h <= 'f')
373 {
374 nibble = 10 + h - 'a';
375 }
376 else if (h == ' ' || h == ':')
377 {
378 continue;
379 }
380 else
381 {
382 printf_P(PSTR("Bad hex 0x%x '%c'\n"), hex[i], hex[i]);
383 return 1;
384 }
385
386 if (z % 2 == 0)
387 {
388 upper = nibble << 4;
389 }
390 else
391 {
392 out[o] = upper | nibble;
393 o++;
394 }
395
396 z++;
397 }
398
399 if (o != size)
400 {
401 printf_P(PSTR("Short hex\n"));
402 return 1;
403 }
404 return 0;
405 }
406 #endif
407
408 static void 373 static void
409 init_sensors() 374 init_sensors()
410 { 375 {
411 uint8_t id[OW_ROMCODE_SIZE]; 376 uint8_t id[OW_ROMCODE_SIZE];
412 printf_P(PSTR("init sensors\n")); 377 printf_P(PSTR("init sensors\n"));
435 else 400 else
436 { 401 {
437 printf_P(PSTR("Too many sensors\n")); 402 printf_P(PSTR("Too many sensors\n"));
438 } 403 }
439 } 404 }
440 } 405
441 406 max_measurements = TOTAL_MEASUREMENTS / n_sensors;
442 static void 407 }
443 check_first_startup() 408
444 { 409 static void
445 #if 0 410 load_params()
411 {
446 uint16_t magic; 412 uint16_t magic;
447 eeprom_read(magic, magic); 413 eeprom_read(magic, magic);
448 if (magic != EXPECT_MAGIC) 414 if (magic == EXPECT_MAGIC)
449 { 415 {
450 printf_P(PSTR("First boot, looking for sensors...\n")); 416 eeprom_read(measure_wake, measure_wake);
451 // in case of power fumbles don't want to reset during eeprom write, 417 eeprom_read(comms_wake, comms_wake);
452 long_delay(2); 418 eeprom_read(wake_secs, wake_secs);
453 cmd_init(); 419 }
454 cmd_add_all(); 420 }
421
422 static void
423 cmd_get_params()
424 {
425 printf_P(PSTR("measure %hu comms %hu wake %u tick %d sensors %u (%u) meas %hu (%hu)\n"),
426 measure_wake, comms_wake, wake_secs, TICK,
427 n_sensors, MAX_SENSORS,
428 max_measurements, TOTAL_MEASUREMENTS);
429 }
430
431 static void
432 cmd_set_params(const char *params)
433 {
434 uint16_t new_measure_wake;
435 uint16_t new_comms_wake;
436 uint8_t new_wake_secs;
437 int ret = sscanf_P(params, PSTR("%hu %hu %u"),
438 &new_measure_wake, &new_comms_wake, &new_wake_secs);
439
440 if (ret != 3)
441 {
442 printf_P(PSTR("Bad values\n"));
443 }
444 else
445 {
455 cli(); 446 cli();
456 magic = EXPECT_MAGIC; 447 eeprom_write(new_measure_wake, measure_wake);
448 eeprom_write(new_comms_wake, comms_wake);
449 eeprom_write(new_wake_secs, wake_secs);
450 uint16_t magic = EXPECT_MAGIC;
457 eeprom_write(magic, magic); 451 eeprom_write(magic, magic);
458 sei(); 452 sei();
459 } 453 printf_P(PSTR("set_params for next boot\n"));
460 #endif 454 printf_P(PSTR("measure %hu comms %hu wake %u\n"),
455 new_measure_wake, new_comms_wake, new_wake_secs);
456 }
457 }
458
459 static void
460 cmd_awake()
461 {
462 stay_awake = 1;
463 printf_P(PSTR("awake\n"));
461 } 464 }
462 465
463 static void 466 static void
464 read_handler() 467 read_handler()
465 { 468 {
481 } 484 }
482 else if (strcmp_P(readbuf, PSTR("sensors")) == 0) 485 else if (strcmp_P(readbuf, PSTR("sensors")) == 0)
483 { 486 {
484 cmd_sensors(); 487 cmd_sensors();
485 } 488 }
489 else if (strcmp_P(readbuf, PSTR("get_params")) == 0)
490 {
491 cmd_get_params();
492 }
493 else if (strncmp_P(readbuf, PSTR("set_params "),
494 strlen("set_params ") == 0))
495 {
496 cmd_set_params(&readbuf[strlen("set_params ")]);
497 }
498 else if (strcmp_P(readbuf, PSTR("awake")) == 0)
499 {
500 cmd_awake();
501 }
486 else if (strcmp_P(readbuf, PSTR("reset")) == 0) 502 else if (strcmp_P(readbuf, PSTR("reset")) == 0)
487 { 503 {
488 cmd_reset(); 504 cmd_reset();
489 } 505 }
490 else 506 else
494 } 510 }
495 511
496 ISR(INT0_vect) 512 ISR(INT0_vect)
497 { 513 {
498 need_comms = 1; 514 need_comms = 1;
499 comms_timeout = WAKE_SECS; 515 comms_timeout = wake_secs;
500 blink(); 516 blink();
501 _delay_ms(100); 517 _delay_ms(100);
502 blink(); 518 blink();
503 } 519 }
504 520
530 } 546 }
531 547
532 ISR(TIMER2_COMPA_vect) 548 ISR(TIMER2_COMPA_vect)
533 { 549 {
534 TCNT2 = 0; 550 TCNT2 = 0;
535 measure_count ++; 551 measure_count += TICK;
536 comms_count ++; 552 comms_count += TICK;
537 553
538 clock_epoch ++; 554 clock_epoch += TICK;
539 555
540 if (comms_timeout != 0) 556 if (comms_timeout != 0)
541 { 557 {
542 comms_timeout--; 558 comms_timeout -= TICK;
543 } 559 }
544 560
545 if (measure_count >= MEASURE_WAKE) 561 if (measure_count >= measure_wake)
546 { 562 {
547 measure_count = 0; 563 measure_count = 0;
548 need_measurement = 1; 564 need_measurement = 1;
549 } 565 }
550 566
551 if (comms_count >= COMMS_WAKE) 567 if (comms_count >= comms_wake)
552 { 568 {
553 comms_count = 0; 569 comms_count = 0;
554 need_comms = 1; 570 need_comms = 1;
555 } 571 }
556 } 572 }
607 } 623 }
608 } 624 }
609 ADCSRA = 0; 625 ADCSRA = 0;
610 PRR |= _BV(PRADC); 626 PRR |= _BV(PRADC);
611 627
612 float res_volts = 1.1 * 1024 * num / sum; 628 //float res_volts = 1.1 * 1024 * num / sum;
613 629 //return 1000 * res_volts;
614 return 1000 * res_volts; 630 return ((uint32_t)1100*1024*num) / sum;
615 } 631 }
616 632
617 static void 633 static void
618 do_measurement() 634 do_measurement()
619 { 635 {
622 simple_ds18b20_start_meas(NULL); 638 simple_ds18b20_start_meas(NULL);
623 // sleep rather than using a long delay 639 // sleep rather than using a long delay
624 deep_sleep(); 640 deep_sleep();
625 //_delay_ms(DS18B20_TCONV_12BIT); 641 //_delay_ms(DS18B20_TCONV_12BIT);
626 642
627 if (n_measurements == NUM_MEASUREMENTS) 643 if (n_measurements == max_measurements)
628 { 644 {
629 n_measurements = 0; 645 n_measurements = 0;
630 } 646 }
631 647
632 for (uint8_t s = 0; s < MAX_SENSORS; s++) 648 for (uint8_t s = 0; s < n_sensors; s++)
633 { 649 {
634 uint16_t reading; 650 uint16_t reading;
635 if (s >= n_sensors) 651 uint8_t ret = simple_ds18b20_read_raw(sensor_id[s], &reading);
636 { 652 if (ret != DS18X20_OK)
637 reading = VALUE_NOSENSOR; 653 {
638 } 654 reading = VALUE_BROKEN;
639 else 655 }
640 { 656 set_measurement(s, n_measurements, reading);
641 uint8_t ret = simple_ds18b20_read_raw(sensor_id[s], &reading);
642 if (ret != DS18X20_OK)
643 {
644 reading = VALUE_BROKEN;
645 }
646 }
647 measurements[n_measurements][s] = reading;
648 } 657 }
649 658
650 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 659 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
651 { 660 {
652 if (n_measurements == 0) 661 if (n_measurements == 0)
671 set_aux_power(1); 680 set_aux_power(1);
672 uart_on(); 681 uart_on();
673 682
674 // write sd card here? same 3.3v regulator... 683 // write sd card here? same 3.3v regulator...
675 684
676 for (comms_timeout = WAKE_SECS; comms_timeout > 0; ) 685 for (comms_timeout = wake_secs;
686 comms_timeout > 0 || stay_awake;
687 )
677 { 688 {
678 if (need_measurement) 689 if (need_measurement)
679 { 690 {
680 need_measurement = 0; 691 need_measurement = 0;
681 do_measurement(); 692 do_measurement();
734 stdout = &mystdout; 745 stdout = &mystdout;
735 uart_on(); 746 uart_on();
736 747
737 printf(PSTR("Started.\n")); 748 printf(PSTR("Started.\n"));
738 749
739 check_first_startup(); 750 load_params();
740 751
741 init_sensors(); 752 init_sensors();
742 753
743 uart_off(); 754 uart_off();
744 755