heater3.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  1. #include "heater3.h"
  2. #include "lcd-twi.h"
  3. #include "potentiometers.h"
  4. #include "saveload.h"
  5. #include "fifo.h"
  6. #include "tools.h"
  7. const char cyrillic[64] = { 'A', 0xA0, 'B', 0xA1, 0xE0, 'E', 0xA3, 0xA4, 0xA5, 0xA6, 'K', 0xA7, 'M', 'H', 'O', 0xA8,
  8. 'P', 'C', 'T', 0xA9, 0xAA, 'X', 0xE1, 0xAB, 0xAC, 0xE2, 0xAD, 0xAE, 'b', 0xAF, 0xB0, 0xB1,
  9. 'a', 0xB2, 0xB3, 0xB4, 0xE3, 'e', 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 'o', 0xBE,
  10. 'p', 'c', 0xBF, 'y', 0xE4, 'x', 0xE5, 0xC0, 0xC1, 0xE6, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7 };
  11. volatile uint8_t btn_act = 0;
  12. volatile uint8_t rxbuf[40];
  13. volatile uint8_t count = 0;
  14. volatile comdata_str rxdata;
  15. volatile uint8_t tick1 = 0;
  16. volatile uint8_t tick2 = 0;
  17. uint8_t cal_tmax = 130;
  18. uint8_t cal_tmin = 40;
  19. heater_str heater[2];
  20. opamp_str opamp[2];
  21. preset_str preset[2];
  22. uint8_t txrequest = 0;
  23. static FILE lcd_stdout = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
  24. static FILE uart_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
  25. FIFO(512) fifo0;
  26. ISR(PCINT3_vect)
  27. {
  28. btn_act = 1;
  29. if(((BTNPIN >> 4) | 0xF0) == 0xF0)
  30. {
  31. cli();
  32. WDTCSR |= (1 << WDCE) | (1 << WDE);
  33. }
  34. }
  35. ISR(INT0_vect) /*OVERCURRENT PROTECTION 1*/
  36. {
  37. cli();
  38. GATEPORT |= (1 << GATE1) | (1 << GATE2);
  39. LEDPORT &= ~((1 << LED1) | (1 << LED2));
  40. PORTC &= ~(1 << V12POWER);
  41. heater[0].status.heating = heater[1].status.heating = 0;
  42. heater[0].status.onoff = heater[1].status.onoff = 0;
  43. heater[0].status.ocp = 1;
  44. }
  45. ISR(INT1_vect) /*OVERCURRENT PROTECTION 2*/
  46. {
  47. cli();
  48. GATEPORT |= (1 << GATE1) | (1 << GATE2);
  49. LEDPORT &= ~((1 << LED1) | (1 << LED2));
  50. PORTC &= ~(1 << V12POWER);
  51. heater[0].status.heating = heater[1].status.heating = 0;
  52. heater[0].status.onoff = heater[1].status.onoff = 0;
  53. heater[1].status.ocp = 1;
  54. }
  55. ISR(USART0_RX_vect)
  56. {
  57. count++;
  58. rxbuf[count - 1] = UDR0;
  59. }
  60. ISR(USART0_UDRE_vect)
  61. {
  62. if(FIFO_IS_EMPTY(fifo0))
  63. {
  64. UCSR0B &= ~(1 << UDRIE0);
  65. }
  66. else
  67. {
  68. UDR0 = FIFO_FRONT(fifo0);
  69. FIFO_POP(fifo0);
  70. }
  71. }
  72. ISR(TIMER0_COMPA_vect)
  73. {
  74. tick1 = 1;
  75. }
  76. ISR(TIMER1_COMPA_vect)
  77. {
  78. tick2 = 1;
  79. }
  80. void init()
  81. {
  82. /* Watchdog clear*/
  83. MCUSR &= ~(1 << WDRF);
  84. WDTCSR |= (1 << WDCE) | (1 << WDE);
  85. WDTCSR = 0x00;
  86. /* External interrupts initialization */
  87. EICRA |= (1 << ISC01) | (1 << ISC11);
  88. EIMSK |= (1 << INT0) | (1 << INT1);
  89. /* GPIO Initialization */
  90. PORTC |= (1 << GATE1) | (1 << GATE2) | (1 << V12POWER);
  91. DDRC |= (1 << LED1) | (1 << LED2) | (1 << GATE1) | (1 << GATE2) | (1 << V12POWER);
  92. /* UART Initialization */
  93. TXD_PORT |= (1 << TXD_BIT);
  94. TXD_DDR |= (1 << TXD_BIT);
  95. #if U2X0_SET
  96. UBRR0H = (uint8_t)(((F_CPU / (8 * BAUD_RATE)) - 1) >> 8);
  97. UBRR0L = (uint8_t)((F_CPU / (8 * BAUD_RATE)) - 1);
  98. UCSR0A = (1 << U2X0);
  99. #elif
  100. UBRR0H = (uint8_t)(((F_CPU / (16 * BAUD_RATE)) - 1) >> 8);
  101. UBRR0L = (uint8_t)((F_CPU / (16 * BAUD_RATE)) - 1);
  102. #endif
  103. UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
  104. UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
  105. /* SPI Initialization */
  106. DDRB |= (1 << MOSI_BIT) | (1 << SCK_BIT) | (1 << SS_BIT) | (7 << PORTB0);
  107. PORTB |= (1 << MOSI_BIT) | (1 << SCK_BIT) | (1 << SS_BIT);
  108. SPCR = (1 << SPE) | (1 << MSTR);
  109. /* TWI Initialization */
  110. TWBR = (uint8_t)(((F_CPU / TWI_FREQ) - 16) / 2);
  111. TWCR = (1 << TWEN);
  112. /* Timer0 Initialization */
  113. TCCR0A = (1 << WGM01);
  114. OCR0A = 0x80;
  115. TCCR0B = (1 << CS00) | (1 << CS02);
  116. TIMSK0 = (1 << OCIE0A);
  117. /* Timer1 Initialization */
  118. TCCR1B = (1 << CS12) | (1 << CS10) | (1 << WGM12);
  119. OCR1A = 0x400;
  120. TIMSK1 = (1 << OCIE1A);
  121. /* ADC Initialization */
  122. ADMUX |= (1 << REFS0) | (1 << REFS1);
  123. ADCSRA = (1 << ADEN) | (1 << ADPS0) | (1 << ADPS1);
  124. DIDR0 = 0xFF;
  125. PCICR = (1 << PCIE3);
  126. PCMSK3 = 0xF0;
  127. }
  128. void MAX_ReadData()
  129. {
  130. uint8_t i = 0;
  131. max31855_t data;
  132. btw32_t *dptr = (btw32_t*)&data;
  133. PORTB = (PORTB & 0xF8) | MAXADDR;
  134. PORTB &= ~(1 << SS_BIT);
  135. for(i = 0; i < 4; i++)
  136. {
  137. SPDR = 0xFF;
  138. while(!(SPSR & (1 << SPIF)));
  139. dptr->byte[3 - i] = SPDR;
  140. }
  141. PORTB |= (1 << SS_BIT);
  142. heater[CH0].tintr = heater[CH1].tintr = (int8_t)data.intt_int;
  143. if(data.intt_frac * (100.0 / 16.0) >= 50)
  144. heater[CH0].tintr++;
  145. if(data.oc | data.scg | data.scg)
  146. {
  147. heater[CH0].status.couple = heater[CH1].status.couple = dptr->byte[0] & 0x07;
  148. heater[CH0].tcouple = heater[CH1].tcouple = 0;
  149. }
  150. else
  151. {
  152. heater[CH0].status.couple = heater[CH1].status.couple = 0;
  153. heater[CH0].tcouple = heater[CH1].tcouple = ((int16_t)data.tct_int ^ 0x0800) - 0x0800;
  154. if((data.tct_frac * (100 / 4)) >= 50)
  155. heater[CH0].tcouple = heater[CH1].tcouple++;
  156. }
  157. }
  158. int16_t CalculateTemp(uint16_t data, uint8_t ch)
  159. {
  160. if(data > preset[ch].curve[0].adcdata)
  161. return 0;
  162. if(data < preset[ch].curve[15].adcdata)
  163. return 150;
  164. for(uint8_t i = 0; i < 16; i++)
  165. {
  166. if(data >= preset[ch].curve[i].adcdata)
  167. {
  168. return Approx(preset[ch].curve[i - 1].adcdata, preset[ch].curve[i].adcdata,
  169. preset[ch].curve[i - 1].temp, preset[ch].curve[i].temp, data);
  170. }
  171. }
  172. return (-1);
  173. }
  174. int16_t TMeasure(uint8_t ch)
  175. {
  176. uint16_t addata = 0;
  177. uint16_t avg_data = 0;
  178. uint8_t i = 0;
  179. ADMUX = (ADMUX & 0xF8) | (ch & 0x01);
  180. _delay_us(100);
  181. avg_data = 0;
  182. for(i = 0; i < 10; i++)
  183. {
  184. ADCSRA |= (1 << ADSC);
  185. while(!(ADCSRA & (1 << ADIF)));
  186. addata = ADCL;
  187. addata |= ((uint16_t)ADCH) << 8;
  188. avg_data += addata;
  189. }
  190. addata = avg_data / 10;
  191. heater[ch].tmeas_raw = addata;
  192. heater[ch].tmeas = CalculateTemp(addata, ch);
  193. return (heater[ch].tmeas);
  194. }
  195. uint16_t CurrMeasure(uint8_t ch)
  196. {
  197. uint16_t addata = 0;
  198. ADMUX = (ADMUX & 0xF8) | (ADC_CUR1 + (ch & 0x01));
  199. _delay_us(100);
  200. ADCSRA |= (1 << ADSC);
  201. while(!(ADCSRA & (1 << ADIF)));
  202. addata = ADCL;
  203. addata |= ((uint16_t)ADCH) << 8;
  204. heater[ch].current = ((float)addata * 2.4);
  205. return (heater[ch].current);
  206. }
  207. int lcd_putchar(char c, FILE *stream)
  208. {
  209. if(c >= 0xC0)
  210. c = cyrillic[c - 0xC0];
  211. LCD_SendData(c);
  212. return 0;
  213. }
  214. int uart_putchar(char c, FILE *stream)
  215. {
  216. cli();
  217. if(!FIFO_IS_FULL(fifo0))
  218. {
  219. FIFO_PUSH(fifo0, c);
  220. UCSR0B |= (1 << UDRIE0);
  221. }
  222. sei();
  223. return 0;
  224. }
  225. void TransmitPresets()
  226. {
  227. uint8_t checksum = 0x1F;
  228. uart_putchar(0x55, NULL);
  229. // fprintf(&uart_stdout, "BEG");
  230. uart_putchar(0x45, NULL);
  231. uart_putchar(0x85, NULL);
  232. for(uint8_t pn = 0; pn < 25; pn++)
  233. {
  234. for(uint8_t offs = 0; offs < 13; offs++)
  235. {
  236. EEAR = 0x30 + (pn * sizeof(preset_str)) + offs;
  237. EECR |= (1 << EERE);
  238. uint8_t data = EEDR;
  239. uart_putchar(data, NULL);
  240. checksum += data;
  241. }
  242. }
  243. uart_putchar(checksum, NULL);
  244. txrequest = 0;
  245. // fprintf(&uart_stdout, "END");
  246. }
  247. void Transmit()
  248. {
  249. comdata_str *txdata = (comdata_str*)calloc(1, sizeof(comdata_str));
  250. txdata->start = 0x55;
  251. txdata->command = txrequest;
  252. switch((txreq_t)txrequest)
  253. {
  254. case REQ_RST:
  255. case REQ_ACK:
  256. case REQ_NACK:
  257. txdata->len = 0;
  258. break;
  259. case REQ_MAINDATA:
  260. txdata->len = sizeof(heater);
  261. memcpy(txdata->data, heater, sizeof(heater));
  262. break;
  263. case REQ_DEBUGDATA:
  264. break;
  265. case REQ_PRESETTABLE:
  266. TransmitPresets();
  267. free(txdata);
  268. return;
  269. case REQ_PRESETDATA:
  270. txdata->len = sizeof(preset);
  271. memcpy(txdata->data, preset, sizeof(preset));
  272. break;
  273. }
  274. //fprintf(&uart_stdout, "BEG");
  275. for(uint8_t i = 0; i < (txdata->len + 3); i++)
  276. {
  277. uart_putchar(((uint8_t*)txdata)[i], NULL);
  278. txdata->checksum += ((uint8_t*)txdata)[i];
  279. }
  280. uart_putchar(txdata->checksum, NULL);
  281. //fprintf(&uart_stdout, "END");
  282. txrequest = 0;
  283. free(txdata);
  284. }
  285. void ResetMCU(void)
  286. {
  287. cli();
  288. WDTCSR |= (1 << WDCE) | (1 << WDE);
  289. while(1);
  290. }
  291. void SwitchHeating(uint8_t ch, uint8_t onoff)
  292. {
  293. if(onoff)
  294. {
  295. GATEPORT &= ~(1 << (GATE1 + (ch & 0x01)));
  296. LEDPORT |= (1 << (LED1 + (ch & 0x01)));
  297. heater[ch].status.heating = 1;
  298. }
  299. else
  300. {
  301. GATEPORT |= (1 << (GATE1 + (ch & 0x01)));
  302. LEDPORT &= ~(1 << (LED1 + (ch & 0x01)));
  303. heater[ch].status.heating = 0;
  304. }
  305. }
  306. float VoltageMeasure(uint8_t ch)
  307. {
  308. uint16_t addata = 0;
  309. float voltage = 0.0;
  310. ADMUX = (ADMUX & 0xF8) | (ch & 0x01);
  311. _delay_us(100);
  312. ADCSRA |= (1 << ADSC);
  313. while(!(ADCSRA & (1 << ADIF)));
  314. addata = ADCL;
  315. addata |= ((uint16_t)ADCH) << 8;
  316. voltage = (float)addata * 0.0025;
  317. voltage = (voltage / (0.758 * opamp[ch].gain)) + opamp[ch].shift;
  318. return voltage;
  319. }
  320. circ_t CircuitDetect(uint8_t ch)
  321. {
  322. uint8_t gain, shift, drive;
  323. float voltage;
  324. circ_t circ;
  325. gain = heater[ch].gain;
  326. shift = heater[ch].shift;
  327. drive = heater[ch].drive;
  328. SetDriveVoltage(ch, 0);
  329. SetInputRange(ch, 0.0, 3.0);
  330. voltage = VoltageMeasure(ch);
  331. if(voltage > 3.0)
  332. {
  333. circ = CIRC_OPEN;
  334. }
  335. else if((voltage > 0.05) && (voltage <= 1.5))
  336. {
  337. SetDriveData(ch, 0xFF);
  338. SwitchDrive(ch, ON);
  339. _delay_ms(1);
  340. voltage = VoltageMeasure(ch);
  341. SetDriveData(ch, drive);
  342. SwitchDrive(ch, OFF);
  343. if(voltage < 0.2)
  344. {
  345. circ = CIRC_MOSFET;
  346. }
  347. else
  348. {
  349. circ = CIRC_RES_DIODE;
  350. }
  351. }
  352. else
  353. {
  354. circ = CIRC_RES;
  355. }
  356. SetGainData(ch, gain);
  357. SetShiftData(ch, shift);
  358. SetDriveData(ch, drive);
  359. heater[ch].status.circuit = circ;
  360. return circ;
  361. }
  362. void UARTDataAvail()
  363. {
  364. static uint8_t rxcnt;
  365. uint8_t localcnt = count;
  366. for(uint8_t i = 0; i < localcnt; i++)
  367. {
  368. uint8_t rxbyte = rxbuf[i];
  369. switch(rxcnt)
  370. {
  371. case 0:
  372. if(rxbyte == 0x55)
  373. {
  374. //rxdata.start = rxbyte;
  375. rxdata.checksum = rxbyte;
  376. rxcnt++;
  377. }
  378. break;
  379. case 1:
  380. if(rxbyte < 100)
  381. {
  382. rxdata.len = rxbyte;
  383. rxdata.checksum += rxbyte;
  384. rxcnt++;
  385. }
  386. else
  387. {
  388. rxcnt = 0;
  389. }
  390. break;
  391. case 2:
  392. rxdata.command = rxbyte;
  393. rxdata.checksum += rxbyte;
  394. rxcnt++;
  395. break;
  396. default:
  397. if(rxcnt < (rxdata.len + 3))
  398. {
  399. rxdata.data[rxcnt - 3] = rxbyte;
  400. rxdata.checksum += rxbyte;
  401. rxcnt++;
  402. }
  403. else
  404. {
  405. if(rxbyte == rxdata.checksum)
  406. {
  407. ProcessCommand();
  408. }
  409. rxcnt = 0;
  410. }
  411. }
  412. count--;
  413. }
  414. }
  415. int AutoCalibration(uint8_t ch)
  416. {
  417. uint8_t drive = 0;
  418. int16_t tstart = 0;
  419. uint16_t delcnt = 0;
  420. float vlow = 0.0, vhigh = 0.0;
  421. MAX_ReadData();
  422. CircuitDetect(ch);
  423. if(((heater[ch].status.circuit == CIRC_MOSFET) || (heater[ch].status.circuit == CIRC_RES_DIODE)) && (heater[ch].status.couple == 0))
  424. {
  425. LCD_SendCmd(LCD_CLR);
  426. SetInputRange(ch, 0.0, 3.0);
  427. SetDriveVoltage(ch, 0.0);
  428. _delay_ms(2);
  429. do {
  430. MAX_ReadData();
  431. LCD_SetPos(0, 0);
  432. fprintf(&lcd_stdout, "K%.1u P%.2u Tm=%.3u -", ch + 1, heater[ch].preset, heater[ch].tmeas);
  433. LCD_SetPos(0, 1);
  434. fprintf(&lcd_stdout, "CALIB. Tc=%.3u -", heater[ch].tcouple);
  435. } while(heater[ch].tcouple > cal_tmin);
  436. tstart = heater[ch].tcouple;
  437. vhigh = VoltageMeasure(ch) + 0.04;
  438. if(heater[ch].status.circuit == CIRC_MOSFET)
  439. {
  440. do {
  441. SetDriveData(ch, drive);
  442. SwitchDrive(ch, ON);
  443. SwitchHeating(ch, ON);
  444. _delay_ms(1);
  445. CurrMeasure(ch);
  446. SwitchHeating(ch, OFF);
  447. SwitchDrive(ch, OFF);
  448. drive++;
  449. } while(heater[ch].current < 1000);
  450. drive--;
  451. SwitchDrive(ch, ON);
  452. }
  453. SwitchHeating(ch, ON);
  454. while(heater[ch].tcouple < (cal_tmax + 2))
  455. {
  456. if(CurrMeasure(ch) > CURR_MAX)
  457. return 0;
  458. if(heater[ch].status.circuit == CIRC_MOSFET)
  459. {
  460. if(heater[ch].current > 1500)
  461. {
  462. SetDriveData(ch, --drive);
  463. SwitchDrive(ch, ON);
  464. }
  465. if(heater[ch].current < 1000)
  466. {
  467. SetDriveData(ch, ++drive);
  468. SwitchDrive(ch, ON);
  469. }
  470. }
  471. MAX_ReadData();
  472. if((heater[ch].status.circuit == CIRC_OPEN) || (heater[ch].status.circuit == CIRC_RES) || (heater[ch].status.couple != 0))
  473. {
  474. LoadPreset(ch);
  475. return (-1);
  476. }
  477. if(++delcnt > 300)
  478. {
  479. delcnt = 0;
  480. if((heater[ch].tcouple - tstart) < 5)
  481. {
  482. SwitchHeating(ch, OFF);
  483. SwitchDrive(ch, OFF);
  484. LCD_SetPos(0, 0);
  485. fprintf(&lcd_stdout, "Íåäîñòàòî÷íûé ");
  486. LCD_SetPos(0, 1);
  487. fprintf(&lcd_stdout, "òåïëîâîé êîíòàêò");
  488. LoadPreset(ch);
  489. btn_act = 0;
  490. while(!btn_act);
  491. return(-1);
  492. }
  493. else
  494. {
  495. tstart = heater[ch].tcouple;
  496. }
  497. }
  498. LCD_SetPos(0, 0);
  499. fprintf(&lcd_stdout, "%04.2f-%04.2f G=%04.2f", vhigh, vlow, opamp[ch].drive);
  500. LCD_SetPos(0, 1);
  501. fprintf(&lcd_stdout, "I=%.4umA Tc=%.3u ", heater[ch].current, heater[ch].tcouple);
  502. }
  503. SwitchHeating(ch, OFF);
  504. SwitchDrive(ch, OFF);
  505. _delay_ms(2);
  506. vlow = VoltageMeasure(ch);
  507. if(vlow > 0.01)
  508. vlow -= 0.01;
  509. SetInputRange(ch, vlow, vhigh);
  510. for(uint8_t temp = cal_tmax; temp >= cal_tmin; temp -= 10)
  511. {
  512. while(heater[ch].tcouple >= temp)
  513. {
  514. MAX_ReadData();
  515. LCD_SetPos(0, 0);
  516. fprintf(&lcd_stdout, "VH=%04.2f Dm=%.3u -", vhigh, heater[ch].tmeas_raw);
  517. LCD_SetPos(0, 1);
  518. fprintf(&lcd_stdout, "VL=%04.2f Tc=%.3u -", vlow, heater[ch].tcouple);
  519. }
  520. TMeasure(ch);
  521. preset[ch].curve[temp / 10].temp = temp;
  522. preset[ch].curve[temp / 10].adcdata = heater[ch].tmeas_raw;
  523. if((heater[ch].status.circuit == CIRC_OPEN) || (heater[ch].status.circuit == CIRC_RES) || (heater[ch].status.couple != 0) )
  524. {
  525. LoadPreset(ch);
  526. return (-1);
  527. }
  528. }
  529. for(uint8_t temp = 0; temp < cal_tmin; temp += 10)
  530. {
  531. preset[ch].curve[temp / 10].temp = temp;
  532. preset[ch].curve[temp / 10].adcdata = Approx(preset[ch].curve[cal_tmin / 10].temp, preset[ch].curve[cal_tmax / 10].temp,
  533. preset[ch].curve[cal_tmin / 10].adcdata, preset[ch].curve[cal_tmax / 10].adcdata, preset[ch].curve[temp / 10].temp);
  534. }
  535. for(uint8_t temp = (cal_tmax + 10); temp < 160; temp += 10)
  536. {
  537. preset[ch].curve[temp / 10].temp = temp;
  538. preset[ch].curve[temp / 10].adcdata = Approx(preset[ch].curve[cal_tmin / 10].temp, preset[ch].curve[cal_tmax / 10].temp,
  539. preset[ch].curve[cal_tmin / 10].adcdata, preset[ch].curve[cal_tmax / 10].adcdata, preset[ch].curve[temp / 10].temp);
  540. }
  541. if(strlen(preset[ch].header) == 0)
  542. {
  543. strncpy(preset[ch].header, "DEFAULT", 12);
  544. }
  545. preset[ch].number = heater[ch].preset;
  546. preset[ch].gain = heater[ch].gain;
  547. preset[ch].shift = heater[ch].shift;
  548. preset[ch].drive = heater[ch].drive;
  549. SavePreset(ch);
  550. LCD_SendCmd(LCD_CLR);
  551. }
  552. return 0;
  553. }
  554. void ManualCalibration(uint8_t ch)
  555. {
  556. uint8_t drive = 0;
  557. float vlow = 0.0, vhigh = 0.0;
  558. LCD_SendCmd(LCD_CLR);
  559. LCD_SetPos(0, 0);
  560. fprintf(&lcd_stdout, "ÐÓ×Í. ÊÀËÈÁÐÎÂÊÀ");
  561. if(heater[ch].status.circuit == CIRC_MOSFET)
  562. {
  563. do {
  564. SetDriveData(ch, drive);
  565. SwitchDrive(ch, ON);
  566. SwitchHeating(ch, ON);
  567. _delay_ms(1);
  568. CurrMeasure(ch);
  569. SwitchHeating(ch, OFF);
  570. SwitchDrive(ch, OFF);
  571. drive++;
  572. } while(heater[ch].current < 1000);
  573. drive--;
  574. }
  575. while(heater[ch].status.calib == CAL_MANUAL)
  576. {
  577. if(count)
  578. {
  579. UARTDataAvail();
  580. }
  581. if(txrequest)
  582. {
  583. Transmit();
  584. }
  585. if(heater[ch].status.heating)
  586. {
  587. if(heater[ch].status.circuit == CIRC_MOSFET)
  588. SwitchDrive(ch, ON);
  589. SwitchHeating(ch, ON);
  590. _delay_ms(1);
  591. if(CurrMeasure(ch) > 2000)
  592. {
  593. drive--;
  594. SetDriveData(ch, drive);
  595. SwitchDrive(ch, ON);
  596. }
  597. }
  598. else
  599. {
  600. SwitchHeating(ch, OFF);
  601. SwitchDrive(ch, OFF);
  602. }
  603. }
  604. heater[ch].status.heating = OFF;
  605. }
  606. void ProcessCommand()
  607. {
  608. uint8_t ch = ((rxdata.command & 0x80) >> 7) & 0x01;
  609. rxdata.command &= 0x7F;
  610. txrequest = REQ_ACK;
  611. switch(rxdata.command)
  612. {
  613. case CMD_RESET:
  614. ResetMCU();
  615. break;
  616. case CMD_REQ:
  617. txrequest = rxdata.data[0];
  618. break;
  619. case CMD_CHONOFF:
  620. heater[ch].status.onoff = rxdata.data[0];
  621. SwitchHeating(ch, OFF);
  622. SwitchDrive(ch, OFF);
  623. break;
  624. case CMD_SETTEMP:
  625. heater[ch].tset = rxdata.data[0];
  626. break;
  627. case CMD_SETRANGE:
  628. heater[ch].gain = rxdata.data[0];
  629. heater[ch].shift = rxdata.data[1];
  630. SetGainData(ch, rxdata.data[0]);
  631. SetShiftData(ch, rxdata.data[1]);
  632. break;
  633. case CMD_SETVDRIVE:
  634. heater[ch].drive = rxdata.data[0];
  635. opamp[ch].drive = ((float)heater->drive / 25.76);
  636. break;
  637. case CMD_SWPRESET:
  638. heater[ch].preset = rxdata.data[0];
  639. LoadPreset(ch);
  640. SavePrefs();
  641. break;
  642. case CMD_LOADDATA:
  643. memcpy((uint8_t*)preset, (uint8_t*)rxdata.data, rxdata.len);
  644. SavePreset(ch);
  645. break;
  646. case CMD_HEATING:
  647. if(heater[ch].status.calib == CAL_MANUAL)
  648. heater[ch].status.heating = rxdata.data[0];
  649. break;
  650. case CMD_CALIBRATION:
  651. heater[ch].status.calib = rxdata.data[0];
  652. cal_tmin = rxdata.data[1];
  653. cal_tmax = rxdata.data[2];
  654. if(heater[ch].status.calib == CAL_MANUAL)
  655. ManualCalibration(ch);
  656. else if(heater[ch].status.calib == CAL_AUTO)
  657. AutoCalibration(ch);
  658. break;
  659. }
  660. }
  661. void LoadingScreen()
  662. {
  663. uint8_t c = 0xFF, i = 0, d = 0, btn = 0;
  664. do
  665. {
  666. _delay_ms(20);
  667. LCD_SetPos(i, 0);
  668. LCD_SendData(c);
  669. LCD_SetPos(15 - i, 1);
  670. LCD_SendData(c);
  671. if(++i > 15)
  672. {
  673. c ^= ~' ';
  674. i = 0;
  675. d++;
  676. }
  677. btn = ~((BTNPIN >> 4) | 0xF0);
  678. }
  679. while(btn || (d < 2));
  680. LCD_SendCmd(LCD_CLR);
  681. }
  682. int main()
  683. {
  684. uint8_t ch = CH0;
  685. uint8_t tmp = 0;
  686. uint8_t display = DISP_MAIN;
  687. btn_t button;
  688. menu_str *menu = (menu_str*)calloc(sizeof(menu_str), 1);
  689. memset(heater, 0x00, sizeof(heater));
  690. memset(opamp, 0x00, sizeof(opamp));
  691. memset(preset, 0x00, sizeof(preset));
  692. opamp[CH0].ch = heater[CH0].status.channel = CH0;
  693. opamp[CH1].ch = heater[CH1].status.channel = CH1;
  694. heater[CH0].tset = heater[CH1].tset = 25;
  695. stdout = &uart_stdout;
  696. init();
  697. LCD_Init();
  698. LoadingScreen();
  699. LoadPrefs();
  700. LoadPreset(CH0);
  701. LoadPreset(CH1);
  702. //SwitchPower(ON);
  703. CircuitDetect(CH0);
  704. CircuitDetect(CH1);
  705. sei();
  706. Transmit();
  707. while(1)
  708. {
  709. if(count)
  710. {
  711. UARTDataAvail();
  712. }
  713. if(txrequest)
  714. {
  715. Transmit();
  716. }
  717. if(heater[CH0].status.ocp || heater[CH1].status.ocp)
  718. {
  719. LCD_SetPos(0, 0);
  720. fprintf(&lcd_stdout, "ÇÀÙÈÒÀ ÏÎ ÒÎÊÓ!!");
  721. LCD_SetPos(0, 1);
  722. fprintf(&lcd_stdout, "ÍÀÆ.");
  723. LCD_SendData(0x00);
  724. fprintf(&lcd_stdout, " ÄËß ÑÁÐÎÑÀ");
  725. while(((BTNPIN >> 4) | 0xF0) != 0xF7);
  726. ResetMCU();
  727. }
  728. if(tick1)
  729. {
  730. /* ------------- MEASURING SECTION ----------------- */
  731. tick1 = 0;
  732. MAX_ReadData();
  733. tmp = ch;
  734. for(uint8_t ch = CH0; ch <= CH1; ch++)
  735. {
  736. if(CurrMeasure(ch) > CURR_MAX)
  737. {
  738. heater[ch].status.onoff = OFF;
  739. }
  740. SwitchHeating(ch, OFF);
  741. SwitchDrive(ch, OFF);
  742. _delay_ms(1);
  743. CircuitDetect(ch);
  744. TMeasure(ch);
  745. if(heater[ch].status.circuit == CIRC_OPEN)
  746. {
  747. heater[ch].status.onoff = OFF;
  748. }
  749. else if(heater[ch].status.circuit == CIRC_RES)
  750. {
  751. if((heater[ch].status.onoff == ON) && (heater[ch].tcouple < heater[ch].tset))
  752. {
  753. SwitchHeating(ch, ON);
  754. }
  755. else
  756. {
  757. SwitchHeating(ch, OFF);
  758. }
  759. }
  760. else
  761. {
  762. if((heater[ch].status.onoff == ON) && (heater[ch].tmeas < heater[ch].tset))
  763. {
  764. SwitchDrive(ch, ON);
  765. SwitchHeating(ch, ON);
  766. }
  767. else
  768. {
  769. SwitchDrive(ch, OFF);
  770. SwitchHeating(ch, OFF);
  771. }
  772. }
  773. }
  774. ch = tmp;
  775. } ////// if(tick1) end
  776. if(tick2)
  777. {
  778. /* ------------- DISPLAY SECTION ----------------- */
  779. tick2 = 0;
  780. if(display == DISP_MAIN)
  781. {
  782. LCD_SetPos(0, 0);
  783. fprintf(&lcd_stdout, "K%.1u #%.2u Tï=", ch + 1, heater[ch].preset);
  784. if(!heater[ch].status.couple)
  785. {
  786. fprintf(&lcd_stdout, "%.3d\x01", heater[ch].tcouple);
  787. }
  788. else
  789. {
  790. fprintf(&lcd_stdout, "--- ");
  791. }
  792. switch(heater[ch].status.circuit)
  793. {
  794. case CIRC_OPEN:
  795. LCD_SendData(SYM_OPEN);
  796. break;
  797. case CIRC_SHORT:
  798. LCD_SendData(SYM_SHORT);
  799. break;
  800. case CIRC_RES:
  801. LCD_SendData(SYM_RES);
  802. break;
  803. case CIRC_MOSFET:
  804. LCD_SendData(SYM_MOSFET);
  805. break;
  806. case CIRC_RES_DIODE:
  807. LCD_SendData(SYM_DIODE);
  808. break;
  809. case CIRC_DIODE:
  810. break;
  811. }
  812. LCD_SetPos(0, 1);
  813. fprintf(&lcd_stdout, "Tó=%.3u\x01 ", heater[ch].tset);
  814. if((heater[ch].status.circuit == CIRC_OPEN) || (heater[ch].status.circuit == CIRC_SHORT))
  815. {
  816. fprintf(&lcd_stdout, "ÎÒÊËÞ×.");
  817. }
  818. else if(heater[ch].status.circuit == CIRC_RES)
  819. {
  820. fprintf(&lcd_stdout, "I=%4.2fA", ((float)heater[ch].current) / 1000.0);
  821. }
  822. else
  823. {
  824. fprintf(&lcd_stdout, "Òí=%.3d\x01", heater[ch].tmeas);
  825. }
  826. if(heater[ch].status.onoff)
  827. {
  828. if(heater[ch].status.heating)
  829. {
  830. LCD_SendData(0xD9);
  831. }
  832. else
  833. {
  834. LCD_SendData(0xDA);
  835. }
  836. }
  837. else
  838. {
  839. LCD_SendData('-');
  840. }
  841. if(menu->set == 1)
  842. {
  843. if(menu->blink_cnt % 4 == 0)
  844. {
  845. if(menu->blink_cnt > 40)
  846. {
  847. menu->set = 0;
  848. menu->blink_cnt = 0;
  849. SavePrefs();
  850. }
  851. LCD_SetPos(3, 1);
  852. fprintf(&lcd_stdout, " ");
  853. }
  854. menu->blink_cnt++;
  855. }
  856. else if(menu->set == 2)
  857. {
  858. if(menu->blink_cnt % 4 == 0)
  859. {
  860. if(menu->blink_cnt > 40)
  861. {
  862. menu->set = 0;
  863. menu->blink_cnt = 0;
  864. SavePrefs();
  865. }
  866. LCD_SetPos(4, 0);
  867. fprintf(&lcd_stdout, " ");
  868. }
  869. menu->blink_cnt++;
  870. }
  871. if(button.pressed && !button.holded)
  872. {
  873. if(++button.holdcnt == 12)
  874. {
  875. button.holded = 1;
  876. btn_act = 1;
  877. }
  878. }
  879. }
  880. else if(display == DISP_VER)
  881. {
  882. LCD_SetPos(0, 0);
  883. fprintf(&lcd_stdout, "ÓÊÍ-2 09.09.2019");
  884. LCD_SetPos(0, 1);
  885. fprintf(&lcd_stdout, "Íàãàåâ Àëåêñàíäð");
  886. }
  887. //txrequest = REQ_MAINDATA;
  888. //Transmit();
  889. } ////// if(tick2) end
  890. /* ---------------- BUTTON SECTION --------------- */
  891. if(btn_act)
  892. {
  893. _delay_ms(20);
  894. btn_act = 0;
  895. button.code = ~((BTNPIN >> 4) | 0xF0);
  896. if((button.code != 0x00) && (!button.holded)) // Button down event
  897. {
  898. if(display == DISP_MAIN)
  899. {
  900. button.pressed = 1;
  901. button.released = 0;
  902. button.prev_code = button.code;
  903. switch(button.code)
  904. {
  905. case 0x01:
  906. menu->blink_cnt = 1;
  907. if(menu->set == 1)
  908. {
  909. heater[ch].tset -= (heater[ch].tset != 0);
  910. }
  911. else if(menu->set == 2)
  912. {
  913. heater[ch].preset -= (heater[ch].preset != 0);
  914. LoadPreset(ch);
  915. }
  916. else
  917. {
  918. ch = CH0;
  919. }
  920. break;
  921. case 0x02:
  922. menu->blink_cnt = 1;
  923. if(menu->set == 1)
  924. {
  925. heater[ch].tset += (heater[ch].tset != 150);
  926. }
  927. else if(menu->set == 2)
  928. {
  929. heater[ch].preset += (heater[ch].preset != 24);
  930. LoadPreset(ch);
  931. }
  932. else
  933. {
  934. ch = CH1;
  935. }
  936. break;
  937. case 0x03:
  938. LCD_SendCmd(LCD_CLR);
  939. display = DISP_VER;
  940. break;
  941. case 0x04:
  942. menu->set = (menu->set + 1) % 3;
  943. if(menu->set == 0)
  944. SavePrefs();
  945. menu->blink_cnt = 0;
  946. break;
  947. } ////// switch(btn_code) end
  948. } ////// if(display == ON) end
  949. }
  950. else if(button.code == 0) // Button up event
  951. {
  952. if(!button.holded)
  953. {
  954. display = DISP_MAIN;
  955. if(button.prev_code == 0x08)
  956. {
  957. heater[ch].status.onoff ^= 1;
  958. SwitchDrive(ch, OFF);
  959. SwitchHeating(ch, OFF);
  960. }
  961. }
  962. button.pressed = 0;
  963. button.released = 1;
  964. button.holded = 0;
  965. button.holdcnt = 0;
  966. }
  967. else // Button hold event
  968. {
  969. switch(button.code)
  970. {
  971. case 0x01:
  972. case 0x02:
  973. btn_act = 1;
  974. button.holded = 0;
  975. button.holdcnt--;
  976. break;
  977. case 0x04:
  978. menu->set = 0;
  979. AutoCalibration(ch);
  980. button.pressed = 0;
  981. button.holded = 0;
  982. button.holdcnt = 0;
  983. break;
  984. case 0x08:
  985. button.prev_code = 0;
  986. display = OFF;
  987. LCD_SendCmd(LCD_CLR);
  988. //btn_hold = 0;
  989. break;
  990. }
  991. }
  992. } ////// if(btn_act) end
  993. } ////// while(1) end
  994. } ////// main() end