changeset 363:99e7c2958a06

merge
author Matt Johnston <matt@ucc.asn.au>
date Sun, 24 Jun 2012 23:48:25 +0800
parents cfcd200c69da (diff) 8fea6144951b (current diff)
children 8645fdcacad1
files
diffstat 2 files changed, 272 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/main.c	Sun Jun 24 23:48:11 2012 +0800
+++ b/main.c	Sun Jun 24 23:48:25 2012 +0800
@@ -7,6 +7,7 @@
 #include <util/delay.h>
 #include <avr/pgmspace.h>
 #include <avr/eeprom.h>
+#include <avr/wdt.h>
 #include <util/crc16.h>
 
 // for DWORD of get_fattime()
@@ -46,6 +47,8 @@
 #define PIN_SHDN PD7
 
 // limited to uint16_t
+// XXX - increasing this to 300 causes strange failures, 
+// not sure why
 #define NUM_MEASUREMENTS 280
 // limited to uint8_t
 #define MAX_SENSORS 3
@@ -58,6 +61,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 FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
         _FDEV_SETUP_WRITE);
@@ -115,8 +119,15 @@
 static void
 setup_chip()
 {
+    cli();
+
+    // stop watchdog timer (might have been used to cause a reset)
+    wdt_reset();
+    MCUSR &= ~_BV(WDRF);
+    WDTCSR |= _BV(WDCE) | _BV(WDE);
+    WDTCSR = 0;
+
     // Set clock to 2mhz
-    cli();
     CLKPR = _BV(CLKPCE);
     // divide by 4
     CLKPR = _BV(CLKPS1);
@@ -245,15 +256,24 @@
     uint8_t n_sensors;
     eeprom_read(n_sensors, n_sensors);
 
+    uint16_t millivolt_vcc, int_temp;
+
+    adc_internal(&millivolt_vcc, &int_temp);
+
     fprintf_P(crc_stdout, PSTR("START\n"));
     fprintf_P(crc_stdout, PSTR("now=%lu\n"
                                 "time_step=%hu\n"
                                 "first_time=%lu\n"
-                                "last_time=%lu\n"), 
+                                "last_time=%lu\n"
+                                "voltage=%hu\n"
+                                "avrtemp=%hu\n"), 
                                 clock_epoch, 
                                 (uint16_t)MEASURE_WAKE, 
                                 first_measurement_clock, 
-                                last_measurement_clock);
+                                last_measurement_clock,
+                                millivolt_vcc,
+                                int_temp
+                                );
     fprintf_P(crc_stdout, PSTR("sensors=%u\n"), n_sensors);
     for (uint8_t s = 0; s < n_sensors; s++)
     {
@@ -294,6 +314,23 @@
 }
 
 static void
