Commit ccb57fb5 authored by Pontus Giselsson's avatar Pontus Giselsson
Browse files

P-Current control sampling rate 0.5ms

parent 316030e8
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
avr-gcc -mmcu=atmega16 -g -Wall -o current_control current_control.c
\ No newline at end of file
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
/*********************************************
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) {}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment