Unexpected Behavior

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

The problem I am having is that a certain part of my program is not getting executed after it should be, yet I have found any issues when running AVR Simulator 2 nor are there any compile issues.

Theory of operation:
Run:
1. If !TRIGGER de-bounce TRIGGER input via software routine before turning on drive.
2. If !TRIGGER after debounce, TURN OFF BRAKE, delay before turn on drive.
3. Start drive PWM with soft start PWM value for x amount of time.
4. Change PWM to full value after soft start is completed and wait for TRIGGER to occur.

Stop:
1. If TRIGGER turn off drive, delay for x amount of time before turning on brake
2. Turn on brake after delay is complete and wait for !TRIGGER to occur again.

SafeMode.c

void Run_In_Safe_Mode(void){
/* local variable definitions to function Run_In_SafeMode */
	static bool TriggerFlag = true, RunLockFlag = false, StopLockFlag = false;
	
	if( !SW6 ){
		while( 1 ){
			if( TriggerFlag ){
				if( Debounced_Deb && !TRIGGER ){
					TURN_OFF_LED2;
					if( !RunLockFlag ){
						DISABLE_TIMER0_INTB;
						ENABLE_TIMER0_INTA;
						TURN_OFF_BRAKE;
						OCR0A = TC0_PSD1;					/* set TC0 pre-start delay time */
						START_TIMER0;						/* start TC0 prestart delay */
						OCR1A = SoftStartDutyCycle_UsrSet;	/* set PWM to 80% of DutyCycle_UsrSet */
						RunLockFlag = true;					/* locks out routine */
						TC0DelayComplete_ISR = false;		/* enables TC0 delay for next use */
					}
					if( TC0DelayComplete_ISR && RunLockFlag ){		
						Start_PWM1();				
						OCR0A = TC0_SSD;					/* set TC0 soft start delay time */
						START_TIMER0;						/* start soft start delay (TC0) */
						TriggerFlag = false;				/* enables Stop segment for next use */
						RunLockFlag = false;				/* unlocks RunLockFlag for next use */
						SoftStartComplete_ISR = true;		/* indicates that soft start is finished */
						Debounced_Deb = false;				/* locks out entire Run sequence until */
						TC0DelayComplete_ISR = false;		/* enables TC0 delay for next use */	
					}
				}else{
					Debounce_Trigger();
				}
			}else{
				if( TRIGGER && !StopLockFlag && !SoftStartComplete_ISR ){
					Stop_PWM1();		
					OCR0A = TC0_PSD2;					/* set TC0 pre-start delay time */
					START_TIMER0;						/* start TC0 prestart delay */
					StopLockFlag = true;				/* locks out routine */
					TC0DelayComplete_ISR = false;		/* enables TC0 delay for next use */
				}
				if( TC0DelayComplete_ISR && StopLockFlag ){
					TURN_ON_BRAKE;
					TriggerFlag = true;					/* enables Run segment for next use */
					StopLockFlag = false;				/* unlocks StopLockFlag for next use */					
					Debouncing_Deb = false;
					Locked_Deb = false;
					TC0DelayComplete_ISR = false;		/* enables TC0 delay for next use */	
					DISABLE_TIMER0_INTA;
					ENABLE_TIMER0_INTB;	
					TURN_ON_LED2;		
				}
			}
		}
	}	
}

Debounce.c

void Debounce_Trigger( void ){
/* Local Variable Definitions to Debounce_Trigger */
static uint16_t TriggerState_Deb = 0, Temp_Deb = 1;	

	if( TC0_COMPB_INT_FLAG_ISR ){
		TriggerState_Deb = (TriggerState_Deb<<1) | TRIGGER | 0xe000 | Temp_Deb;
		Temp_Deb = 0;
		if( TriggerState_Deb==0xf000 ){
			Debounced_Deb = true;
			TriggerState_Deb = 0;
			Temp_Deb = 1;
		}else{
			START_TIMER0;
		}
		TC0_COMPB_INT_FLAG_ISR = false;
	}else{

		if( !Locked_Deb ){
			OCR0B = TC0_DT;
			Locked_Deb = true;
		}
		if( !TRIGGER && !Debouncing_Deb ){
			START_TIMER0;
			Debouncing_Deb = true;		
		}
	}
}

