Tiny44 Freezing

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, so I am driving a motor that spins a disc with a mosfet from a tiny44, and has an optical encoder for feedback. I have my control algorithm working to vary the PWM duty cycle with an acceptable degree of oscillation, but after a random interval, the micro just seems to freeze on whatever PWM duty cycle it happens to be on when the freeze occurs. If I reset the microcontroller, control resumes for another random period of time. What could cause this?

/* Name: main.c
 * Author: 
 * Copyright: 
 * License: 
 */

#include 
#include 
#include 
#include 
#include 

typedef uint8_t byte;
typedef uint16_t word;

#define aByte(bit) (1 << bit) // byte with bit set

#define IRLedPin PA1
#define photoTransistorPin PA0
#define motorPin PB2
#define laserPin PA7

#define setPortAPinForOutput(pin) (DDRA |= aByte(pin))
#define setPortAPin(pin) (PORTA |= aByte(pin))
#define clearPortAPin(pin) (PORTA &= ~(aByte(pin)))

#define setPortBPinForOutput(pin) (DDRB |= aByte(pin))
#define setPortBPin(pin) (PORTB |= aByte(pin))
#define clearPortBPin(pin) (PORTB &= ~(aByte(pin)))

volatile byte overflows;
//volatile word 
//volatile word lastTimeStamp;

#define desiredTicksPerInterrupt 5000

ISR(PCINT0_vect)
{
	/*
	 

	 
	 if timer's not running
		zero timer
		start it with app. prescaler (/8 i think; (20000000/8)/200 holes per second gives 12,500 max clock ticks between holes at slowest speed we care about, well within range of the 16-bit timer)
	 
	 if timer is running
		stop it
		decide whether running too fast or too slow, or if overflow happened, just max out pwm
		adjust pwm freq
	 
	 
	 Want 500 holes per second
	 So we want (20000000/8)/500 = 5000 clock ticks between interrupts. 
	 
	 
	 
	 */
	
	
	if(TCCR1B == 0x00 && !(PINA & (1 << photoTransistorPin)))  //If timer is stopped and it was a falling edge
	{
		overflows = 0;  //Reset overflows counter
		TCNT1 = 0x0000;  //Reset timer
		TCCR1B |= _BV(CS11); //Start timer with /8 prescaler
	} else if (!(PINA & (1 << photoTransistorPin))){                // If the timer isn't stopped...
		TCCR1B &= ~_BV(CS11); //Stop timer.
		if (overflows > 0)  //If overfow happened...
		{
			OCR0A = 0xFF;  //Max out PWM.
		} else {            //If it didn't...
			
			if(TCNT1 > desiredTicksPerInterrupt)
			{
				if(OCR0A < 0xFF)
				{
					OCR0A++;  //turn up the duty cycle
				}
			}
			
			if(TCNT1 < desiredTicksPerInterrupt)
			{
				if(OCR0A > 0x01)
				{
					OCR0A--;  //turn down the duty cycle
				}
			}
			
		}
		
	}
	
}
	 

ISR(TIM1_OVF_vect)  
{	
	overflows++;  //increment overflows counter when an overflow happens	
}

int main(void)
{
	
	//set clock divider to /1
	CLKPR = (1 << CLKPCE);
	CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
	
	
	setPortAPinForOutput(IRLedPin);
	setPortAPin(IRLedPin);
	
	setPortBPinForOutput(motorPin); 
	
	
	TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); //Toggle OC0A on Compare Match, Set WGM00 for Phase Correct PWM
	TCCR0B = _BV(CS00);  //Start clock, no prescaler
	OCR0A = 0xFF; //Start at 100% duty cycle for spin-up
	
	GIMSK = _BV(PCIE0);  //Enable pin change interrupt 0
	PCMSK0 = _BV(PCINT0);  //Enable pin change interrupt on PA0
	
	TIMSK1 = _BV(TOIE1); //Enable timer overflow interrupt
	
	sei();  //Enable interrupts
	
    for(;;){
		
    }
    return 0;   /* never reached */
}