diff --git a/linear_pendulum_2009/avr/current_control.c b/linear_pendulum_2009/avr/current_control.c index 70205f14b45bb4309bf823757898d116314e6c25..8f5c2200018e091efb9a6ddaefa71212ed38bf65 100644 --- a/linear_pendulum_2009/avr/current_control.c +++ b/linear_pendulum_2009/avr/current_control.c @@ -15,11 +15,25 @@ #include <avr/interrupt.h> #include <inttypes.h> -volatile int16_t ref = 20; + +// reference generation variables +volatile int16_t ref = 200; volatile int16_t refCount = 0; volatile int8_t refFlag = 0; + + + +// control variables +volatile unsigned char lbyte,hbyte; +volatile int16_t result; +volatile int16_t ctrl; +volatile int16_t ctrl_out; +volatile int16_t temp; volatile uint8_t alt = 1; +volatile uint8_t low, high; + + /* Routine used to set the red LED */ void setLED(uint8_t on) @@ -46,7 +60,8 @@ static void putchar(unsigned char ch) /* Interrupt service routine for handling incoming bytes on the serial port might be needed to catch incoming bytes */ SIGNAL(SIG_UART_RECV){} -/* Read 10-bit input using the AD converter */ + + static inline int16_t readInput() { uint8_t low, high; ADCSRA |= 0x40; @@ -55,7 +70,7 @@ static inline int16_t readInput() { high = ADCH; return ((high<<8) | low) - 512; } - + /* Write 8-bit output using the PWM-generator */ static inline void writeOutput(int16_t val) { @@ -68,76 +83,48 @@ static inline void writeOutput(int16_t val) { OCR1BH = 0; //(unsigned char) (val&0xff00); OCR1BL = (unsigned char) (val&0x00ff); } - - //unsigned char lbyte,hbyte; - //hbyte = ((val & 0xff00)>>8); //Get ADC result high byte - //lbyte = ((val & 0x00ff)); //Get ADC result low byte - - //putchar(hbyte); - //putchar(lbyte); } -/* Periodic timer interrupt */ -SIGNAL(SIG_OUTPUT_COMPARE2) + +/* Interrupt when AD-conversion completes */ +SIGNAL(SIG_ADC) { - + setPA4(1); - // PORTA &= 0xef; - unsigned char lbyte,hbyte; - int16_t result; - int16_t ctrl; - int16_t ctrl_out; - int16_t temp; + // Read input + low = inp(ADCL); + high = inp(ADCH); + result = ((high<<8) | low) - 512; - setPA4(alt); - - result = readInput(); - - setPA4(0); - + // Scale incoming current measurement result = result*3; //!!!!!!!!!!!!!!!!!!!!!!! - // Compensate for offset in measurements + // Scale incoming current measurement // result += 13; - - //hbyte = (((ref-result) & 0xff00)>>8); //Get ADC result high byte - //lbyte = (((ref-result) & 0x00ff)); //Get ADC result low byte - - // Transmit data - //putchar(hbyte); //high byte - //putchar(lbyte); //low byte - - //hbyte = ((result & 0xff00)>>8); //Get ADC result high byte - //lbyte = ((result & 0x00ff)); //Get ADC result low byte - - // Transmit data - //putchar(hbyte); //high byte - //putchar(lbyte); //low byte - - // control + + //control ctrl = ref-result; ctrl = ((ctrl + (1<< 2)) >> 3); //saturation/rounding to 8 bit - if (ctrl > 127) - ctrl_out = 127; - else if (ctrl < -128) - ctrl_out = -128; + if (ctrl > 511) + ctrl_out = 511; + else if (ctrl < -511) + ctrl_out = -511; else ctrl_out = ctrl; - - //writeOutput(ctrl_out); - writeOutput(ref); - - - - temp = (int16_t) ctrl_out; - hbyte = ((temp & 0xff00)>>8); //Get ADC result high byte - lbyte = ((temp & 0x00ff)); //Get ADC result low byte - putchar(hbyte); - putchar(lbyte); - + + + // write output + if (ctrl_out < 0) { + PORTC = 0x80+(PORTC & 0x7F); + OCR1BL = (unsigned char) (-ctrl_out); + } else { + PORTC = (PORTC & 0x7F); + OCR1BL = (unsigned char) (ctrl_out); + } + setPA4(0); } @@ -186,8 +173,8 @@ int main() outp(0x10,DDRA); // test pin output /* Timer section */ - // Enable TCNT2 (timer2) compare match interrupts, and timer0 overflow interrupts - outp(BV(OCIE2)|BV(TOIE0),TIMSK); + // Enable timer0 overflow interrupts + outp(BV(TOIE0),TIMSK); /* Timer 1, 8 bit fast PWM no prescaling -> h_pwm=17.35 micros */ outp(BV(COM1A1)|BV(COM1B1)|BV(WGM10),TCCR1A); @@ -203,10 +190,10 @@ int main() /* Timer 2 (control loop), prescaler 256, clear on compare match (28), -> h = 0.5 ms */ - outp(BV(WGM21)|BV(CS22)|BV(CS21),TCCR2); - outp(28,OCR2); + // outp(BV(WGM21)|BV(CS22)|BV(CS21),TCCR2); + //outp(28,OCR2); /* Reset timer 2 */ - outp(0,TCNT2); + //outp(0,TCNT2); /* Timer 0 for reference generation, prescaler = 1024 periodic h = ? */ outp(BV(CS02)|BV(CS00),TCCR0); @@ -222,13 +209,8 @@ int main() /* AREF (AREF is 5V) pin external capacitor, MUX0 for current, MUX3?? for pendulum angle */ outp(BV(REFS0)|BV(MUX0),ADMUX); - // Enable ADC interrupts, start first conversion (what do adps0-2 do), prescaler 128 - // outp(BV(ADEN)|BV(ADSC)|BV(ADPS2)|BV(ADPS1)|BV(ADPS0),ADCSRA); - // Enable ADC interrupts, start first conversion (what do adps0-2 do), prescaler 8 - // outp(BV(ADEN)|BV(ADSC)|BV(ADPS1)|BV(ADPS0),ADCSRA); - - // Enable ADC interrupts, start first conversion (what do adps0-2 do), prescaler 64 - outp(BV(ADEN)|BV(ADSC)|BV(ADPS2)|BV(ADPS1),ADCSRA); + // Enable ADC interrupts, start first conversion (what do adps0-2 do), prescaler 32 + outp(BV(ADEN)|BV(ADATE)|BV(ADSC)|BV(ADIE)|BV(ADPS2)|BV(ADPS0),ADCSRA); // outp(BV(ADEN)|BV(ADSC),ADCSRA);