Difference between revisions of "AVR Code"
From Just in Time
m |
|||
Line 15: | Line 15: | ||
#define HALFSTEPS | #define HALFSTEPS | ||
− | #define waitTime 43200 // 12 * 3600 | + | //#define waitTime 43200 // 12 * 3600 |
− | //#define waitTime 60 | + | //#define waitTime 43380 // 12 * 3600 + 3 * 60 |
+ | #define waitTime 40 | ||
− | // | + | // define delays that are caused by mechanical construction |
− | #define | + | // it takes about 30 seconds from starting the stop-action before the pendulum has actually stopped |
− | #define | + | #define stopDelay 30 // in seconds |
+ | #define startDelay 3 // in seconds | ||
#define soft_reset() \ | #define soft_reset() \ | ||
Line 60: | Line 62: | ||
#ifdef HALFSTEPS | #ifdef HALFSTEPS | ||
− | #define | + | #define almostStop 412 |
#define totalStop 160 | #define totalStop 160 | ||
#define stopSpeed 200 | #define stopSpeed 200 | ||
#else | #else | ||
− | #define | + | #define almostStop 825 |
#define totalStop 350 | #define totalStop 350 | ||
#define stopSpeed 100 | #define stopSpeed 100 | ||
Line 100: | Line 102: | ||
uint16_t *addr; | uint16_t *addr; | ||
addr = (uint16_t *)0x1f0; | addr = (uint16_t *)0x1f0; | ||
− | |||
− | |||
eeprom_write_word(addr,totalSteps); | eeprom_write_word(addr,totalSteps); | ||
} | } | ||
Line 172: | Line 172: | ||
} | } | ||
− | void | + | void stopTime() |
{ | { | ||
− | // | + | // this function stops the Pendulum |
if(side == LEFT) | if(side == LEFT) | ||
{ | { | ||
− | for(uint16_t q=0;q< | + | for(uint16_t q=0;q<almostStop;q++) // bring to almostStop position from left side |
{ | { | ||
stepRight(); | stepRight(); | ||
Line 190: | Line 190: | ||
if(side == RIGHT) | if(side == RIGHT) | ||
{ | { | ||
− | for(uint16_t q=0;q< | + | for(uint16_t q=0;q<almostStop;q++) // bring to almostStop position from right side |
{ | { | ||
stepLeft(); | stepLeft(); | ||
Line 203: | Line 203: | ||
} | } | ||
− | void | + | void startTime() |
{ | { | ||
− | // | + | // start the pendulum with stepper |
if(side == LEFT) | if(side == LEFT) | ||
{ | { | ||
Line 216: | Line 216: | ||
} | } | ||
− | void | + | void waitForSecondsPassedReset() |
{ | { | ||
− | // | + | // wait until the ISR has reset the secondsPassed bool to avoid premature triggering |
while(!secondsPassedReset); | while(!secondsPassedReset); | ||
secondsPassedReset = 0; | secondsPassedReset = 0; | ||
Line 224: | Line 224: | ||
− | void | + | void waitForStartTijd() |
{ | { | ||
− | while(secondsPassed < waitTime - | + | while(secondsPassed < waitTime - startDelay) |
{ | { | ||
checkSwitches(); | checkSwitches(); | ||
} | } | ||
− | + | waitForSecondsPassedReset(); // if the ISR hasn't reset the bool, the next phase would trigger immediately | |
} | } | ||
− | void | + | void waitForStopTijd() |
{ | { | ||
− | while(secondsPassed < waitTime - | + | while(secondsPassed < waitTime - stopDelay) |
{ | { | ||
checkSwitches(); | checkSwitches(); | ||
} | } | ||
− | + | waitForSecondsPassedReset(); // if the ISR hasn't reset the bool, the next phase would trigger immediately | |
} | } | ||
Line 309: | Line 309: | ||
TIMSK &= ~(1 << OCIE2); | TIMSK &= ~(1 << OCIE2); | ||
ASSR |= (1 << AS2); // set async mode (crystal nodig) | ASSR |= (1 << AS2); // set async mode (crystal nodig) | ||
− | OCR2 = 31; // prescaler 1024 | + | OCR2 = 31; // prescaler 1024 with OCR 32 is 1 interrupt per sec. |
TCNT2 = 0; // reset counter voor de zekerheid | TCNT2 = 0; // reset counter voor de zekerheid | ||
− | TCCR2 = (1 << WGM21) | (1 << COM20) | 7; // set in normal mode | + | TCCR2 = (1 << WGM21) | (1 << COM20) | 7; // set in normal mode with prescaler 1024 |
− | // we | + | // we turn on OCR2 toggle, to make it possible to have a led on the programming header |
while(ASSR & (1 << TCN2UB)); // wait voor TCN ready | while(ASSR & (1 << TCN2UB)); // wait voor TCN ready | ||
while(ASSR & (1 << OCR2UB)); // wait voor OCR ready | while(ASSR & (1 << OCR2UB)); // wait voor OCR ready | ||
Line 326: | Line 326: | ||
TIMSK2 &= ~(1 << TOIE2); | TIMSK2 &= ~(1 << TOIE2); | ||
TIMSK2 &= ~(1 << OCIE2A); | TIMSK2 &= ~(1 << OCIE2A); | ||
− | ASSR |= (1 << AS2); // set async mode (crystal | + | ASSR |= (1 << AS2); // set async mode (crystal) |
− | OCR2A = 31; // prescaler 1024 | + | OCR2A = 31; // prescaler 1024 with OCR 32 for 1 interrupt per sec. |
− | TCNT2 = 0; // reset counter | + | TCNT2 = 0; // reset counter |
TCCR2A = 0; | TCCR2A = 0; | ||
TCCR2A = (1 << WGM21); | TCCR2A = (1 << WGM21); | ||
− | // we | + | // we turn on OCR2 toggle, to make it possible to have a led on the programming header |
− | |||
TCCR2B = 7; // prescaler 256 | TCCR2B = 7; // prescaler 256 | ||
while(ASSR & (1 << TCN2UB)); // wait voor TCN ready | while(ASSR & (1 << TCN2UB)); // wait voor TCN ready | ||
Line 340: | Line 339: | ||
TIFR2 = 0; // clear interrupt flags | TIFR2 = 0; // clear interrupt flags | ||
− | // | + | // turn on interrupts |
TIMSK2 |= (1 << OCIE2A); | TIMSK2 |= (1 << OCIE2A); | ||
#endif | #endif | ||
− | + | DDRD = 0x00; // set all D as inputs | |
− | + | PORTD = 0xff; // pullups on | |
− | |||
− | DDRD = 0x00; // set all D | ||
− | PORTD = 0xff; // pullups | ||
// test(); | // test(); | ||
− | //check | + | // check if both switches are pressed; this is a user reset |
− | // in | + | // since in this case we can't determine which side the arm is we get the position from eeprom |
if(!(PIND & rightSwitch) && !(PIND & leftSwitch)) | if(!(PIND & rightSwitch) && !(PIND & leftSwitch)) | ||
{ | { | ||
Line 360: | Line 356: | ||
else | else | ||
{ | { | ||
− | if(!(PIND & leftSwitch)) // arm | + | if(!(PIND & leftSwitch)) // arm is left in rest |
{ | { | ||
side = LEFT; | side = LEFT; | ||
} | } | ||
− | if(!(PIND & rightSwitch)) // arm | + | if(!(PIND & rightSwitch)) // arm is right in rest |
{ | { | ||
side = RIGHT; | side = RIGHT; | ||
} | } | ||
− | if(side == 0) // arm | + | if(side == 0) // arm neither left nor right, turn to right rest position |
{ | { | ||
returnRight(); | returnRight(); | ||
Line 376: | Line 372: | ||
− | // | + | // startTime(); |
− | + | stopTime(); | |
secondsPassed = 23; | secondsPassed = 23; | ||
sei(); | sei(); | ||
Line 383: | Line 379: | ||
while(1) | while(1) | ||
{ | { | ||
− | + | waitForStartTijd(); | |
− | + | startTime(); | |
− | + | waitForStopTijd(); | |
− | + | stopTime(); | |
} | } | ||
} | } | ||
Line 400: | Line 396: | ||
PORTB ^= (1 << PB3); //stub to check if interrupts work | PORTB ^= (1 << PB3); //stub to check if interrupts work | ||
} | } | ||
+ | |||
</nowiki> | </nowiki> |
Revision as of 09:07, 1 April 2012
/* * pendule.c * * Created on: 2 mrt. 2012 * Author: Vincent */ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <avr/eeprom.h> #define HALFSTEPS //#define waitTime 43200 // 12 * 3600 //#define waitTime 43380 // 12 * 3600 + 3 * 60 #define waitTime 40 // define delays that are caused by mechanical construction // it takes about 30 seconds from starting the stop-action before the pendulum has actually stopped #define stopDelay 30 // in seconds #define startDelay 3 // in seconds #define soft_reset() \ do \ { \ wdt_enable(WDTO_15MS); \ for(;;) \ { \ } \ } while(0) // Function Prototype to reset wdt on startup void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3"))); // Function Implementation void wdt_init(void) { MCUSR = 0; wdt_disable(); return; } volatile uint16_t secondsPassed; volatile uint8_t secondsPassedReset; #define ORG (1<<PC2) #define YEL (1<<PC3) #define PIK (1<<PC4) #define BLU (1<<PC5) #define leftSwitch (1<<PD3) #define rightSwitch (1<<PD2) #define switchPort PIND #define LEFT 1 #define RIGHT 2 #ifdef HALFSTEPS #define almostStop 412 #define totalStop 160 #define stopSpeed 200 #else #define almostStop 825 #define totalStop 350 #define stopSpeed 100 #endif #define stepDelay 3 uint8_t steps[8]; uint8_t currentStep = 0; uint8_t side = 0; // 1 = left, 2 = right uint16_t stopWaitTime; uint16_t totalSteps; void clear_eeprom() { uint8_t *addr; for(uint16_t i=0;i<=E2END;i++) { addr = (uint8_t *)i; eeprom_write_byte(addr,0xff); } } void write_eeprom(uint8_t oscVal) { uint8_t *addr; addr = (uint8_t *)0x1ff; eeprom_write_byte(addr,oscVal); } void write_totalSteps() { uint16_t *addr; addr = (uint16_t *)0x1f0; eeprom_write_word(addr,totalSteps); } uint8_t read_eeprom() { uint8_t *addr; addr = (uint8_t *)0x1ff; uint8_t tByte = eeprom_read_byte(addr); return(tByte); } void checkSwitches() { if(!(PIND & rightSwitch) && !(PIND & leftSwitch)) { write_eeprom(side); soft_reset(); } } void stepLeft() { currentStep++; currentStep = currentStep%8; PORTC = steps[currentStep]; _delay_ms(stepDelay); checkSwitches(); // PORTC = 0x00; } void setSide(uint8_t sid) { side = sid; } void stopStep() { PORTC = 0x00; } void returnLeft() { while(PIND & leftSwitch) { stepLeft(); } stopStep(); side = LEFT; } void stepRight() { currentStep--; currentStep = currentStep%8; PORTC = steps[currentStep]; _delay_ms(stepDelay); checkSwitches(); // PORTC = 0x00; } void returnRight() { while(PIND & rightSwitch) { stepRight(); } stopStep(); side = RIGHT; } void stopTime() { // this function stops the Pendulum if(side == LEFT) { for(uint16_t q=0;q<almostStop;q++) // bring to almostStop position from left side { stepRight(); } for(uint16_t q=0;q<totalStop;q++) { stepRight(); _delay_ms(stopSpeed); } returnLeft(); } if(side == RIGHT) { for(uint16_t q=0;q<almostStop;q++) // bring to almostStop position from right side { stepLeft(); } for(uint16_t q=0;q<totalStop;q++) { stepLeft(); _delay_ms(stopSpeed); } returnRight(); } } void startTime() { // start the pendulum with stepper if(side == LEFT) { returnRight(); } else if(side == RIGHT) { returnLeft(); } } void waitForSecondsPassedReset() { // wait until the ISR has reset the secondsPassed bool to avoid premature triggering while(!secondsPassedReset); secondsPassedReset = 0; } void waitForStartTijd() { while(secondsPassed < waitTime - startDelay) { checkSwitches(); } waitForSecondsPassedReset(); // if the ISR hasn't reset the bool, the next phase would trigger immediately } void waitForStopTijd() { while(secondsPassed < waitTime - stopDelay) { checkSwitches(); } waitForSecondsPassedReset(); // if the ISR hasn't reset the bool, the next phase would trigger immediately } void test() { while(1) { returnLeft(); returnRight(); } } void countSteps() { while(PIND & leftSwitch) { stepLeft(); } setSide(LEFT); totalSteps = 0; while(PIND & rightSwitch) { stepRight(); totalSteps++; } setSide(RIGHT); write_totalSteps(); } void defineSteps() { #ifdef HALFSTEPS steps[0] = ORG; steps[1] = YEL; steps[2] = PIK; steps[3] = BLU; steps[4] = ORG; steps[5] = YEL; steps[6] = PIK; steps[7] = BLU; #else steps[0] = ORG; steps[1] = ORG | YEL; steps[2] = YEL; steps[3] = YEL | PIK; steps[4] = PIK; steps[5] = PIK | BLU; steps[6] = BLU; steps[7] = BLU | ORG; #endif } int main() { //define steps for stepper defineSteps(); // set DDR for blinkled on OC2A DDRB = (1 << PB3); // set output for stepper PORTC = 0; DDRC = (ORG | YEL | PIK | BLU); // init timer atmega8 #ifdef _atmega8 TIMSK &= ~(1 << TOIE2); TIMSK &= ~(1 << OCIE2); ASSR |= (1 << AS2); // set async mode (crystal nodig) OCR2 = 31; // prescaler 1024 with OCR 32 is 1 interrupt per sec. TCNT2 = 0; // reset counter voor de zekerheid TCCR2 = (1 << WGM21) | (1 << COM20) | 7; // set in normal mode with prescaler 1024 // we turn on OCR2 toggle, to make it possible to have a led on the programming header while(ASSR & (1 << TCN2UB)); // wait voor TCN ready while(ASSR & (1 << OCR2UB)); // wait voor OCR ready while(ASSR & (1 << TCR2UB)); // wait voor TCR ready TIFR = 0; // clear interrupt flags // nu kunnen de interrupts aan.. TIMSK |= (1 << OCIE2); sei(); #else // init timer atmega88 TIMSK2 &= ~(1 << TOIE2); TIMSK2 &= ~(1 << OCIE2A); ASSR |= (1 << AS2); // set async mode (crystal) OCR2A = 31; // prescaler 1024 with OCR 32 for 1 interrupt per sec. TCNT2 = 0; // reset counter TCCR2A = 0; TCCR2A = (1 << WGM21); // we turn on OCR2 toggle, to make it possible to have a led on the programming header TCCR2B = 7; // prescaler 256 while(ASSR & (1 << TCN2UB)); // wait voor TCN ready while(ASSR & (1 << OCR2AUB)); // wait voor OCR ready while(ASSR & (1 << TCR2AUB)); // wait voor TCR ready TIFR2 = 0; // clear interrupt flags // turn on interrupts TIMSK2 |= (1 << OCIE2A); #endif DDRD = 0x00; // set all D as inputs PORTD = 0xff; // pullups on // test(); // check if both switches are pressed; this is a user reset // since in this case we can't determine which side the arm is we get the position from eeprom if(!(PIND & rightSwitch) && !(PIND & leftSwitch)) { side = read_eeprom(); } else { if(!(PIND & leftSwitch)) // arm is left in rest { side = LEFT; } if(!(PIND & rightSwitch)) // arm is right in rest { side = RIGHT; } if(side == 0) // arm neither left nor right, turn to right rest position { returnRight(); } } // startTime(); stopTime(); secondsPassed = 23; sei(); while(1) { waitForStartTijd(); startTime(); waitForStopTijd(); stopTime(); } } ISR( TIMER2_COMPA_vect) { secondsPassed++; if(secondsPassed > waitTime) { secondsPassed = 1; secondsPassedReset = 1; } PORTB ^= (1 << PB3); //stub to check if interrupts work }