233 lines
5.7 KiB
C
233 lines
5.7 KiB
C
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/pgmspace.h>
|
|
#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<OVERVOLTAGE_TIMEOUT1) overvoltage_counter1++;
|
|
} else {
|
|
overvoltage_counter1 = 0;
|
|
if(overvoltage_off_counter1<OVERVOLTAGEOFF_TIMEOUT1) overvoltage_off_counter1++;
|
|
}
|
|
|
|
if(voltage > OVERVOLTAGE2) {
|
|
overvoltage_off_counter2 = 0;
|
|
if(overvoltage_counter2<OVERVOLTAGE_TIMEOUT2) overvoltage_counter2++;
|
|
} else {
|
|
overvoltage_counter2 = 0;
|
|
if(overvoltage_off_counter2<OVERVOLTAGEOFF_TIMEOUT2) overvoltage_off_counter2++;
|
|
}
|
|
|
|
if(voltage < UNDERVOLTAGE) {
|
|
undervoltage_off_counter = 0;
|
|
if(undervoltage_counter<UNDERVOLTAGE_TIMEOUT) undervoltage_counter++;
|
|
} else {
|
|
undervoltage_counter = 0;
|
|
if(undervoltage_off_counter<UNDERVOLTAGEOFF_TIMEOUT) undervoltage_off_counter++;
|
|
}
|
|
|
|
|
|
if(overvoltage_counter1 >= OVERVOLTAGE_TIMEOUT1) {
|
|
overvoltage_off_counter1 = 0;
|
|
DUMP_ON;
|
|
}
|
|
|
|
if(overvoltage_off_counter1 >= OVERVOLTAGEOFF_TIMEOUT1) {
|
|
overvoltage_counter1 = 0;
|
|
DUMP_OFF;
|
|
}
|
|
|
|
if(overvoltage_counter2 >= OVERVOLTAGE_TIMEOUT2) {
|
|
overvoltage_off_counter2 = 0;
|
|
GEN_OFF;
|
|
}
|
|
|
|
if(overvoltage_off_counter2 >= OVERVOLTAGEOFF_TIMEOUT2) {
|
|
overvoltage_counter2 = 0;
|
|
GEN_ON;
|
|
}
|
|
|
|
if(undervoltage_counter >= UNDERVOLTAGE_TIMEOUT) {
|
|
undervoltage_off_counter = 0;
|
|
overvoltage_off_counter1 = OVERVOLTAGEOFF_TIMEOUT1;
|
|
LOAD_OFF;
|
|
DUMP_OFF;
|
|
}
|
|
|
|
if(undervoltage_off_counter >= UNDERVOLTAGEOFF_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;
|
|
}
|
|
|
|
|