#include #include #include #include "utils.h" #include "main.h" #include "adc.h" #include "uart.h" volatile uint16_t syscounter = 0; uint16_t voltage_bat = 0; uint16_t voltage_gen = 0; uint16_t current_in = 0; uint8_t overvoltage_counter = 0; uint8_t overvoltage_off_counter = 0; uint8_t undervoltage_counter = 0; uint8_t undervoltage_off_counter = 0; uint8_t generator_counter = 0; uint8_t generator_off_counter = 0; static void timer_init(void) { // clock is 8MHz TCCR1B |= _BV(WGM12) | _BV(CS11) | _BV(CS10) ; // CTC Mode for Timer 1 (16Bit) with prescale of 64 OCR1A = 1250; // 100Hz TIMSK = _BV(OCIE1A); sei(); // enable interrupts } static void ports_init(void) { DDR_SW |= _BV(LOADSW) | _BV(GENSW); PORT_SW &= ~(_BV(LOADSW) | _BV(GENSW)); } void measure(void) { static int16_t temp; voltage_bat = adc_read_avg(AD_V_BAT, 4); voltage_bat *= VOLTAGE_PER_TICK; voltage_bat += 790; voltage_gen = adc_read_avg(AD_V_GEN, 4); voltage_gen *= VOLTAGE_PER_TICK; temp = adc_read_avg(AD_I_GEN, 4); temp -= CURRENT_OFFSET; if(temp < 0) temp = 0; current_in = temp * CURRENT_PER_TICK; } uint16_t get_power(uint16_t voltage, int16_t currents) { return (voltage/100 * (currents/100)) / 100 ; } void pretty_print_all_values(void) { uart_puts_P("Battery Voltage: "); uart_print_uint16(voltage_bat); uart_puts_P("mV\r\n"); uart_puts_P("Generator Voltage: "); uart_print_uint16(voltage_gen); uart_puts_P("mV\r\n"); uart_puts_P("Generator: "); uart_print_uint16(current_in); uart_puts_P("mA "); uart_print_uint16(get_power(voltage_bat, current_in)); uart_puts_P("W\r\n"); uart_puts_P("switches (load, gen): "); uart_putc(48 + (IS_LOAD_ON >> LOADSW)); uart_putc(','); uart_putc(48 + (IS_GEN_ON >> GENSW)); uart_puts_P("\r\n"); } void handle_over_and_undervoltage(void) { if(voltage_bat < UNDERVOLTAGE) { undervoltage_off_counter = 0; if(undervoltage_counter GENERATOR) { generator_off_counter = 0; if(generator_counter= UNDERVOLTAGE_TIMEOUT) { // spannung zu niedrig => abschalten undervoltage_off_counter = 0; LOAD_OFF; } else { // spannung ist okay // ist die spannung schon lange genug okay? if(undervoltage_off_counter >= UNDERVOLTAGEOFF_TIMEOUT) { undervoltage_counter = 0; // ja, also schauen ob der generator schon lange genug läuft if(generator_counter >= GENERATOR_TIMEOUT) { // ja, also einschalten LOAD_ON; } else { // nein, generator nicht lange genug an // ist er vielleicht schon lange aus? if(generator_off_counter >= GENERATOR_OFF_TIMEOUT) { // ja, also abschalten, egal ob akku okay LOAD_OFF; } } } } #ifdef DEBUG uart_puts_P("ov1="); uart_print_uint8(overvoltage_counter1); uart_puts_P(" ovo1="); uart_print_uint8 (overvoltage_off_counter1); uart_puts_P("\r\n"); uart_puts_P("uv ="); uart_print_uint8(undervoltage_counter); uart_puts_P(" uvo ="); uart_print_uint8(undervoltage_off_counter); uart_puts_P("\r\n"); #endif } static void work_uart(void) { uint16_t uart_char = uart_getc(); if(uart_char != UART_NO_DATA) { switch(uart_char & 0xff) { case 'p': pretty_print_all_values(); break; case 'a': uart_putc('A'); uart_print_uint16(voltage_bat); uart_putc(','); uart_print_uint16(current_in); uart_putc(','); uart_print_uint16(0); uart_putc(','); uart_print_uint16(get_power(voltage_bat, current_in)); uart_putc(','); uart_print_uint16(0); uart_putc(','); uart_putc(48 + (IS_LOAD_ON >> LOADSW)); uart_putc(','); uart_putc(48); uart_putc(','); uart_putc(48 + (IS_GEN_ON >> GENSW)); uart_putc('B'); break; } } } int main(void) { ports_init(); adc_init(); timer_init(); uart_init(UART_BAUD_SELECT(19200,F_CPU)); LOAD_OFF; GEN_ON; while(1) { if(syscounter >= 100) { syscounter = 0; measure(); //pretty_print_all_values(); handle_over_and_undervoltage(); } work_uart(); } return(0); } // system timer SIGNAL(TIMER1_COMPA_vect) { syscounter++; syscounter %= 60000; }