My first AVR *practical* gadget!

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I set out, months ago to learn microcontroller programming, to keep me focused I chose something that I could actually use and share, so here is it: the BirdBrain Mk1. :lol:

That's the first assembled prototype, so please overlook some crooked caps and resistors...
The second one came out much neater.

It's a motor timer for small electric free flight model planes. 8 to 16 inches in wingspan.
It works like this, the board has one button and one slide switch. The switch chooses between two run modes and the button is the user interface... :wink:
Pressing down and holding the button sets the flight time, for every second you hold it the counter adds 4 seconds and blinks the LED so the user can count along. After releasing the button the flight time is stored in EEPROM so it won't need resetting if the battery is unplugged.
Doing a double click starts the run sequence, first the timer blinks out the time set 1 blink = 4 sec. Then the motor is engaged, ramping up the speed for 2 seconds to be gentle with any geartrain between the motor and propeller. At this point, depending on the position of the switch the flight modes diverge, FM1 is a full power run, full throttle for the duration of the flight. FM2 is a discharge mode, it starts at 100% throttle and slows down during the length of the motor run to about 60%. For both there's a 1 second soft stop at the end.
At any point of the motor run, clicking the button stops everything and goes back to standby.
The timer also has a sleep timer to go to sleep after 45 seconds of no use, and a low battery monitor that also sends it to sleep if the voltage is bellow 3V. I've also used the low voltage monitor to check that the motor isn't stalled (i.e something stops the prop), it's crude but works most of the time.

Here's the full code:

//******** Bird Brian Mk.1 ********//
//  Electric Free Flight timer     //
//                                 //
// Author	: Alejandro Garcia //
// Target	: ATTiny13V        //
// MCu Speed: 4.8Mhz               //
// Version  : 1.00                 //
// Date     : 29-10-08             //
//*********************************//

// Distribute freely but please do not to use commercially

#include 
#include 
#include 
#include 

volatile unsigned char Run;
volatile unsigned char Repeat;
volatile unsigned char SetTime;
volatile unsigned char TimeSet;
volatile unsigned char AutoSleep;
volatile unsigned char MainLoop;
volatile unsigned char Volt1;
volatile unsigned char Volt2;
unsigned char ChangePower;
unsigned char ElapsedTime;
unsigned char Mode;
unsigned char PWM;
unsigned char TenthSecond;
volatile int Tick;

void VoltageTest();
void SleepFunction();
void _LED(int delay);

