AVR Code
From Just in Time
* 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 60
// waarschijnlijk middelen de startvertraging en de stopvertraging elkaar uit
- define stopVertraging 30 // in seconds
- define startVertraging 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 bijnaStop 412 #define totalStop 160 #define stopSpeed 200
- else
#define bijnaStop 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_byte(addr,(totalSteps&0xff00)>>8); // eeprom_write_byte(addr+1,totalSteps&0xff); 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 stopDeTijd() { // deze functie stopt de tijd/slinger met de stepper motor if(side == LEFT) { for(uint16_t q=0;q<bijnaStop;q++) // breng naar bijnastop positie { stepRight(); } for(uint16_t q=0;q<totalStop;q++) { stepRight(); _delay_ms(stopSpeed); } returnLeft(); } if(side == RIGHT) { for(uint16_t q=0;q<bijnaStop;q++) // breng naar bijnastop positie { stepLeft(); } for(uint16_t q=0;q<totalStop;q++) { stepLeft(); _delay_ms(stopSpeed); } returnRight(); } }
void startDeTijd() { // deze functie start de tijd/slinger met de stepper motor if(side == LEFT) { returnRight(); } else if(side == RIGHT) { returnLeft(); } }
void wachtOpSecondsPassedReset() { // functie wacht tot de ISR functie de secondspassed reset while(!secondsPassedReset); secondsPassedReset = 0; }
void wachtOpStartTijd()
{
while(secondsPassed < waitTime - startVertraging)
{
checkSwitches();
}
wachtOpSecondsPassedReset(); // omdat anders de andere wachtfunctie onmiddelijk kan triggeren
}
void wachtOpStopTijd() { while(secondsPassed < waitTime - stopVertraging) { checkSwitches(); } wachtOpSecondsPassedReset(); // omdat anders de andere wachtfunctie onmiddelijk kan triggeren }
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 met OCR 32 levert 1 interrupt per sec. TCNT2 = 0; // reset counter voor de zekerheid TCCR2 = (1 << WGM21) | (1 << COM20) | 7; // set in normal mode met prescaler 1024 // we zetten OCR2 toggle aan, zodat er evt. een seconde ledje op de prog. header kan 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 nodig) OCR2A = 31; // prescaler 1024 met OCR 32 levert 1 interrupt per sec. TCNT2 = 0; // reset counter voor de zekerheid TCCR2A = 0; TCCR2A = (1 << WGM21); // we zetten OCR2 toggle aan, zodat er evt. een seconde ledje op de prog. header kan // TCCR2A |= (1 << COM2A0); // activate OC2A toggle 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
// nu kunnen de interrupts aan.. TIMSK2 |= (1 << OCIE2A);
- endif
// sei();
DDRD = 0x00; // set all D als inputs
PORTD = 0xff; // pullups aan
// test();
//check eerst of beide switches ingedrukt zijn; dit duidt op een soft reset // in dat geval de side uit het eeprom halen if(!(PIND & rightSwitch) && !(PIND & leftSwitch)) { side = read_eeprom(); } else { if(!(PIND & leftSwitch)) // arm staat links in ruststand { side = LEFT; } if(!(PIND & rightSwitch)) // arm staat rechts in ruststand { side = RIGHT; }
if(side == 0) // arm niet in ruststand, draai naar links tot rustswitch { returnRight(); } }
// startDeTijd();
stopDeTijd();
secondsPassed = 23;
sei();
while(1) { wachtOpStartTijd(); startDeTijd(); wachtOpStopTijd(); stopDeTijd(); } }
ISR( TIMER2_COMPA_vect) { secondsPassed++; if(secondsPassed > waitTime) { secondsPassed = 1; secondsPassedReset = 1; } PORTB ^= (1 << PB3); //stub to check if interrupts work }