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
}