Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
06/06/11 16:00
Read: times


 
#182505 - Servo control blues
Guys I need a bit of advice on some code I've written in Keil in C for an 89C51 core microcontroller. It's a simple application really and I was staggered when I've found that in practice it didn't work (It does work well while emulating the program in Keil step by step). It isn't the most elegant of codes, it's supposed to be quick and dirty to get things done (I know...I know).

The code I've written is supposed to set a servo to turn to 90 degrees, then force the microcontroller to wait for an incoming input through serial and turn the microcontroller accordingly (U to turn right and D to turn left). A normally closed Emergency button is connected with INT0 (set to operate at negative edge triggering in code). When it's pressed the ISR should execute, which should stop the servo motor from turning and if it's pressed for a minimum of 10 seconds the system should reset i.e. control passes back to the main program.

That's the basic operation. As I said it does work well when debugging it in Keil. Problem is, in practice the application works well when the system receives the first external interrupt (i.e. emergency button is pressed), but than after about a couple of seconds, the micro re-executes the ISR without any external INT0 trigger! (Used LEDs to check if this is what's happening and seems the case).

I'm sure I'm missing something out. Any help would be appreciated.


Thanks in advance!

Kai



	 #include <reg52.h>
	 sbit L_G = P0^0;				   // Green Led
	 sbit L_R = P0^2;				   // Red Led 
	 sbit buz = P0^4;				   // Buzzer
	 sbit srv = P0^6;				   // Servo 
	 sbit eme2 = P0^7;				   // not used
	 sbit intbut = P3^2; 			   // interrupt pin 
	 unsigned char mychar;
	 unsigned int on, off, rotL, rotR, ctr = 0;
	 unsigned int i, x, y, delay, dly = 0;
	 int RST = 0;	 

	 void main (void)
	 {
	 	
	 	
		// datasheet pg62 setting timer mode
		// Timer 1 = 1	 ( Gate1 = 0, C/T1# = 0, M11 = 2, M01 = 0)
		// Timer 0 = 2	 ( Gate0 = 0, C/T0# = 0, M11 = 0, M01 = 1)
		TMOD = 0x21;			//use Timer1 auto-reload & Timer 0 16 bit timer
		// setting baudrate value using the following eauqation
		//TH1 = 256 - ((Crystal / 384) / Baud)
        //TH1 = 256 - ((18,432,000 / 384) / 9600 )
        //TH1 = 256 - ((48,000) / 9600)
        //TH1 = 256 - 5 = 251		
		TH1 = 0xFB;
		SCON = 0x50;			//8-bit UARTVariable, pg 54
		TR1 = 1;				//start timer

		IT0=1;          //set external interrupt 0 negative edge-triggered
    	EX0=1;          //enable external interrupt 0 interrupt
 	    EA=1;           //enable global interrupt
		
		L_R = 0;
		
		// set the servo position to 90 degrees
		for (ctr = 0; ctr <= 10; ctr++)
			{
				//	_________
				//		     |_____________________
				//	 1.49ms	     19.59ms
				//1.49 on
				for (on = 0; on <= 100; on++);  
				 	{
				  		srv = 0;
				  	}
				//18.1ms off
				for (off = 0; off <= 5900; off++);
				  	{
				  		srv = 1;
					}			
			}
		
		while(1)
			{
			//while(RI == 0);		//wait to receive
			mychar = SBUF;		//save serial input value in mychar
			if (mychar == 'U')
			{
				// servo up, active state
				// set the servo position to 0 degrees
				L_G = 0;        //Green LED on
				L_R = 1;		//Red LED off		
				
				for (rotL = 0; rotL <= 10; rotL++)
					{ 
					//	_________
					//		     |_____________________
					//	 0.955ms	     18.087ms
					//0.955ms on
					//was 185 change to 150
					for (on = 0; on <= 650; on++);  
				 		{
				  			srv = 0;
				  		}
					//18.087ms off
					for (off = 0; off <= 5250; off++);
				  		{
				  			srv = 1;
						} 
					}
			}
			
			else if (mychar == 'D')
			{
				// Servo down, active state
				// set the servo position to 180 degrees
				L_G = 0; 		//Green LED on
				L_R = 1;		//Red LED off
				for (rotR = 0; rotR <= 10; rotR++)
					{				
					//	_________
					//		     |_____________________
					//	 1.809ms	     17.575ms
					//1.809ms on
					for (on = 0; on <= 550; on++);  
				 		{
				  			srv = 0;
				  		}
						//17.575ms off
					for (off = 0; off <= 5315; off++);
				  		{
				  			srv = 1;
						} 
					}
			}			
						
			}
			
	 }

	 void turn_on(void) interrupt 0
	 {		
		EA = 0;
		i, x, y, delay, dly = 0;
		RST = 0;

		
		L_G = 1;        //Switch off green LED
		
		// 1 timer value shall be 20ms
		// 500 timer values = 500 * 20ms = 10s
		// now timer step
			
		// Timer 0 step = Crystal/12
		//              = 18,432,000/12
		//              = 1536000Hz
			
		// Time = 1/Frequency
		//      = 1/1536000
		//      = 651.041666nS
			
		// 1 timer step = 651.041666nS, 
		//         ?    = 20ms 
		// answer = 20msec / 651.0416667nSec 
		//        = 30720 steps

		// Now TFO overflows at FFFFh 
		// therefore 65536 - 30720 = 34816  
		// 34816 dec = 8800h
		// Therefore setting THO = 88h and TLO = 00h

		// Now including the LED and Buzzer emergency PWM
		
		// From the Keil debugger using performance graph it was found
		// that the delay for flicketing the LED and buzzer takes
		// Delay start A time = 0.000292
		// Delay stop A time = 0.034318
		// Therfore total delay time A = 0.034318 - 0.000292
		//                             = 0.034026 seconds
		 
		// Now if we add the delays together we get
		// Total delay = (delay Start A till Delay Stop A + 20ms  by Timer)
		//             = (0.034026 + 20ms)
		//             =  0.054026        

		// Now recalculating the for loop for the time
		// 1 timer step + delay time = 0.55ms
		// 10s = ?
		// timer steps = 10/55ms
		//             = 182 
		
		while (((i != 182) && (intbut == 0)) || (RST == 0))
		{
			for (i = 0; i < 182; i++)
			{
				//Delay A - start
				for (x = 0; x <= 5200; x++);  
				  {
				  L_R = 0;		//Red led on for 0.1sec
				  buz  = 0;		//Buzzer on for 0.1 sec
				  }
				
				for (y = 0; y <= 5200; y++);
				{
				   L_R = 1;	//Red Led off for 0.1sec
				   buz = 1;	//Buzzer of for 0.1sec
				}
			 	//Delay A - stop
				
				//start timer
				TH0 = 0x88;		//set 20ms
		    	TL0 = 0x00;	     
				TR0 = 1;		//start timer
				while(TF0 == 0);

				if  ((i >= 181) && (intbut == 0))
					{
						RST = 1;	 //exit interrupt loop
						TR0 = 0;     // stop the timer
			            TF0 = 0;     // clear timer 0 overflow flag						
						
						
					    eme2 = 0;
						for ( delay = 0; delay <= 10000; delay++)
						{
						for (dly = 0; dly <= 100; dly++)
						{}
						}
				
						eme2 = 1;
						
						
					}
				else if ((i <= 181) && (intbut == 1) && (RST == 0))
					{
					i = 0; //restart timer for loop if emergency is not pressed
					}
		
			
			}
			
						 
		}	
	   RST = 0; //for Good Practice
	   EA = 1;
	}	
	


 





List of 7 messages in thread
TopicAuthorDate
Servo control blues            01/01/70 00:00      
   it would be nice ...            01/01/70 00:00      
       ... it would be better ...            01/01/70 00:00      
   RE: emulating the program in Keil step by step            01/01/70 00:00      
      something *looks* simple doesn't mean it *is* simple            01/01/70 00:00      
         Very few simple applications.            01/01/70 00:00      
            The 90:10 Rule again            01/01/70 00:00      

Back to Subject List