Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.31 KB | None | 0 0
  1. * embedded_coms_boost.c
  2. *
  3. * Author: Steve Gunn & Klaus-Peter Zauner
  4. * Licence: This work is licensed under the Creative Commons Attribution License.
  5. * View this license at http://creativecommons.org/about/licenses/
  6. * Notes:
  7. * - Use with host_coms_boost.c
  8. *
  9. * - F_CPU must be defined to match the clock frequency
  10. *
  11. * - Compile with the options to enable floating point
  12. * numbers in printf():
  13. * -Wl,-u,vfprintf -lprintf_flt -lm
  14. *
  15. * - Pin assignment:
  16. * | Port | Pin | Use |
  17. * |------+-----+-----------------------------|
  18. * | A | PA0 | Voltage at load |
  19. * | D | PD0 | Host connection TX (orange) |
  20. * | D | PD1 | Host connection RX (yellow) |
  21. * | D | PD7 | PWM out to drive MOSFET |
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <avr/io.h>
  26. #include <util/delay.h>
  27. #include <math.h>
  28. #include <avr/interrupt.h>
  29. #include <string.h>
  30.  
  31. #include <stdlib.h>
  32.  
  33. #define BDRATE_BAUD 9600
  34. #define BUFFSIZE 20
  35.  
  36. #define ADCREF_V 3.3
  37. #define ADCMAXREAD 1023 /* 10 bit ADC */
  38.  
  39. /* Find out what value gives the maximum
  40. output voltage for your circuit:
  41. */
  42. #define PWM_DUTY_MAX 250 /* 94% duty cycle */
  43.  
  44. void init_stdio2uart0(void);
  45. int uputchar0(char c, FILE *stream);
  46. int ugetchar0(FILE *stream);
  47.  
  48. //static void increase_set(void);
  49. //static void decrease_set(void);
  50. //static void init_encoder(void);
  51.  
  52. //static void init_encoder(void) ;
  53. //static uint8_t read_encoder_state();
  54.  
  55. void init_adc(void);
  56. double v_load(void);
  57.  
  58. void init_UART0(void);
  59.  
  60.  
  61. int updatepid(void);
  62. int map (int x, int in_min, int in_max, int out_min, int out_max);
  63. void init_pwm(void);
  64. void pwm_duty(uint8_t x);
  65.  
  66. //////////////////////////////////////////////////////
  67. volatile float SETPOINT_V = 5; /* set point for compile time control */
  68.  
  69. volatile uint8_t SET_PWM = 100;
  70.  
  71. volatile uint16_t cnt = 0;
  72.  
  73. /* constants for PID */
  74. volatile const float Kp = 1.5;
  75. volatile const float Ki = 0.000009;
  76. volatile const float Kd = 0.000001;
  77.  
  78. /* Global Variables for PID */
  79. volatile float d_Temp = 0;
  80. volatile float i_Temp = 0;
  81. volatile float PWM_Temp = 200;
  82. volatile float err_value;
  83.  
  84.  
  85.  
  86. volatile int control = 1;
  87.  
  88. volatile float v_error = 0;
  89. volatile int adjusting = 0;
  90. /////////////// INPUT Section ////////////////////////
  91.  
  92. int main(void)
  93. {
  94. int prm;
  95. float set_temp;
  96. int res;
  97. char cmd[BUFFSIZE];
  98.  
  99.  
  100.  
  101. init_stdio2uart0();
  102. init_pwm();
  103. init_adc();
  104.  
  105. DDRB |= _BV(7);
  106. printf("\r\nIlMatto Coms Boost READY!\n");
  107.  
  108. printf("set voltage is currently %f \n", SETPOINT_V);
  109. TCCR1A = 0; // Sets timer 1 in CTC Mode 4
  110. TCCR1B = _BV(WGM12);
  111. TCCR1B = _BV(CS10); // We want to wait for the new duty cycle to take effect (prescaler 1024)
  112. OCR1A = 20; // But High precision achieved with timer
  113. TIMSK1 |= _BV(OCIE1A); // Enable interrupt
  114. /* enable global interrupts */
  115.  
  116. sei();
  117.  
  118. for(;;)
  119. {
  120.  
  121. res = scanf("%s %d", cmd, &prm);
  122. //printf("CMD was: \"%s\" with %d (%d)\r\n", cmd, prm, res);
  123. if ( res !=2)
  124. { // Error!
  125. scanf("%*s");
  126. printf( "error\n"); // Clear input buffer
  127. }
  128. else
  129. {
  130. TIMSK1 = 0;
  131. if (!strcmp("R", cmd))
  132. {
  133. // Disable interrupt to set manual duty
  134. printf("reading\r\n");
  135. printf( "%04d: ", cnt );
  136.  
  137.  
  138. printf( "voltage: %5.3f V\n", v_load() );
  139. //printf( "prm is : %d\n", prm);
  140.  
  141. cnt++;
  142. }
  143. else if (!strcmp("H", cmd))
  144. { // Disable interrupt to set manual duty
  145. //printf( "recieved value is: (%3d)\n", prm);
  146. SETPOINT_V = 18;
  147. }
  148. else if (!strcmp("L", cmd))
  149. {
  150. //printf( "recieved value is: %3d\n", prm);
  151. SETPOINT_V = 1;
  152. }
  153. else if (!strcmp("S", cmd))
  154. {
  155. set_temp = (float)(prm)/1000;
  156. // printf( "recieved value is: (%3d)\n", prm);
  157. if (set_temp > 18)
  158. {
  159. printf("voltage output limited 18v\r\n");
  160. printf("voltage output set to 18\n");
  161. prm = 18;
  162. }
  163. if (set_temp <=1)
  164. {
  165. printf("Minimum voltage output is 1.37v\r\n");
  166. printf("voltage output set to 1.37\n");
  167. }
  168. SETPOINT_V = set_temp;
  169.  
  170. }
  171. else if (!strcmp("C", cmd))
  172. {
  173.  
  174. //printf("changing to control method %d", prm);
  175. if (prm == 1 || prm == 0)
  176. {
  177. control = prm;
  178. }
  179. else
  180. {
  181. printf("invalid input, controller unchanged\n");
  182. }
  183. }
  184. else
  185. {
  186. printf( "error\n");
  187. break;
  188. }
  189. }
  190.  
  191. TIMSK1 |= _BV(OCIE1A);
  192. }
  193. }
  194.  
  195.  
  196.  
  197. ISR(TIMER1_COMPA_vect)
  198. {
  199. v_error = SETPOINT_V - v_load();
  200.  
  201. if (control == 1)
  202. {
  203. if (v_load() < SETPOINT_V )
  204. {
  205. SET_PWM ++;
  206. if (SET_PWM == 246)
  207. {
  208. SET_PWM = 245;
  209.  
  210.  
  211. }
  212. pwm_duty(SET_PWM); // Limited by PWM_DUTY_MAX
  213. }
  214. else
  215. {
  216. SET_PWM --;
  217. if (SET_PWM == 0)
  218. {
  219. SET_PWM = 1;
  220. }
  221. pwm_duty(SET_PWM);
  222. }
  223. }
  224. else
  225. {
  226. float iMax = 50;
  227. float iMin = 0;
  228.  
  229. float P_Term;
  230. float I_Term;
  231. float D_Term;
  232. int new_ADC_value;
  233. float PWM_Duty;
  234.  
  235. new_ADC_value = v_load();
  236.  
  237. err_value = (SETPOINT_V - new_ADC_value);
  238.  
  239. i_Temp += err_value;
  240.  
  241. if (i_Temp > iMax)
  242. {
  243. i_Temp = iMax;
  244. }
  245.  
  246. else if (i_Temp < iMin)
  247. {
  248. i_Temp = iMin;
  249. }
  250.  
  251. P_Term = Kp * err_value;
  252. I_Term = Ki * i_Temp;
  253. D_Term = Kd * (d_Temp - err_value);
  254. d_Temp = err_value;
  255.  
  256. PWM_Duty = PWM_Temp + (P_Term + I_Term + D_Term);
  257.  
  258. if (PWM_Duty > 250)
  259. {
  260. PWM_Duty = 245;
  261. }
  262. else if (PWM_Duty < 0)
  263. {
  264. PWM_Duty = 0;
  265. }
  266. pwm_duty(PWM_Duty);
  267.  
  268. PWM_Temp = PWM_Duty;
  269.  
  270. }
  271.  
  272. /*if(v_error <= 0.2) // If the difference of voltage is significant - set the LED high
  273. {
  274. PORTB |= _BV(7);
  275. adjusting = 0;
  276. }
  277.  
  278. else // If not, then low
  279. {
  280.  
  281. PORTB &= !_BV(7);
  282. adjusting = 1;
  283. }*/
  284. }
  285.  
  286. int map(int x, int in_min, int in_max, int out_min, int out_max)
  287. {
  288. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  289. }
  290.  
  291. int uputchar0(char c, FILE *stream)
  292. {
  293. if (c == '\n') uputchar0('\r', stream);
  294. while (!(UCSR0A & _BV(UDRE0)));
  295. UDR0 = c;
  296. return c;
  297. }
  298.  
  299. int ugetchar0(FILE *stream)
  300. {
  301. while(!(UCSR0A & _BV(RXC0)));
  302. return UDR0;
  303. }
  304.  
  305. void init_stdio2uart0(void)
  306. {
  307. /* Configure UART0 baud rate, one start bit, 8-bit, no parity and one stop bit */
  308. UBRR0H = (F_CPU/(BDRATE_BAUD*16L)-1) >> 8;
  309. UBRR0L = (F_CPU/(BDRATE_BAUD*16L)-1);
  310. UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  311. UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
  312.  
  313. /* Setup new streams for input and output */
  314. static FILE uout = FDEV_SETUP_STREAM(uputchar0, NULL, _FDEV_SETUP_WRITE);
  315. static FILE uin = FDEV_SETUP_STREAM(NULL, ugetchar0, _FDEV_SETUP_READ);
  316.  
  317. /* Redirect all standard streams to UART0 */
  318. stdout = &uout;
  319. stderr = &uout;
  320. stdin = &uin;
  321. }
  322.  
  323.  
  324. ISR(INT0_vect)
  325. {
  326. SETPOINT_V = 3;
  327. printf( "Set Voltage =%02d\n", SETPOINT_V );
  328.  
  329. }
  330.  
  331. void init_adc (void)
  332. {
  333. /* REFSx = 0 : Select AREF as reference
  334. * ADLAR = 0 : Right shift result
  335. * MUXx = 0 : Default to channel 0
  336. */
  337. ADMUX = 0x00;
  338. /* ADEN = 1 : Enable the ADC
  339. * ADPS2 = 1 : Configure ADC prescaler
  340. * ADPS1 = 1 : F_ADC = F_CPU / 64
  341. * ADPS0 = 0 : = 187.5 kHz
  342. */
  343. ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1);
  344. }
  345.  
  346.  
  347. double v_load(void)
  348. {
  349. uint16_t adcread;
  350.  
  351. /* Start single conversion */
  352. ADCSRA |= _BV ( ADSC );
  353. /* Wait for conversion to complete */
  354. while ( ADCSRA & _BV ( ADSC ) );
  355. adcread = ADC;
  356.  
  357.  
  358. return (double) ((adcread * ADCREF_V/ADCMAXREAD)/0.176);
  359. }
  360.  
  361.  
  362.  
  363. void init_pwm(void)
  364. {
  365. /* TIMER 2 */
  366. DDRD |= _BV(PD6); /* PWM out */
  367. DDRD |= _BV(PD7); /* inv. PWM out */
  368.  
  369.  
  370. TCCR2A = _BV(WGM20) | /* fast PWM/MAX */
  371. _BV(WGM21) | /* fast PWM/MAX */
  372. _BV(COM2A1); /* A output */
  373. TCCR2B = _BV(CS20); /* no prescaling */
  374. }
  375.  
  376.  
  377. /* Adjust PWM duty cycle
  378. Keep in mind this is not monotonic
  379. a 100% duty cycle has no switching
  380. and consequently will not boost.
  381. */
  382. void pwm_duty(uint8_t x)
  383. {
  384. x = x > PWM_DUTY_MAX ? PWM_DUTY_MAX : x;
  385.  
  386.  
  387. OCR2A = x;
  388. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement