#include #include #include #include "utils.h" #include "main.h" #include "adc.h" #include "uart.h" volatile uint16_t syscounter = 0; uint16_t voltage = 0; uint16_t current_in = 0; uint16_t current_out = 0; uint8_t overvoltage_counter1 = 0; uint8_t overvoltage_off_counter1 = 0; uint8_t overvoltage_counter2 = 0; uint8_t overvoltage_off_counter2 = 0; uint8_t undervoltage_counter = 0; uint8_t undervoltage_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) | _BV(DUMPSW); PORT_SW &= ~(_BV(LOADSW) | _BV(GENSW) | _BV(DUMPSW)); } void measure(void) { static int16_t temp; voltage = adc_read_avg(AD_V, 4); voltage *= 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; temp = adc_read_avg(AD_I_LOAD, 4); temp -= CURRENT_OFFSET; if(temp < 0) temp = 0; current_out = 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("Voltage: "); uart_print_uint16(voltage); uart_puts_P("mV\r\n"); uart_puts_P("Load: "); uart_print_uint16(current_out); uart_puts_P("mA "); uart_print_uint16( get_power(voltage, current_out)); uart_puts_P("W\r\n"); uart_puts_P("Generator: "); uart_print_uint16(current_in); uart_puts_P("mA "); uart_print_uint16(get_power(voltage, current_in)); uart_puts_P("W\r\n"); uart_puts_P("switches (load, dump, gen): "); uart_putc(48 + (IS_LOAD_ON >> LOADSW)); uart_putc(','); uart_putc(48 + (IS_DUMP_ON >> DUMPSW)); uart_putc(','); uart_putc(48 + (IS_GEN_ON >> GENSW)); uart_puts_P("\r\n"); } void handle_over_and_undervoltage(void) { if(voltage > OVERVOLTAGE1) { overvoltage_off_counter1 = 0; if(overvoltage_counter1 OVERVOLTAGE2) { overvoltage_off_counter2 = 0; if(overvoltage_counter2= OVERVOLTAGE_TIMEOUT1) { overvoltage_off_counter1 = 0; DUMP_ON; } if(overvoltage_off_counter1 >= OVERVOLTAGE_TIMEOUT1) { overvoltage_counter1 = 0; DUMP_OFF; } if(overvoltage_counter2 >= OVERVOLTAGE_TIMEOUT2) { overvoltage_off_counter2 = 0; GEN_OFF; } if(overvoltage_off_counter2 >= OVERVOLTAGE_TIMEOUT2) { overvoltage_counter2 = 0; GEN_ON; } if(undervoltage_counter >= UNDERVOLTAGE_TIMEOUT) { undervoltage_off_counter = 0; LOAD_OFF; } if(undervoltage_off_counter >= UNDERVOLTAGE_TIMEOUT) { undervoltage_counter = 0; LOAD_ON; } #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("ov2="); uart_print_uint8(overvoltage_counter2); uart_puts_P(" ovo2="); uart_print_uint8 (overvoltage_off_counter2); 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); uart_putc(','); uart_print_uint16(current_in); uart_putc(','); uart_print_uint16(current_out); uart_putc(','); uart_print_uint16(get_power(voltage, current_in)); uart_putc(','); uart_print_uint16(get_power(voltage, current_out)); uart_putc(','); uart_putc(48 + (IS_LOAD_ON >> LOADSW)); uart_putc(','); uart_putc(48 + (IS_DUMP_ON >> DUMPSW)); 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; DUMP_OFF; 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; }