Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- * embedded_coms_boost.c
- *
- * Author: Steve Gunn & Klaus-Peter Zauner
- * Licence: This work is licensed under the Creative Commons Attribution License.
- * View this license at http://creativecommons.org/about/licenses/
- * Notes:
- * - Use with host_coms_boost.c
- *
- * - F_CPU must be defined to match the clock frequency
- *
- * - Compile with the options to enable floating point
- * numbers in printf():
- * -Wl,-u,vfprintf -lprintf_flt -lm
- *
- * - Pin assignment:
- * | Port | Pin | Use |
- * |------+-----+-----------------------------|
- * | A | PA0 | Voltage at load |
- * | D | PD0 | Host connection TX (orange) |
- * | D | PD1 | Host connection RX (yellow) |
- * | D | PD7 | PWM out to drive MOSFET |
- */
- #include <stdio.h>
- #include <avr/io.h>
- #include <util/delay.h>
- #include <math.h>
- #include <avr/interrupt.h>
- #include <string.h>
- #include <stdlib.h>
- #define BDRATE_BAUD 9600
- #define BUFFSIZE 20
- #define ADCREF_V 3.3
- #define ADCMAXREAD 1023 /* 10 bit ADC */
- /* Find out what value gives the maximum
- output voltage for your circuit:
- */
- #define PWM_DUTY_MAX 250 /* 94% duty cycle */
- void init_stdio2uart0(void);
- int uputchar0(char c, FILE *stream);
- int ugetchar0(FILE *stream);
- //static void increase_set(void);
- //static void decrease_set(void);
- //static void init_encoder(void);
- //static void init_encoder(void) ;
- //static uint8_t read_encoder_state();
- void init_adc(void);
- double v_load(void);
- void init_UART0(void);
- int updatepid(void);
- int map (int x, int in_min, int in_max, int out_min, int out_max);
- void init_pwm(void);
- void pwm_duty(uint8_t x);
- //////////////////////////////////////////////////////
- volatile float SETPOINT_V = 5; /* set point for compile time control */
- volatile uint8_t SET_PWM = 100;
- volatile uint16_t cnt = 0;
- /* constants for PID */
- volatile const float Kp = 1.5;
- volatile const float Ki = 0.000009;
- volatile const float Kd = 0.000001;
- /* Global Variables for PID */
- volatile float d_Temp = 0;
- volatile float i_Temp = 0;
- volatile float PWM_Temp = 200;
- volatile float err_value;
- volatile int control = 1;
- volatile float v_error = 0;
- volatile int adjusting = 0;
- /////////////// INPUT Section ////////////////////////
- int main(void)
- {
- int prm;
- float set_temp;
- int res;
- char cmd[BUFFSIZE];
- init_stdio2uart0();
- init_pwm();
- init_adc();
- DDRB |= _BV(7);
- printf("\r\nIlMatto Coms Boost READY!\n");
- printf("set voltage is currently %f \n", SETPOINT_V);
- TCCR1A = 0; // Sets timer 1 in CTC Mode 4
- TCCR1B = _BV(WGM12);
- TCCR1B = _BV(CS10); // We want to wait for the new duty cycle to take effect (prescaler 1024)
- OCR1A = 20; // But High precision achieved with timer
- TIMSK1 |= _BV(OCIE1A); // Enable interrupt
- /* enable global interrupts */
- sei();
- for(;;)
- {
- res = scanf("%s %d", cmd, &prm);
- //printf("CMD was: \"%s\" with %d (%d)\r\n", cmd, prm, res);
- if ( res !=2)
- { // Error!
- scanf("%*s");
- printf( "error\n"); // Clear input buffer
- }
- else
- {
- TIMSK1 = 0;
- if (!strcmp("R", cmd))
- {
- // Disable interrupt to set manual duty
- printf("reading\r\n");
- printf( "%04d: ", cnt );
- printf( "voltage: %5.3f V\n", v_load() );
- //printf( "prm is : %d\n", prm);
- cnt++;
- }
- else if (!strcmp("H", cmd))
- { // Disable interrupt to set manual duty
- //printf( "recieved value is: (%3d)\n", prm);
- SETPOINT_V = 18;
- }
- else if (!strcmp("L", cmd))
- {
- //printf( "recieved value is: %3d\n", prm);
- SETPOINT_V = 1;
- }
- else if (!strcmp("S", cmd))
- {
- set_temp = (float)(prm)/1000;
- // printf( "recieved value is: (%3d)\n", prm);
- if (set_temp > 18)
- {
- printf("voltage output limited 18v\r\n");
- printf("voltage output set to 18\n");
- prm = 18;
- }
- if (set_temp <=1)
- {
- printf("Minimum voltage output is 1.37v\r\n");
- printf("voltage output set to 1.37\n");
- }
- SETPOINT_V = set_temp;
- }
- else if (!strcmp("C", cmd))
- {
- //printf("changing to control method %d", prm);
- if (prm == 1 || prm == 0)
- {
- control = prm;
- }
- else
- {
- printf("invalid input, controller unchanged\n");
- }
- }
- else
- {
- printf( "error\n");
- break;
- }
- }
- TIMSK1 |= _BV(OCIE1A);
- }
- }
- ISR(TIMER1_COMPA_vect)
- {
- v_error = SETPOINT_V - v_load();
- if (control == 1)
- {
- if (v_load() < SETPOINT_V )
- {
- SET_PWM ++;
- if (SET_PWM == 246)
- {
- SET_PWM = 245;
- }
- pwm_duty(SET_PWM); // Limited by PWM_DUTY_MAX
- }
- else
- {
- SET_PWM --;
- if (SET_PWM == 0)
- {
- SET_PWM = 1;
- }
- pwm_duty(SET_PWM);
- }
- }
- else
- {
- float iMax = 50;
- float iMin = 0;
- float P_Term;
- float I_Term;
- float D_Term;
- int new_ADC_value;
- float PWM_Duty;
- new_ADC_value = v_load();
- err_value = (SETPOINT_V - new_ADC_value);
- i_Temp += err_value;
- if (i_Temp > iMax)
- {
- i_Temp = iMax;
- }
- else if (i_Temp < iMin)
- {
- i_Temp = iMin;
- }
- P_Term = Kp * err_value;
- I_Term = Ki * i_Temp;
- D_Term = Kd * (d_Temp - err_value);
- d_Temp = err_value;
- PWM_Duty = PWM_Temp + (P_Term + I_Term + D_Term);
- if (PWM_Duty > 250)
- {
- PWM_Duty = 245;
- }
- else if (PWM_Duty < 0)
- {
- PWM_Duty = 0;
- }
- pwm_duty(PWM_Duty);
- PWM_Temp = PWM_Duty;
- }
- /*if(v_error <= 0.2) // If the difference of voltage is significant - set the LED high
- {
- PORTB |= _BV(7);
- adjusting = 0;
- }
- else // If not, then low
- {
- PORTB &= !_BV(7);
- adjusting = 1;
- }*/
- }
- int map(int x, int in_min, int in_max, int out_min, int out_max)
- {
- return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
- }
- int uputchar0(char c, FILE *stream)
- {
- if (c == '\n') uputchar0('\r', stream);
- while (!(UCSR0A & _BV(UDRE0)));
- UDR0 = c;
- return c;
- }
- int ugetchar0(FILE *stream)
- {
- while(!(UCSR0A & _BV(RXC0)));
- return UDR0;
- }
- void init_stdio2uart0(void)
- {
- /* Configure UART0 baud rate, one start bit, 8-bit, no parity and one stop bit */
- UBRR0H = (F_CPU/(BDRATE_BAUD*16L)-1) >> 8;
- UBRR0L = (F_CPU/(BDRATE_BAUD*16L)-1);
- UCSR0B = _BV(RXEN0) | _BV(TXEN0);
- UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
- /* Setup new streams for input and output */
- static FILE uout = FDEV_SETUP_STREAM(uputchar0, NULL, _FDEV_SETUP_WRITE);
- static FILE uin = FDEV_SETUP_STREAM(NULL, ugetchar0, _FDEV_SETUP_READ);
- /* Redirect all standard streams to UART0 */
- stdout = &uout;
- stderr = &uout;
- stdin = &uin;
- }
- ISR(INT0_vect)
- {
- SETPOINT_V = 3;
- printf( "Set Voltage =%02d\n", SETPOINT_V );
- }
- void init_adc (void)
- {
- /* REFSx = 0 : Select AREF as reference
- * ADLAR = 0 : Right shift result
- * MUXx = 0 : Default to channel 0
- */
- ADMUX = 0x00;
- /* ADEN = 1 : Enable the ADC
- * ADPS2 = 1 : Configure ADC prescaler
- * ADPS1 = 1 : F_ADC = F_CPU / 64
- * ADPS0 = 0 : = 187.5 kHz
- */
- ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1);
- }
- double v_load(void)
- {
- uint16_t adcread;
- /* Start single conversion */
- ADCSRA |= _BV ( ADSC );
- /* Wait for conversion to complete */
- while ( ADCSRA & _BV ( ADSC ) );
- adcread = ADC;
- return (double) ((adcread * ADCREF_V/ADCMAXREAD)/0.176);
- }
- void init_pwm(void)
- {
- /* TIMER 2 */
- DDRD |= _BV(PD6); /* PWM out */
- DDRD |= _BV(PD7); /* inv. PWM out */
- TCCR2A = _BV(WGM20) | /* fast PWM/MAX */
- _BV(WGM21) | /* fast PWM/MAX */
- _BV(COM2A1); /* A output */
- TCCR2B = _BV(CS20); /* no prescaling */
- }
- /* Adjust PWM duty cycle
- Keep in mind this is not monotonic
- a 100% duty cycle has no switching
- and consequently will not boost.
- */
- void pwm_duty(uint8_t x)
- {
- x = x > PWM_DUTY_MAX ? PWM_DUTY_MAX : x;
- OCR2A = x;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement