123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- #include <avr/io.h>
- #include <util/delay.h>
- #include <avr/pgmspace.h>
- #include <avr/eeprom.h>
- #include "main.h"
- #include "1wire.h"
- #include "gtext.h"
- #include "sed1335.h"
- #include "ds18b20.h"
- #include "dac8571.h"
- #include "ads1224.h"
- #include "display.h"
- volatile struct timers timers;
- volatile unsigned char tick; // incremented every 100ms
- unsigned char getkey(void){
- static unsigned char old;
- unsigned char key;
- static unsigned char counter;
- DDRA = 0;
- PORTA = 0xff;
- DDRC |= _BV(PC7);
- _delay_ms(2);
- key = ~PINA;
- DDRC &= ~_BV(PC7);
- PORTA = 0;
- DDRA = 0xff;
- if(key == 0)
- counter = 0;
- if(key == old){
- switch(counter){
- default:
- counter++;
- return 0;
- case 5:
- counter++;
- break;
- case 8:
- break;
- }
- } else {
- counter = 0;
- }
- old = key;
- return key;
- }
- struct settings {
- float coeff_generator_volt_A;
- float coeff_generator_volt_B;
- float coeff_generator_curr_A;
- float coeff_generator_curr_B;
- float coeff_disch_curr_A;
- float coeff_disch_curr_B;
- float coeff_volt_A;
- float coeff_volt_B;
- float coeff_curr_A;
- float coeff_curr_B;
- };
- struct settings settings;
- EEMEM struct settings eep_settings = {
- .coeff_generator_volt_A = 1597.035901,
- .coeff_generator_volt_B = 1317.235211,
- .coeff_generator_curr_A = 65535.0/20,
- .coeff_generator_curr_B = 1310,
- .coeff_disch_curr_A = 2996.00532623169,
- .coeff_disch_curr_B = 4298.2689747004,
- .coeff_volt_A = 1.55337778893448E-07,
- .coeff_volt_B = -0.092784032021951,
- .coeff_curr_A = -9.03353481586364E-08,
- .coeff_curr_B = 0.124868806047484,
- // .coeff_curr_A = .001,
- // .coeff_curr_B = 0,
- };
- unsigned int vdac = 0;
- unsigned int cdac = 0;
- void dac_update(void){
- dac8571_set(cdac, CURR_DAC);
- dac8571_set(vdac, VOLT_DAC);
- }
- void set_voltage(float u){
- vdac = u * settings.coeff_generator_volt_A + settings.coeff_generator_volt_B;
- dac_update();
- }
- void set_charge_curr(float i){
- cdac = i * settings.coeff_generator_curr_A + settings.coeff_generator_curr_B;
- dac_update();
- }
- void set_discharge_curr(float i){
- cdac = i * settings.coeff_disch_curr_A + settings.coeff_disch_curr_B;
- dac_update();
- }
- #define CONV_ENABLE _BV(PD5)
- #define DISCH_ENABLE _BV(PD1)
- #define REL_K1 _BV(PD6)
- #define REL_K2 _BV(PD7)
- #define K1_ON() {PORTD |= REL_K1;}
- #define K1_OFF() {PORTD &= ~REL_K1;}
- #define K2_ON() {PORTD |= REL_K2;}
- #define K2_OFF() {PORTD &= ~REL_K2;}
- #define POWER_OFF() {PORTD &= ~(CONV_ENABLE | DISCH_ENABLE);}
- #define CONV_ON() {PORTD |= CONV_ENABLE;}
- #define DISCH_ON() {PORTD |= DISCH_ENABLE;}
- void output_off(void){
- cdac = 0;
- vdac = 0;
- POWER_OFF();
- dac_update();
- K1_OFF();
- K2_OFF();
- }
- void charge_on(void){
- output_off();
- K1_ON();
- CONV_ON();
- }
- void discharge_on(void){
- output_off();
- K2_ON();
- DISCH_ON();
- }
- #define MEAS_VOLT 0
- #define MEAS_CURR 1
- float meas[2];
- signed long int adc_results[2];
- unsigned char adc_process_data(void){
- static unsigned char adc_channel = AIN1;
- static signed long int adc;
- if(adc_data_ready){
- atomic_set_slint(&adc, adc_val);
- switch(adc_channel){
- case AIN1:
- adc_results[MEAS_VOLT] = adc;
- meas[MEAS_VOLT] = adc * settings.coeff_volt_A + settings.coeff_volt_B;
- adc_channel = AIN2;
- ads1224_mux(AIN2);
- break;
- case AIN2: default:
- adc_results[MEAS_CURR] = adc;
- meas[MEAS_CURR] = adc * settings.coeff_curr_A + settings.coeff_curr_B;
- adc_channel = AIN1;
- ads1224_mux(AIN1);
- break;
- }
- adc_data_ready = 0;
- return 1;
- }
- return 0;
- }
- __flash const char text0[] = "stop";
- __flash const char text1[] = "\x80""aduj";
- __flash const char text2[] = "roz\x80""aduj";
- __flash const char text3[] = "reset";
- __flash const char text4[] = "Uset(charg) = ";
- __flash const char text5[] = "Uset(disch) = ";
- __flash const char text6[] = "Iset = ";
- __flash const char *main_menu_texts[] = {
- text0,
- text1,
- text2,
- text3,
- text4,
- text5,
- text6,
- };
- #define MENU_MAX 6
- #define MODE_STOP 0
- #define MODE_CHARGE 1
- #define MODE_DISCHARGE 2
- void main(void){
- unsigned char i=0;
- unsigned char pos=0;
- unsigned char k;
- unsigned char mode = MODE_STOP;
- unsigned int volt_set = 365, disch_volt_set = 210, curr_set = 30; // *0,01V, *0,01V, *0,1A
- signed long long int charge_counter = 0, energy_counter = 0; // *0,1µC, *10µJ
- unsigned long int time_counter = 0; // *0,1s
- /* unsigned char state = STATE_DEFAULT;
- unsigned char oldstate = state;*/
-
- eeprom_read_block(&settings, &eep_settings, sizeof(struct settings));
-
-
- // system timer
- OCR2A = (125-1); // 1ms
- TCCR2A = _BV(WGM21);
- TCCR2B = _BV(CS22);
- TIMSK2 = _BV(OCIE2A);
-
-
- // fan pwm timer
- ICR1 = (330-1); // 25kHz
- OCR1B = 40;
- TCCR1A = _BV(COM1B1) | _BV(WGM11);
- TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
- TCCR1C = 0;
- DDRD |= _BV(PD4);
-
- sei();
- PORTC &= _BV(PC7); // KEY
- DDRB |= _BV(PB2); // TESTPOINT
-
- DDRD |= REL_K1 | REL_K2 | DISCH_ENABLE | CONV_ENABLE;
-
- GLCD_Initialize();
- GLCD_Clear();
-
- ads1224_init();
- ads1224_mux(AIN1);
-
- /* charge_on();
- set_voltage(volt_set);
- set_charge_curr(curr_set);*/
- for(;;){
- dac_update();
- adc_process_data();
- gettemp();
- cursor(0, 7);
- puttext_P(PSTR("Temp: "));
- if(temp_ok & _BV(0)){
- disp_temp(temps[0]);
- if(temps[0] < 350){
- atomic_set_uint(&OCR1B, 0);
- } else if(temps[0] < 900){
- atomic_set_uint(&OCR1B, (unsigned long int)((temps[0] - 300)*(unsigned long int)(0.506*32.0))>>5);
- } else {
- atomic_set_uint(&OCR1B, 329);
- }
- } else {
- atomic_set_uint(&OCR1B, 329);
- puttext_P(PSTR("B\x80\x7e""d"));
- }
- clearline();
- for(i=0; i<=MENU_MAX; i++){
- cursor(0, i);
- if(pos == i)
- putchar('*');
- else
- putchar(' ');
- putchar(' ');
- puttext_P(main_menu_texts[i]);
- putchar(' ');
- switch(i){
- default: break;
- case 1: if(mode == MODE_CHARGE) puttext_P(PSTR("w\x80.")); break;
- case 2: if(mode == MODE_DISCHARGE) puttext_P(PSTR("w\x80.")); break;
- case 4: disp_num(volt_set, 2); putchar('V'); break;
- case 5: disp_num(disch_volt_set, 2); putchar('V'); break;
- case 6: disp_num(curr_set, 1); putchar('A'); break;
- }
- clearline();
- }
- k = getkey();
- switch(k){
- default: break;
- case KEY_UP: if(pos>0) pos--; break;
- case KEY_DOWN: if(pos<MENU_MAX) pos++; break;
- case KEY_LEFT:
- switch(pos){
- case 4:
- if(mode != MODE_STOP)
- break;
- if(volt_set > 0)
- volt_set -= 5;
- break;
- case 5:
- if(mode != MODE_STOP)
- break;
- if(disch_volt_set > 0)
- disch_volt_set -= 5;
- break;
- case 6:
- if(mode != MODE_STOP)
- break;
- if(curr_set > 0)
- curr_set -= 1;
- break;
- }
- break;
- case KEY_RIGHT:
- switch(pos){
- case 4:
- if(mode != MODE_STOP)
- break;
- if(volt_set < 3000) // 30V
- volt_set += 5;
- break;
- case 5:
- if(mode != MODE_STOP)
- break;
- if(disch_volt_set < 3000) // 30V
- disch_volt_set += 5;
- break;
- case 6:
- if(mode != MODE_STOP)
- break;
- if(curr_set < 200)
- curr_set += 1; // 10A
- break;
- }
- break;
- case KEY_OK:
- switch(pos){
- case 0:
- mode = MODE_STOP;
- output_off();
- break;
- case 1:
- if(mode != MODE_STOP)
- break;
- mode = MODE_CHARGE;
- charge_on();
- set_voltage((float)volt_set/100.0);
- set_charge_curr((float)curr_set/10.0);
- break;
- case 2:
- if(mode != MODE_STOP)
- break;
- mode = MODE_DISCHARGE;
- discharge_on();
- set_discharge_curr((float)curr_set/10.0);
- break;
- case 3:
- if(mode != MODE_STOP)
- break;
- charge_counter = 0;
- energy_counter = 0;
- time_counter = 0;
- break;
- }
- break;
- }
-
- if(tick){
- cli();
- if(mode != MODE_STOP){
- charge_counter += meas[MEAS_CURR] * (float)tick / (float)(10.0 * 0.1e-6);
- energy_counter += meas[MEAS_CURR] * meas[MEAS_VOLT] * (float)tick / (float)(10.0 * 10e-6);
- time_counter += tick;
- }
- tick = 0;
- sei();
-
- if(mode == MODE_DISCHARGE && meas[MEAS_VOLT] < (float)disch_volt_set/100.0){
- mode = MODE_STOP;
- output_off();
- }
-
- cursor(0,8);
- disp_num(meas[MEAS_VOLT] * 1000, 3);
- putchar('V');
- putchar(' ');
- disp_num(meas[MEAS_CURR] * 1000, 3);
- putchar('A');
- putchar(' ');
- disp_num(meas[MEAS_CURR] * meas[MEAS_VOLT] * 10, 1);
- putchar('W');
- clearline();
- cursor(0,9);
- disp_num((float)charge_counter * (float)(0.1e-6 * 10000.0 / 3600.0), 4);
- puttext_P(PSTR("Ah "));
- disp_num((float)energy_counter * (float)(10e-6 * 10000.0 / 3600.0), 4);
- puttext_P(PSTR("Wh "));
- disp_num(time_counter, 1);
- puttext_P(PSTR("s"));
- clearline();
- }
- }
- }
- ISR(TIMER2_COMPA_vect){ // 1ms
- unsigned int *volatile ctimer;
- unsigned char i;
-
- for(i=0; i<sizeof(timers)/sizeof(unsigned int); i++){ // decrement every variable from timers struct unless it's already zero
- ctimer = ((unsigned int *)&timers) + i;
- if(*ctimer)
- (*ctimer)--;
- }
-
- if(timers.tick == 0){
- tick++; // 100ms
- timers.tick = 100;
- }
- }
|