int main (void)
{
	sei(); //  Enable global interrupts
	DDRB &= ~(1<<PB1) & ~(1<<PB4) &~(1<<PB3); // PB1 as Button1 input, PB3 as flight mode button, PB4 voltage monitor
	DDRB |= (1<<PB0) | (1<<PB2); // PB1 as output for motor, PB2 as output for LED
	PORTB |= (1<<PB1) | (1<<PB3); // Enable PB0/PB3 pull-up resistor
	GIMSK |= (1<<INT0); // Enable INT0 interrupt

	TIMSK0 |= (1<<TOIE0); // Enable Timer0 overflow interrupt

	TCCR0B |= (1<<CS00); // No clock prescaler

	ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADSC) | (1<<ADATE); //  Enable ADC. Set ADC prescaler to 64. Start Conversion
	ADMUX |= (1<<REFS0) | (1<<ADLAR) | (1<<MUX1); // Enable Internal Voltage Reference, Left adjust register, ADC2 (PB4) as analog input

	Repeat = 0;
	AutoSleep = 0;

	while(1)
	{
		TCCR0A |= (1<<WGM00) | (1<<COM0A1) | (1<<COM0A0); //Phase Correct PWM mode, toggle OC0A on Compare Match
		MCUCR |= (1<<ISC01); // Set INT0 as falling edge trigger
		OCR0A = 255;
		_LED(50000);
		MainLoop = 1;
		Volt1 = 255; // Set up Volt1 value
		VoltageTest();	// Check battery level

		while(MainLoop)
		{

			if(Run)	// Start run
			{
				OCR0A = 255;
				TimeSet = eeprom_read_word((uint8_t*)12); // Load run time from EEPROM memory
				ElapsedTime = 0;
				for(int i = 0; i <= (TimeSet-1); ++i) // Display time set
				{
					if(Run)
					{
					_LED(20000);
					}
					Tick = 0;
				}
				while(OCR0A>=1)	// Soft start
				{
					if(Run)
					{
						OCR0A = --OCR0A;
						_delay_loop_2(1500);
						if(Tick >= 1300)
						{
							_LED(500);
							Tick = 0;
						}
					}
					else
					{
					break;
					}
				}
				Tick=0;
				while(1)	// Main run
				{
					if(Run)
					{
						if(Tick >=130)		// One second elapsed
						{
							TenthSecond++;
							if(ElapsedTime>=(TimeSet*40) - 30)	/* Multiply time set by 4 and substract 3 seconds
							                                      to run time in account of soft start and stop*/
							{
								break;	// Go out of run loop
							}
							else
							{
								if(TenthSecond >= 10)
								{
									VoltageTest();	// Test Voltage
									_LED(500);
									TenthSecond = 0;
								}
								Tick = 0;
								ElapsedTime++;	
								ChangePower++;

								if(bit_is_clear(PINB, PB3))	// Select flight profile
								{
									if(ChangePower >= TimeSet)	// Discharge curve flight mode
									{
										OCR0A = OCR0A + 4;	// Decrease power
										ChangePower = 0;
									}
								}
								else	// Full power flight mode
								{
									OCR0A = 0;
								}
							}
						}
					}
					else
					{
					break;
					}
				}
				while(OCR0A<=254)	// Soft stop
				{
					if(Run)
					{
						OCR0A = OCR0A + 1;
						_delay_loop_2(1000 + PWM);
					}
					else
					{break;}
				}
				OCR0A = 255;
				Run = 0;
			}
			if(SetTime)	// Time setting routine
			{	
				while(bit_is_clear(PINB, PB1))	// While button is pressed
				{	
					GIMSK &= ~(1<<INT0); // Disable button interrupt
					TimeSet = 0;
					while(bit_is_clear(PINB, PB1)) //If button still pressed, set time
					{
						_LED(50000);
						TimeSet++;
					}
					eeprom_write_byte((uint8_t*)12, TimeSet);	// Store time in EEPROM
				}
				SetTime = 0;	// Button debouncing start
				_delay_loop_2(50000);
				GIMSK |= (1<<INT0);	// Enable interrupts
				Repeat = 0;	// Button debouncing end
			}
		   	if(Repeat)	// Check for double click
			{
				_delay_loop_2(50000);
				Repeat = 0;	// Double click timed out
			}
			if(AutoSleep>=45) // Check for AutoSleep time
			{	
				SleepFunction();
			}
			else	// Status indication
			{
				if(Tick >=1300)
				{
					if(bit_is_clear(PINB, PB3))	// Timer is on Discharge Mode
					{
					_LED(5000);
					_LED(5000);
					}
					else
					{
					_LED(5000);	// Timer is on Normal Mode
					}
					Tick = 0;
					VoltageTest();
					AutoSleep++;
				}
			}
		}
	}
}

ISR(INT0_vect)	// Button interrupt routine
{
	if(Run)	// If motor is running, stop it
	{
		Run = 0;
		Repeat = 0;
		SetTime = 0;
	}
	else
	{
		if(Repeat)	// If double click detected, start motor
		{
			Run = 1;
		}
		else	// Set time loop
		{
			_delay_loop_2(50000);
			_delay_loop_2(50000);
			if(bit_is_clear(PINB, PB1))	// If button is held down, increase run time by 1 every second.
			SetTime = 1;
		}
		Repeat = 1;
		AutoSleep = 0;
	}
}

void VoltageTest()
{
	Volt2 = ADCH;
	if(Volt1 - Volt2 >= 40) // Check for stalled motor
	{
		Run = 0; 
	}
	if(Volt2 <= 190) // 3/3.1 volts reading
	{
	SleepFunction();
	}
	else
	{
	Volt1 = Volt2; // Store voltage reading to compare later
	}
}

