Mercurial > templog
changeset 312:ef64a178092f
- Some basic ADC code
- Turn on -mcall-prologues
- Put strings in program space, saves RAM
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 14 May 2012 00:22:57 +0800 |
parents | fc96a51bdce6 |
children | 139ecb1840fd |
files | Makefile main.c |
diffstat | 2 files changed, 110 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Fri May 11 22:12:11 2012 +0800 +++ b/Makefile Mon May 14 00:22:57 2012 +0800 @@ -17,10 +17,11 @@ # default_serial = "avrdoper" # FUSES ........ Parameters for avrdude to flash the fuses appropriately. -DEVICE = atmega328 +DEVICE = atmega168 CLOCK = 1000000 PROGRAMMER = #-c stk500v2 -P avrdoper OBJECTS = main.o ff.o mmc.o onewire.o +LIBS = -lm FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m # ATMega8 fuse bits used above (fuse bits for other devices are different!): @@ -49,7 +50,7 @@ # Tune the lines below only if you know what you are doing: AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) -COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 +COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 -mcall-prologues # symbolic targets: all: main.hex @@ -85,7 +86,7 @@ # file targets: main.elf: $(OBJECTS) - $(COMPILE) -o main.elf $(OBJECTS) + $(COMPILE) -o main.elf $(OBJECTS) $(LIBS) main.hex: main.elf rm -f main.hex
--- a/main.c Fri May 11 22:12:11 2012 +0800 +++ b/main.c Mon May 14 00:22:57 2012 +0800 @@ -9,6 +9,7 @@ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> +#include <avr/pgmspace.h> #include <util/crc16.h> #include "integer.h" @@ -28,12 +29,16 @@ #define BAUD 9600 #define UBRR ((F_CPU)/16/(BAUD)-1) +#define NUM_MEASUREMENTS 300 + static int uart_putchar(char c, FILE *stream); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); static uint8_t n_measurements; -static uint8_t measurements[500]; +// stored as 1/5 degree above 0 +static uint8_t measurements[NUM_MEASUREMENTS]; +static uint8_t internal_measurements[NUM_MEASUREMENTS]; // boolean flags static uint8_t need_measurement; @@ -49,14 +54,27 @@ static void deep_sleep(); static void -uart_init(unsigned int ubrr) +uart_on(unsigned int ubrr) { // baud rate UBRR0H = (unsigned char)(ubrr >> 8); UBRR0L = (unsigned char)ubrr; - UCSR0B = (1<<RXEN0)|(1<<TXEN0); + UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); //8N1 - UCSR0C = (1<<UMSEL00)|(3<<UCSZ00); + UCSR0C = _BV(UMSEL00) | _BV(UCSZ00); + + // Power reduction register + PRR &= ~_BV(PRUSART0); +} + +static void +uart_off() +{ + // Turn of interrupts and disable tx/rx + UCSR0B = 0; + + // Power reduction register + PRR |= _BV(PRUSART0); } static int @@ -73,13 +91,13 @@ { uint16_t crc = 0; int i; - printf("%d measurements\n", n_measurements); + printf_P(PSTR("%d measurements\n"), n_measurements); for (i = 0; i < n_measurements; i++) { - printf("%3d : %d\n", i, measurements[i]); + printf_P(PSTR("%3d : %d\n"), i, measurements[i]); crc = _crc_ccitt_update(crc, measurements[i]); } - printf("CRC : %d\n", crc); + printf_P(PSTR("CRC : %d\n"), crc); } static void @@ -96,21 +114,21 @@ static void read_handler() { - if (strcmp(readbuf, "fetch") == 0) + if (strcmp_P(readbuf, PSTR("fetch")) == 0) { cmd_fetch(); } - else if (strcmp(readbuf, "clear") == 0) + else if (strcmp_P(readbuf, PSTR("clear")) == 0) { cmd_clear(); } - else if (strcmp(readbuf, "btoff") == 0) + else if (strcmp_P(readbuf, PSTR("btoff")) == 0) { cmd_btoff(); } else { - printf("Bad command\n"); + printf_P(PSTR("Bad command\n")); } } @@ -174,10 +192,65 @@ sleep_mode(); } +static void +do_adc_335() +{ + PRR &= ~_BV(PRADC); + + ADMUX = _BV(ADLAR); + + // 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; + + // 10mV/degree + // scale to 1/5 degree units above 0C + int temp = (res_volts - 2.73) * 500; + 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 internal_volts = res_internal * (1.1 / 1024.0); + + // 1mV/degree + int internal_temp = (internal_volts - 2.73) * 5000; + 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); +} + static void do_measurement() { need_measurement = 0; + + do_adc_335(); } static void @@ -186,7 +259,7 @@ need_comms = 0; // turn on bluetooth - // turn on serial (interrupts) + uart_on(UBRR); // write sd card here? same 3.3v regulator... @@ -197,18 +270,29 @@ { break; } + + if (need_measurement) + { + do_measurement(); + } + idle_sleep(); } + uart_off(); + // turn off bluetooth - // turn off serial (interrupts) } int main(void) { - uart_init(UBRR); + stdout = &mystdout; + uart_on(UBRR); + fprintf_P(&mystdout, PSTR("hello %d\n"), 12); + uart_off(); - fprintf(&mystdout, "hello %d\n", 12); + // turn off everything except timer2 + PRR = _BV(PRTWI) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC); // set up counter2. // COM21 COM20 Set OC2 on Compare Match (p116) @@ -219,6 +303,12 @@ // set async mode ASSR |= _BV(AS2); +#ifdef TEST_MODE + for (;;) + { + do_comms() + } +#else for(;;){ /* insert your main loop code here */ if (need_measurement) @@ -235,5 +325,6 @@ deep_sleep(); } +#endif return 0; /* never reached */ }