diff --git a/linear_pendulum_2009/avr/Makefile b/linear_pendulum_2009/avr/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..91fe37a78cda4bb5a89de1e7998ec604d9a2c05d --- /dev/null +++ b/linear_pendulum_2009/avr/Makefile @@ -0,0 +1,81 @@ +PROJECT=current_control +CHIP=atmega16 + +ARCH=avr +AVRSOURCE= +AVRAUTO=compiled/$(ARCH)/ +AVRARCH=compiled/$(ARCH)/ +LIB_TARGET=$(AVRARCH)lib$(TARGET).a + +CC=$(ARCH)-gcc +CXX=$(ARCH)-gcc +CCFLAGS=-mmcu=$(CHIP) -O5 -I. -I$(AVRAUTO) +AS=$(ARCH)-as +ASFLAGS=-mmcu=$(CHIP) +AR=$(ARCH)-ar +LD=$(ARCH)-ld +OBJDUMP=$(ARCH)-objdump +LDFLAGS= -T $(CHIP).link + +all: $(AVRARCH)$(PROJECT) + +$(LIB_TARGET)(%.o): $(AVRSOURCE)%.c Makefile + $(CC) $(CCFLAGS) -c -o $(AVRARCH)$(%) -I$(AVRSOURCE) -I$(AVRAUTO) $(<) + $(AR) r $(@) $(AVRARCH)$(%) + rm $(AVRARCH)$(%) + +$(LIB_TARGET)(%.o): $(AVRSOURCE)%.cc Makefile + $(CXX) $(CCFLAGS) -c -o $(AVRARCH)$(%) -I$(AVRSOURCE) -I$(AVRAUTO) $(<) + $(AR) r $(@) $(AVRARCH)$(%) + rm $(AVRARCH)$(%) + +$(LIB_TARGET)(%.o): $(AVRSOURCE)%.s Makefile + $(AS) $(ASFLAGS) -o $(AVRARCH)$(%) $(AVRSOURCE)$(*).s + $(AR) r $(@) $(AVRARCH)$(%) + rm $(AVRARCH)$(%) + +$(AVRARCH)%.o: $(AVRSOURCE)%.s Makefile + $(AS) $(ASFLAGS) -o $@ $(AVRSOURCE)$(*).s + +$(AVRARCH)%.o: $(AVRSOURCE)%.c Makefile + $(CC) $(CCFLAGS) -c -o $@ -I. -I$(AVRAUTO) $< + + +$(AVRARCH)%: $(AVRARCH)%.o Makefile + $(CC) $(CCFLAGS) -o $@ $< -lm + +$(AVRARCH)%.sr: all $(AVRARCH)% + avr-objcopy -O srec $(AVRARCH)/$(*) $@ + +%.sr: $(AVRARCH)%.sr + @/bin/true + +%.load: compiled/avr/%.sr +# /work/andersb/atmel/uisp/uisp-0.2b/src/uisp \ +# -dno-poll -dstk200 --erase --upload if=$(AVRARCH)/$(*).sr + uisp \ + -dprog=stk200 \ + --erase \ + --upload if=compiled/avr/$*.sr + +%.load.stk500: compiled/avr/%.sr + uisp \ + -dprog=stk500 \ + --erase \ + --upload if=compiled/avr/$*.sr + +%.dump: all $(AVRARCH)/% + $(OBJDUMP) -D $(AVRARCH)/$(*) + +$(AVRARCH)fuse.sr: fuse.s + avr-gcc -o $(AVRARCH)fuse.o -c fuse.s + avr-objcopy -O srec $(AVRARCH)fuse.o $(AVRARCH)fuse.sr + +fuse.load: $(AVRARCH)fuse.sr + uisp \ + -dprog=stk200 \ + --erase \ + --segment=fuse \ + --upload if=compiled/avr/fuse.sr + +load.stk500: $(PROJECT).load.stk500 \ No newline at end of file diff --git a/linear_pendulum_2009/avr/compile.sh b/linear_pendulum_2009/avr/compile.sh new file mode 100755 index 0000000000000000000000000000000000000000..2fdb97c3223e09e8343c5c6d0d78ce3c3dfc777d --- /dev/null +++ b/linear_pendulum_2009/avr/compile.sh @@ -0,0 +1 @@ +avr-gcc -mmcu=atmega16 -g -Wall -o current_control current_control.c \ No newline at end of file diff --git a/linear_pendulum_2009/avr/compileUpload.sh b/linear_pendulum_2009/avr/compileUpload.sh new file mode 100755 index 0000000000000000000000000000000000000000..e97cfdfa62c342c42bb1305d2a7bf9a7c07d00fd --- /dev/null +++ b/linear_pendulum_2009/avr/compileUpload.sh @@ -0,0 +1,3 @@ +avr-gcc -mmcu=atmega16 -g -Wall -o current_control current_control.c +avr-objcopy -Osrec current_control current_control.sr +uisp -dprog=stk200 --erase --upload if=current_control.sr \ No newline at end of file diff --git a/linear_pendulum_2009/avr/current_control b/linear_pendulum_2009/avr/current_control new file mode 100755 index 0000000000000000000000000000000000000000..1236802cc738412d44badbf6f24556b10cfd4b38 Binary files /dev/null and b/linear_pendulum_2009/avr/current_control differ diff --git a/linear_pendulum_2009/avr/current_control.c b/linear_pendulum_2009/avr/current_control.c new file mode 100644 index 0000000000000000000000000000000000000000..70205f14b45bb4309bf823757898d116314e6c25 --- /dev/null +++ b/linear_pendulum_2009/avr/current_control.c @@ -0,0 +1,247 @@ +/********************************************* + + Current regulation - Aleks Ponjavic 18/09/07 + for LTH - reglerteknik + + Note that the voltage is actually a duty + cycle for the PWM. The PWM is running at + 12V with a duty cycle set by a 10bit value + +*********************************************/ + +//#include <math.h> //Only include if sin will be used, takes up memory! +#include <avr/io.h> +#include <avr/signal.h> +#include <avr/interrupt.h> +#include <inttypes.h> + +volatile int16_t ref = 20; +volatile int16_t refCount = 0; +volatile int8_t refFlag = 0; +volatile uint8_t alt = 1; + + +/* Routine used to set the red LED */ +void setLED(uint8_t on) +{ + if (on) PORTB &= 0x7f; //Turn on + else PORTB |= 0x80; //Turn off +} + +/* Routine used to set pin PD7 */ +void setPA4(uint8_t on) +{ + if (on == 0) PORTA &= 0xef; //Turn off + else PORTA |= 0x10; //Turn on +} + +/* Routine used to transmit bytes on the serial port */ +static void putchar(unsigned char ch) +{ + while ((inp(UCSRA) & 0x20) == 0) {}; + outp(ch, UDR); + while ((inp(UCSRA) & 0x20) == 0) {}; +} + +/* 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; + while (ADCSRA & 0x40); + low = ADCL; + high = ADCH; + return ((high<<8) | low) - 512; +} + + +/* Write 8-bit output using the PWM-generator */ +static inline void writeOutput(int16_t val) { + if (val < 0) { + PORTC = 0x80+(PORTC & 0x7F); + OCR1BH = 0; //(unsigned char) (-val)&0xff00; + OCR1BL = (unsigned char) (-val)&0x00ff; + } else { + PORTC = (PORTC & 0x7F); + 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) +{ + + + // PORTA &= 0xef; + unsigned char lbyte,hbyte; + int16_t result; + int16_t ctrl; + int16_t ctrl_out; + int16_t temp; + + setPA4(alt); + + result = readInput(); + + setPA4(0); + + result = result*3; //!!!!!!!!!!!!!!!!!!!!!!! + + // Compensate for offset in measurements + // 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 + 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; + 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); + +} + + +/* reference square- or triangle wave generator with timer 0 */ +SIGNAL(SIG_OVERFLOW0) { + int8_t rectangle = 1; + refCount++; + if (rectangle == 1) { + if (refFlag == 0) { + if (refCount == 10) { + refFlag = 1; + ref = -ref; + refCount = 0; + } + } else { + if (refCount == 20) { + ref = -ref; + refCount = 0; + } + } + } else { + if (refCount <= 400) { // ref*2 + ref -= 1; + } else { + ref += 1; + } + if (refCount == 800) { // ref*4 + refCount = 0; + } + } +} + + +int main() +{ + int i,j; + + //Port directions + outp(0x80,PORTB); // LED off + outp(0x80,DDRB); // output on LED + outp(0x08,PORTC); // pull up on overtemp signals + outp(0xa0,DDRC); // output on dir and brake + outp(0x80,PORTD); // pull up on reset switch + outp(0x10,DDRD); // output on pwm for motor 1 + + outp(0x10,DDRA); // test pin output + + /* Timer section */ + // Enable TCNT2 (timer2) compare match interrupts, and timer0 overflow interrupts + outp(BV(OCIE2)|BV(TOIE0),TIMSK); + + /* Timer 1, 8 bit fast PWM no prescaling -> h_pwm=17.35 micros */ + outp(BV(COM1A1)|BV(COM1B1)|BV(WGM10),TCCR1A); + // Fast PWM + // outp(BV(WGM12)|BV(CS10),TCCR1B); + // Phase and frequency correct pwm + outp(BV(CS10),TCCR1B); + /* Reset Timer1*/ + + //outp(0x00,TCNT1H); // Reset TCNT1 high + //outp(0x00,TCNT1L); // Reset TCNT1 low + + + + /* 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); + /* Reset timer 2 */ + outp(0,TCNT2); + + /* Timer 0 for reference generation, prescaler = 1024 periodic h = ? */ + outp(BV(CS02)|BV(CS00),TCCR0); + + //Serial communication + outp(0x00, UCSRA); // USART: + outp(0x98, UCSRB); // USART: RxIntEnable|RxEnable|TxEnable + outp(0x86, UCSRC); // USART: 8bit, no parity + outp(0x00, UBRRH); // USART: 115200 @ 14.7456MHz + outp(7,UBRRL); // USART: 115200 @ 14.7456MHz + + + /* 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); + + // outp(BV(ADEN)|BV(ADSC),ADCSRA); + + /* Wait a little bit, probably not needed...*/ + int tmp; + for(i=0;i<2000;i++) + for(j=0;j<400;j++) + tmp = j*j*j; + + + //Enable interrupts + sei(); + + // loop + while (1) {} +}