void SleepFunction()
{
	TCCR0A &= ~(1<<WGM00) & ~(1<<COM0A1) & ~(1<<COM0A0);	// Disable PWM
	Run = 0;
	MCUCR &= ~(1<<ISC01) & ~(1<<ISC00); // Set INT0 as low level
	MCUCR |= (1<<SE) | (1<<SM1); // Enable sleep mode, set sleep mode to power-down.
	PORTB &= ~(1<<PB2);
	Repeat = 0;
	MainLoop = 0;	// Go out of main loop
	asm("sleep");	// Nite nite
}

ISR(TIM0_OVF_vect)	// Timer interrupt
{
	Tick++;
}

void _LED(int delay)	// LED blinking function
{
	PORTB |= (1<<PB2);
	_delay_loop_2(delay);
	PORTB &= ~(1<<PB2);
	_delay_loop_2(delay);
}

I fully anticipate some "why on Earth did you do that like this???" Feel free to show me the right way.
It uses pretty much all the available flash memory on the Tiny13, if anyone can tip on how to optimize it it would be very appreciated. :D

Here's the Eagle schematic, it's my first schematic on that program... I'm still on the hate phase, what's up with CAD programs with workflows stuck in the 80s??? :x

Here's the PCB... done in Corel Draw:

And a closer look 'cause it's pretty small.

So, a big thanks to all the people that helped me with the questions I had along the way.
I still think there are things to improve, the motor stalling is not reliable with small motors (4mm pager type), and it has a rather high sleep current drain, I think 1.5 mA; mostly from the voltage divider on the PB4 ADC and, puzzling enough, from the MOSFET.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you like I can move this thread to the "Academy Forum" which I think would be an appropriate place for it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Neat project!!

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
If you like I can move this thread to the "Academy Forum" which I think would be an appropriate place for it.

Hmmm, yep, that looks more appropriate. :oops:

Please, send it that way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very nice! I'd like to see pictures or a video of the thing in flight!

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Very nice! I'd like to see pictures or a video of the thing in flight!

That may take some time since a model for this thing is pretty far at the back of the Stuff-To-Do queue.

But...

I tested (static) it on a micro R/C plane I already have.

A short run on discharge mode:

http://www.youtube.com/watch?v=0B6HgTor9Qk

And the "ouch!" test, to see if the timer stops when the prop hits something:

http://www.youtube.com/watch?v=rs-alrGuVY8

I'd like to use it on this model, the little know Kakaka Amphibious Pedal Bomber

"The originality of Japanese aircraft design was never in question after the Shirley wobbled onto the scene, albeit briefly, in the closing months of the Pacific war. This light (75 lbs.), cheap ($1.49), last-ditch gesture of a desperate Japanese High Command was in fact little more than a bicycle of the air, its propeller turned by pedal power from the pilot. Towed behind a torpedo boat, the Shirley would sooner or later rise and fumble skyward, staying aloft exactly as long as its pilot's stamina held out and his sprocket chain stayed intact. Hopefully, a U.S. ship would soon be sighted; then, braving massive ack-ack fire as well as large birds, the fanatic suicide candidate at the controls, or handle bars, aimed toward his quarry and pumped furiously until directly overhead. Then, at the flick of a lever, the under slung wicker basket fell away and hit the deck below-and one rabid dog was disgorged to run amuck and wreak its mad havoc. The ravening animal, it was assumed, would take a few Yanks with it by the time the end came. Ingenious-but not ingenious enough; the dogs proved susceptible to seasickness en route to the target and every known Shirley mission ended in anticlimax with a dazed mutt vomiting among the gobs while a paper airplane slowly sank off the starboard bow."

Bruce McCall

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

the little know Kakaka Amphibious Pedal Bomber

:D

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Writing the user's manual now. I'll work on the assembling instructions next.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cool project - Nice work!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CirMicro wrote:
Cool project - Nice work!

Thank you!

So, any comments on the code?