ISR.c

ISR( TIMER0_COMPA_vect ){
	STOP_TIMER0;
	TCNT0 = 0;
		TC0DelayComplete_ISR = true;
		if( SoftStartComplete_ISR==true ){
			OCR1A = DutyCycle_UsrSet;
			SoftStartComplete_ISR = false;
			TC0DelayComplete_ISR = false;
		}
}

ISR( TIMER0_COMPB_vect ){
	STOP_TIMER0;
	TCNT0 = 0;
		TC0_COMPB_INT_FLAG_ISR = true;
}

I did not include any variable definitions or declarations, but they are certainly there. The exact problem I am having is that I can press the trigger, and the debounce routine works, PWM turns on, delays all happen as far as I can tell( checked with a scope and there is a delay between the time the trigger is pressed until the PWM actualy produces an output), and I can also see the soft start PWM duty cycle and then I can see it change on the scope to the full PWM duty cycle, so that is working. I then release the trigger and the PWM turns off and a delay happens before the brake is turned on, but when I press trigger again it stays in the same state. By using LED2 and turning it off and on in various parts of my program I have determined that Debounced_Deb is never set to true again even though !TRIGGER occurs. The simulator is not catching whatever is going on because it never has this issue in simulation. I am thinking there is an issue with switching between output compare A and B interrupts which are vital to the debouncing process and operation. Any ideas?

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

Why does the trigger need debouncing again? If you pull it and it bounces open and the computer reads it, its still off. Next pass, computer sees it and turns on. If you let go, its open. Never heard of a bounce on open.

Imagecraft compiler user

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

Bounce on open seems much less of an issue but I always debounce every switch change. I typically poll at around 20ms to 50ms and look for 3 to 5 same bit values in a row. That works both opening and closing. Sometimes I poll a little faster and shift the switch state into an 8-bit variable. I simply test the variable for "0xff" or "0x00".

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

I figured out the issue, as per my last thread about DWEN I set up my AVR Dragon with DebugWire and watched what exactly was going on. It appears that even with the compare match interrupt disabled if OCR0A or OCR0B has a value other than 0 a match will be generated and the timer is cleared, so because OCR0B had a larger value than OCR0A when the entire program came around again it kept clearing on OCR0A, so a COMPB interrupt was never generated, so it was an endless loop of timer. The simulator didn't catch that fact when I ran the simulation, I wasn't able to decipher that information from the data sheet.

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

Quote:

I wasn't able to decipher that information from the data sheet.

Hmmm--I guess I could be caught on that. But upon reflection, timer actions occur whether or not the _IE_ bits in the TIMSK register are set or not. The same thing with USART and SPI and ADC and ...

You look at the mode selection and its actions. I don't think it says anything about different actions if the _IE_ bit(s) are set or not. It isn't unusual for me to use CTC without an interrupt.

Your code threw me off a bit with the STOP_TIMERn() in the ISR but then no definition for it. I questioned why anyone would do that, but it was apparently a trick for the readers.

All of the above makes me glad I just use my 5ms or 10ms heartbeat timer tick, read all the applicable input pins into a composite variable, and enter it into the debounce routine. All the rest of the code then has the needed edges and current state available.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I was being cautious of the Timer as when I ran the simulation(before I was informed that the AVR Dragon has debug capabilities which my AVRISP did not), the counter was not clearing upon entering the ISR, which the data sheet specified it would, so I figured until I could verify everything I would make sure the timer was cleared and ready for the next use. Thanks for the help, now I can strip all the unnecessary code out.