Actions

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
  
// waarschijnlijk middelen de startvertraging en de stopvertraging elkaar uit
+
// define delays that are caused by mechanical construction
#define stopVertraging 30 // in seconds
+
// it takes about 30 seconds from starting the stop-action before the pendulum has actually stopped
#define startVertraging 3 // in seconds
+
#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 bijnaStop 412
+
#define almostStop 412
 
#define totalStop 160
 
#define totalStop 160
 
#define stopSpeed 200
 
#define stopSpeed 200
 
#else
 
#else
#define bijnaStop 825
+
#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_byte(addr,(totalSteps&0xff00)>>8);
 
// eeprom_write_byte(addr+1,totalSteps&0xff);
 
 
eeprom_write_word(addr,totalSteps);
 
eeprom_write_word(addr,totalSteps);
 
}
 
}
Line 172: Line 172:
 
}
 
}
  
void stopDeTijd()
+
void stopTime()
 
{
 
{
// deze functie stopt de tijd/slinger met de stepper motor
+
// this function stops the Pendulum
 
if(side == LEFT)
 
if(side == LEFT)
 
{
 
{
for(uint16_t q=0;q<bijnaStop;q++) // breng naar bijnastop positie
+
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<bijnaStop;q++) // breng naar bijnastop positie
+
for(uint16_t q=0;q<almostStop;q++) // bring to almostStop position from right side
 
{
 
{
 
stepLeft();
 
stepLeft();
Line 203: Line 203:
 
}
 
}
  
void startDeTijd()
+
void startTime()
 
{
 
{
// deze functie start de tijd/slinger met de stepper motor
+
// start the pendulum with stepper
 
if(side == LEFT)
 
if(side == LEFT)
 
{
 
{
Line 216: Line 216:
 
}
 
}
  
void wachtOpSecondsPassedReset()
+
void waitForSecondsPassedReset()
 
{
 
{
// functie wacht tot de ISR functie de secondspassed reset
+
// 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 wachtOpStartTijd()
+
void waitForStartTijd()
 
{
 
{
while(secondsPassed < waitTime - startVertraging)
+
while(secondsPassed < waitTime - startDelay)
 
{
 
{
 
checkSwitches();
 
checkSwitches();
 
}
 
}
wachtOpSecondsPassedReset(); // omdat anders de andere wachtfunctie onmiddelijk kan triggeren
+
waitForSecondsPassedReset(); // if the ISR hasn't reset the bool, the next phase would trigger immediately
 
}
 
}
  
void wachtOpStopTijd()
+
void waitForStopTijd()
 
{
 
{
while(secondsPassed < waitTime - stopVertraging)
+
while(secondsPassed < waitTime - stopDelay)
 
{
 
{
 
checkSwitches();
 
checkSwitches();
 
}
 
}
wachtOpSecondsPassedReset(); // omdat anders de andere wachtfunctie onmiddelijk kan triggeren
+
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 met OCR 32 levert 1 interrupt per sec.
+
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 met prescaler 1024
+
TCCR2 = (1 << WGM21) | (1 << COM20) | 7; // set in normal mode with prescaler 1024
// we zetten OCR2 toggle aan, zodat er evt. een seconde ledje op de prog. header kan
+
// 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 nodig)
+
ASSR |= (1 << AS2); // set async mode (crystal)
OCR2A = 31; // prescaler 1024 met OCR 32 levert 1 interrupt per sec.
+
OCR2A = 31; // prescaler 1024 with OCR 32 for 1 interrupt per sec.
TCNT2 = 0; // reset counter voor de zekerheid
+
TCNT2 = 0; // reset counter
 
TCCR2A = 0;
 
TCCR2A = 0;
 
TCCR2A = (1 << WGM21);
 
TCCR2A = (1 << WGM21);
// we zetten OCR2 toggle aan, zodat er evt. een seconde ledje op de prog. header kan
+
// we turn on OCR2 toggle, to make it possible to have a led on the programming header
// TCCR2A |= (1 << COM2A0); // activate OC2A toggle
 
 
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
  
// nu kunnen de interrupts aan..
+
// turn on interrupts
 
TIMSK2 |= (1 << OCIE2A);
 
TIMSK2 |= (1 << OCIE2A);
 
#endif
 
#endif
  
// sei();
+
DDRD = 0x00; // set all D as inputs
 
+
PORTD = 0xff; // pullups on
 
 
DDRD = 0x00; // set all D als inputs
 
PORTD = 0xff; // pullups aan
 
  
 
// test();
 
// test();
  
//check eerst of beide switches ingedrukt zijn; dit duidt op een soft reset
+
// check if both switches are pressed; this is a user reset
// in dat geval de side uit het eeprom halen
+
// 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 staat links in ruststand
+
if(!(PIND & leftSwitch)) // arm is left in rest
 
{
 
{
 
side = LEFT;
 
side = LEFT;
 
}
 
}
if(!(PIND & rightSwitch)) // arm staat rechts in ruststand
+
if(!(PIND & rightSwitch)) // arm is right in rest
 
{
 
{
 
side = RIGHT;
 
side = RIGHT;
 
}
 
}
  
if(side == 0) // arm niet in ruststand, draai naar links tot rustswitch
+
if(side == 0) // arm neither left nor right, turn to right rest position
 
{
 
{
 
returnRight();
 
returnRight();
Line 376: Line 372:
  
  
// startDeTijd();
+
// startTime();
stopDeTijd();
+
stopTime();
 
secondsPassed = 23;
 
secondsPassed = 23;
 
sei();
 
sei();
Line 383: Line 379:
 
while(1)
 
while(1)
 
{
 
{
wachtOpStartTijd();
+
waitForStartTijd();
startDeTijd();
+
startTime();
wachtOpStopTijd();
+
waitForStopTijd();
stopDeTijd();
+
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
}