+cmd_awake()
+{
+    comms_timeout = WAKE_SECS;
+    printf_P(PSTR("awake %hu\n"), WAKE_SECS);
+}
+
+static void
+cmd_reset()
+{
+    printf_P(PSTR("reset\n"));
+    _delay_ms(100);
+    cli(); // disable interrupts 
+    wdt_enable(WDTO_15MS); // enable watchdog 
+    while(1); // wait for watchdog to reset processor 
+}
+
+static void
 cmd_measure()
 {
     printf_P(PSTR("measuring\n"));
@@ -466,10 +503,18 @@
     {
         cmd_add_all();
     }
+    else if (strcmp_P(readbuf, PSTR("awake"))== 0)
+    {
+        cmd_awake();
+    }
     else if (strcmp_P(readbuf, PSTR("init")) == 0)
     {
         cmd_init();
     }
+    else if (strcmp_P(readbuf, PSTR("reset")) == 0)
+    {
+        cmd_reset();
+    }
     else
     {
         printf_P(PSTR("Bad command\n"));
@@ -479,6 +524,7 @@
 ISR(INT0_vect)
 {
     need_comms = 1;
+    comms_timeout = WAKE_SECS;
     blink();
     _delay_ms(100);
     blink();
@@ -561,6 +607,42 @@
     sleep_mode();
 }
 
+static void
+adc_internal(uint16_t *millivolt_vcc, uint16_t *int_temp)
+{
+    PRR &= ~_BV(PRADC);
+    
+    // left adjust
+    ADMUX = _BV(ADLAR);
+
+    // ADPS2 = /16 prescaler, 62khz at 1mhz clock
+    ADCSRA = _BV(ADEN) | _BV(ADPS2);
+
+    // 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 * 1024 / f_11;
+    *millivolt_vcc = 1000 * res_volts;
+
+    // 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 internal_volts = res_internal * (1.1 / 1024.0);
+    // decidegrees
+    *int_temp = (internal_volts - 2.73) * 1000;
+
+    PRR |= _BV(PRADC);
+    ADCSRA = 0;
+}
+
 #if 0
 // untested
 static void 
@@ -623,17 +705,13 @@
 do_measurement()
 {
     uint8_t n_sensors;
-    printf("do_measurement\n");
     eeprom_read(n_sensors, n_sensors);
-    printf("do_measurement sensors %d\n", n_sensors);
 
-    uint8_t ret = simple_ds18b20_start_meas(NULL);
-    printf_P(PSTR("Read all sensors, ret %d, waiting...\n"), ret);
+    simple_ds18b20_start_meas(NULL);
     _delay_ms(DS18B20_TCONV_12BIT);
 
     if (n_measurements == NUM_MEASUREMENTS)
     {
-        printf_P(PSTR("Measurements overflow\n"));
         n_measurements = 0;
     }
 
@@ -728,7 +806,6 @@
     printf_P(PSTR("Bad interrupt\n"));
 }
 
-
 int main(void)
 {
     setup_chip();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/dump.py	Sun Jun 24 23:48:25 2012 +0800
@@ -0,0 +1,186 @@
+#!/usr/bin/env python2.7
+
+BTADDR = "00:12:03:27:70:88"
+SLEEP_TIME = 5
+# time that the bluetooth takes to get going?
+EXTRA_WAKEUP = 0
+
+FETCH_TRIES = 3
+
+# avoid turning off the bluetooth etc.
+TESTING = False
+
+import sys
+# for wrt
+sys.path.append('/root/python')
+import httplib
+import time
+import traceback
+import binascii
+import hmac
+import zlib
+import urllib
+import urllib2
+
+import config
+
+from utils import monotonic_time, retry, readline, crc16
+
+lightblue = None
+try:
+    import lightblue
+except ImportError:
+    import bluetooth
+
+def get_socket(addr):
+    if lightblue:
+        s = lightblue.socket()
+        s.connect((addr, 1))
+        s.settimeout(3)
+    else:
+        s = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
+        s.connect((addr, 1))
+
+    s.setblocking(False)
+
+    return s
+
+
+@retry()
+def fetch(sock):
+    print "fetch"
+    sock.send("fetch\n")
+
+    crc = 0
+
+    lines = []
+    l = readline(sock)
+    if l != 'START\n':
+        print>>sys.stderr, "Bad expected START line '%s'\n" % l.rstrip('\n')
+        return None
+    crc = crc16(l, crc)
+
+    while True:
+        l = readline(sock)
+
+        crc = crc16(l, crc)
+
+        if l == 'END\n':
+            break
+
+        lines.append(l.rstrip('\n'))
+
+    print lines
+
+    l = readline(sock)
+    recv_crc = None
+    try:
+        k, v = l.rstrip('\n').split('=')
+        print k,v
+        if k == 'CRC':
+            recv_crc = int(v)
+        if recv_crc < 0 or recv_crc > 0xffff:
+            recv_crc = None
+    except ValueError:
+        pass
+
+    if recv_crc is None:
+        print>>sys.stderr, "Bad expected CRC line '%s'\n" % l.rstrip('\n')
+        return None
+
+    if recv_crc != crc:
+        print>>sys.stderr, "Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc)
+        return None
+
+    return lines
+
+@retry()
+def turn_off(sock):
+    if TESTING:
+        return 99
+    print>>sys.stderr, "sending btoff"
+    sock.send("btoff\n");
+    # read newline
+    l = readline(sock)
+    if not l:
+        print>>sys.stderr, "Bad response to btoff\n"
+        return None
+
+    if not l.startswith('off:'):
+        print>>sys.stderr, "Bad response to btoff '%s'\n" % l
+        return None
+    off, next_wake = l.rstrip().split(':')
+    print>>sys.stderr, "Next wake %s" % next_wake
+
+    return int(next_wake)
+
+@retry()
+def clear_meas(sock):
+    sock.send("clear\n");
+    l = readline(sock)
+    if l and l.rstrip() == 'cleared':
+        return True
+
+    print>>sys.stderr, "Bad response to clear %s\n" % str(l)
+    return False
+
+def send_results(lines):
+    enc_lines = binascii.b2a_base64(zlib.compress('\n'.join(lines)))
+    mac = hmac.new(config.HMAC_KEY, enc_lines).hexdigest()
+
+    url_data = urllib.urlencode( {'lines': enc_lines, 'hmac': mac} )
+    con = urllib2.urlopen(config.UPDATE_URL, url_data)
+    result = con.read(100)
+    if result == 'OK':
+        return True
+    else:
+        print>>sys.stderr, "Bad result '%s'" % result
+        return False
+
+def do_comms(sock):
+    args = sys.argv[1:]
+    print "do_comms"
+    for a in args:
+        sock.send('%s\n', a)
+
+    while True:
+        l = readline(sock)
+        print l
+
+testcount = 0
+
+def sleep_for(secs):
+    until = monotonic_time() + secs
+    while True:
+        length = until - monotonic_time()
+        if length <= 0:
+            return
+        time.sleep(length)
+
+def main():
+    next_wake_time = 0
+
+    while True:
+        sock = None
+        try:
+            sock = get_socket(BTADDR)
+        except Exception, e:
+            print>>sys.stderr, "Error connecting:"
+            traceback.print_exc(file=sys.stderr)
+        sleep_time = SLEEP_TIME
+        if sock:
+            next_wake = None
+            try:
+                next_wake_interval = do_comms(sock)
+                next_wake_time = time.time() + next_wake_interval
+            except Exception, e:
+                print>>sys.stderr, "Error in do_comms:"
+                traceback.print_exc(file=sys.stderr)
+            if next_wake_time > time.time():
+                sleep_time = min(next_wake_time - time.time() - EXTRA_WAKEUP, sleep_time)
+
+        print "Sleeping for %d" % sleep_time
+        sleep_for(sleep_time)
+
+if __name__ == '__main__':
+    main()