main.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include <avr/pgmspace.h>
  4. #include <avr/eeprom.h>
  5. #include "main.h"
  6. #include "1wire.h"
  7. #include "gtext.h"
  8. #include "sed1335.h"
  9. #include "ds18b20.h"
  10. #include "dac8571.h"
  11. #include "ads1224.h"
  12. #include "display.h"
  13. volatile struct timers timers;
  14. volatile unsigned char tick; // incremented every 100ms
  15. unsigned char getkey(void){
  16. static unsigned char old;
  17. unsigned char key;
  18. static unsigned char counter;
  19. DDRA = 0;
  20. PORTA = 0xff;
  21. DDRC |= _BV(PC7);
  22. _delay_ms(2);
  23. key = ~PINA;
  24. DDRC &= ~_BV(PC7);
  25. PORTA = 0;
  26. DDRA = 0xff;
  27. if(key == 0)
  28. counter = 0;
  29. if(key == old){
  30. switch(counter){
  31. default:
  32. counter++;
  33. return 0;
  34. case 5:
  35. counter++;
  36. break;
  37. case 8:
  38. break;
  39. }
  40. } else {
  41. counter = 0;
  42. }
  43. old = key;
  44. return key;
  45. }
  46. struct settings {
  47. float coeff_generator_volt_A;
  48. float coeff_generator_volt_B;
  49. float coeff_generator_curr_A;
  50. float coeff_generator_curr_B;
  51. float coeff_disch_curr_A;
  52. float coeff_disch_curr_B;
  53. float coeff_volt_A;
  54. float coeff_volt_B;
  55. float coeff_curr_A;
  56. float coeff_curr_B;
  57. };
  58. struct settings settings;
  59. EEMEM struct settings eep_settings = {
  60. .coeff_generator_volt_A = 1597.035901,
  61. .coeff_generator_volt_B = 1317.235211,
  62. .coeff_generator_curr_A = 65535.0/20,
  63. .coeff_generator_curr_B = 1310,
  64. .coeff_disch_curr_A = 2996.00532623169,
  65. .coeff_disch_curr_B = 4298.2689747004,
  66. .coeff_volt_A = 1.55337778893448E-07,
  67. .coeff_volt_B = -0.092784032021951,
  68. .coeff_curr_A = -9.03353481586364E-08,
  69. .coeff_curr_B = 0.124868806047484,
  70. // .coeff_curr_A = .001,
  71. // .coeff_curr_B = 0,
  72. };
  73. unsigned int vdac = 0;
  74. unsigned int cdac = 0;
  75. void dac_update(void){
  76. dac8571_set(cdac, CURR_DAC);
  77. dac8571_set(vdac, VOLT_DAC);
  78. }
  79. void set_voltage(float u){
  80. vdac = u * settings.coeff_generator_volt_A + settings.coeff_generator_volt_B;
  81. dac_update();
  82. }
  83. void set_charge_curr(float i){
  84. cdac = i * settings.coeff_generator_curr_A + settings.coeff_generator_curr_B;
  85. dac_update();
  86. }
  87. void set_discharge_curr(float i){
  88. cdac = i * settings.coeff_disch_curr_A + settings.coeff_disch_curr_B;
  89. dac_update();
  90. }
  91. #define CONV_ENABLE _BV(PD5)
  92. #define DISCH_ENABLE _BV(PD1)
  93. #define REL_K1 _BV(PD6)
  94. #define REL_K2 _BV(PD7)
  95. #define K1_ON() {PORTD |= REL_K1;}
  96. #define K1_OFF() {PORTD &= ~REL_K1;}
  97. #define K2_ON() {PORTD |= REL_K2;}
  98. #define K2_OFF() {PORTD &= ~REL_K2;}
  99. #define POWER_OFF() {PORTD &= ~(CONV_ENABLE | DISCH_ENABLE);}
  100. #define CONV_ON() {PORTD |= CONV_ENABLE;}
  101. #define DISCH_ON() {PORTD |= DISCH_ENABLE;}
  102. void output_off(void){
  103. cdac = 0;
  104. vdac = 0;
  105. POWER_OFF();
  106. dac_update();
  107. K1_OFF();
  108. K2_OFF();
  109. }
  110. void charge_on(void){
  111. output_off();
  112. K1_ON();
  113. CONV_ON();
  114. }
  115. void discharge_on(void){
  116. output_off();
  117. K2_ON();
  118. DISCH_ON();
  119. }
  120. #define MEAS_VOLT 0
  121. #define MEAS_CURR 1
  122. float meas[2];
  123. signed long int adc_results[2];
  124. unsigned char adc_process_data(void){
  125. static unsigned char adc_channel = AIN1;
  126. static signed long int adc;
  127. if(adc_data_ready){
  128. atomic_set_slint(&adc, adc_val);
  129. switch(adc_channel){
  130. case AIN1:
  131. adc_results[MEAS_VOLT] = adc;
  132. meas[MEAS_VOLT] = adc * settings.coeff_volt_A + settings.coeff_volt_B;
  133. adc_channel = AIN2;
  134. ads1224_mux(AIN2);
  135. break;
  136. case AIN2: default:
  137. adc_results[MEAS_CURR] = adc;
  138. meas[MEAS_CURR] = adc * settings.coeff_curr_A + settings.coeff_curr_B;
  139. adc_channel = AIN1;
  140. ads1224_mux(AIN1);
  141. break;
  142. }
  143. adc_data_ready = 0;
  144. return 1;
  145. }
  146. return 0;
  147. }
  148. __flash const char text0[] = "stop";
  149. __flash const char text1[] = "\x80""aduj";
  150. __flash const char text2[] = "roz\x80""aduj";
  151. __flash const char text3[] = "reset";
  152. __flash const char text4[] = "Uset(charg) = ";
  153. __flash const char text5[] = "Uset(disch) = ";
  154. __flash const char text6[] = "Iset = ";
  155. __flash const char *main_menu_texts[] = {
  156. text0,
  157. text1,
  158. text2,
  159. text3,
  160. text4,
  161. text5,
  162. text6,
  163. };
  164. #define MENU_MAX 6
  165. #define MODE_STOP 0
  166. #define MODE_CHARGE 1
  167. #define MODE_DISCHARGE 2
  168. void main(void){
  169. unsigned char i=0;
  170. unsigned char pos=0;
  171. unsigned char k;
  172. unsigned char mode = MODE_STOP;
  173. unsigned int volt_set = 365, disch_volt_set = 210, curr_set = 30; // *0,01V, *0,01V, *0,1A
  174. signed long long int charge_counter = 0, energy_counter = 0; // *0,1µC, *10µJ
  175. unsigned long int time_counter = 0; // *0,1s
  176. /* unsigned char state = STATE_DEFAULT;
  177. unsigned char oldstate = state;*/
  178. eeprom_read_block(&settings, &eep_settings, sizeof(struct settings));
  179. // system timer
  180. OCR2A = (125-1); // 1ms
  181. TCCR2A = _BV(WGM21);
  182. TCCR2B = _BV(CS22);
  183. TIMSK2 = _BV(OCIE2A);
  184. // fan pwm timer
  185. ICR1 = (330-1); // 25kHz
  186. OCR1B = 40;
  187. TCCR1A = _BV(COM1B1) | _BV(WGM11);
  188. TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
  189. TCCR1C = 0;
  190. DDRD |= _BV(PD4);
  191. sei();
  192. PORTC &= _BV(PC7); // KEY
  193. DDRB |= _BV(PB2); // TESTPOINT
  194. DDRD |= REL_K1 | REL_K2 | DISCH_ENABLE | CONV_ENABLE;
  195. GLCD_Initialize();
  196. GLCD_Clear();
  197. ads1224_init();
  198. ads1224_mux(AIN1);
  199. /* charge_on();
  200. set_voltage(volt_set);
  201. set_charge_curr(curr_set);*/
  202. for(;;){
  203. dac_update();
  204. adc_process_data();
  205. gettemp();
  206. cursor(0, 7);
  207. puttext_P(PSTR("Temp: "));
  208. if(temp_ok & _BV(0)){
  209. disp_temp(temps[0]);
  210. if(temps[0] < 350){
  211. atomic_set_uint(&OCR1B, 0);
  212. } else if(temps[0] < 900){
  213. atomic_set_uint(&OCR1B, (unsigned long int)((temps[0] - 300)*(unsigned long int)(0.506*32.0))>>5);
  214. } else {
  215. atomic_set_uint(&OCR1B, 329);
  216. }
  217. } else {
  218. atomic_set_uint(&OCR1B, 329);
  219. puttext_P(PSTR("B\x80\x7e""d"));
  220. }
  221. clearline();
  222. for(i=0; i<=MENU_MAX; i++){
  223. cursor(0, i);
  224. if(pos == i)
  225. putchar('*');
  226. else
  227. putchar(' ');
  228. putchar(' ');
  229. puttext_P(main_menu_texts[i]);
  230. putchar(' ');
  231. switch(i){
  232. default: break;
  233. case 1: if(mode == MODE_CHARGE) puttext_P(PSTR("w\x80.")); break;
  234. case 2: if(mode == MODE_DISCHARGE) puttext_P(PSTR("w\x80.")); break;
  235. case 4: disp_num(volt_set, 2); putchar('V'); break;
  236. case 5: disp_num(disch_volt_set, 2); putchar('V'); break;
  237. case 6: disp_num(curr_set, 1); putchar('A'); break;
  238. }
  239. clearline();
  240. }
  241. k = getkey();
  242. switch(k){
  243. default: break;
  244. case KEY_UP: if(pos>0) pos--; break;
  245. case KEY_DOWN: if(pos<MENU_MAX) pos++; break;
  246. case KEY_LEFT:
  247. switch(pos){
  248. case 4:
  249. if(mode != MODE_STOP)
  250. break;
  251. if(volt_set > 0)
  252. volt_set -= 5;
  253. break;
  254. case 5:
  255. if(mode != MODE_STOP)
  256. break;
  257. if(disch_volt_set > 0)
  258. disch_volt_set -= 5;
  259. break;
  260. case 6:
  261. if(mode != MODE_STOP)
  262. break;
  263. if(curr_set > 0)
  264. curr_set -= 1;
  265. break;
  266. }
  267. break;
  268. case KEY_RIGHT:
  269. switch(pos){
  270. case 4:
  271. if(mode != MODE_STOP)
  272. break;
  273. if(volt_set < 3000) // 30V
  274. volt_set += 5;
  275. break;
  276. case 5:
  277. if(mode != MODE_STOP)
  278. break;
  279. if(disch_volt_set < 3000) // 30V
  280. disch_volt_set += 5;
  281. break;
  282. case 6:
  283. if(mode != MODE_STOP)
  284. break;
  285. if(curr_set < 200)
  286. curr_set += 1; // 10A
  287. break;
  288. }
  289. break;
  290. case KEY_OK:
  291. switch(pos){
  292. case 0:
  293. mode = MODE_STOP;
  294. output_off();
  295. break;
  296. case 1:
  297. if(mode != MODE_STOP)
  298. break;
  299. mode = MODE_CHARGE;
  300. charge_on();
  301. set_voltage((float)volt_set/100.0);
  302. set_charge_curr((float)curr_set/10.0);
  303. break;
  304. case 2:
  305. if(mode != MODE_STOP)
  306. break;
  307. mode = MODE_DISCHARGE;
  308. discharge_on();
  309. set_discharge_curr((float)curr_set/10.0);
  310. break;
  311. case 3:
  312. if(mode != MODE_STOP)
  313. break;
  314. charge_counter = 0;
  315. energy_counter = 0;
  316. time_counter = 0;
  317. break;
  318. }
  319. break;
  320. }
  321. if(tick){
  322. cli();
  323. if(mode != MODE_STOP){
  324. charge_counter += meas[MEAS_CURR] * (float)tick / (float)(10.0 * 0.1e-6);
  325. energy_counter += meas[MEAS_CURR] * meas[MEAS_VOLT] * (float)tick / (float)(10.0 * 10e-6);
  326. time_counter += tick;
  327. }
  328. tick = 0;
  329. sei();
  330. if(mode == MODE_DISCHARGE && meas[MEAS_VOLT] < (float)disch_volt_set/100.0){
  331. mode = MODE_STOP;
  332. output_off();
  333. }
  334. cursor(0,8);
  335. disp_num(meas[MEAS_VOLT] * 1000, 3);
  336. putchar('V');
  337. putchar(' ');
  338. disp_num(meas[MEAS_CURR] * 1000, 3);
  339. putchar('A');
  340. putchar(' ');
  341. disp_num(meas[MEAS_CURR] * meas[MEAS_VOLT] * 10, 1);
  342. putchar('W');
  343. clearline();
  344. cursor(0,9);
  345. disp_num((float)charge_counter * (float)(0.1e-6 * 10000.0 / 3600.0), 4);
  346. puttext_P(PSTR("Ah "));
  347. disp_num((float)energy_counter * (float)(10e-6 * 10000.0 / 3600.0), 4);
  348. puttext_P(PSTR("Wh "));
  349. disp_num(time_counter, 1);
  350. puttext_P(PSTR("s"));
  351. clearline();
  352. }
  353. }
  354. }
  355. ISR(TIMER2_COMPA_vect){ // 1ms
  356. unsigned int *volatile ctimer;
  357. unsigned char i;
  358. for(i=0; i<sizeof(timers)/sizeof(unsigned int); i++){ // decrement every variable from timers struct unless it's already zero
  359. ctimer = ((unsigned int *)&timers) + i;
  360. if(*ctimer)
  361. (*ctimer)--;
  362. }
  363. if(timers.tick == 0){
  364. tick++; // 100ms
  365. timers.tick = 100;
  366. }
  367. }