Retaining value after a call

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

Here is the code:

#include 
#include 
#include 
#include 

//Definitions
#define Trigger (PINC&_BV(PINC2))
#define Gearbox_Sensor (PINC&_BV(PINC0))
#define Turn_On_SW2 (PORTD |= _BV(PIND2)) 
#define Turn_Off_SW2 (PORTD &= ~_BV(PIND2)) 
#define Turn_On_SW3 (PORTD |= _BV(PIND3)) 
#define Turn_Off_SW3 (PORTD &= ~_BV(PIND3)) 
#define Turn_On_SW4 (PORTD |= _BV(PIND4)) 
#define Turn_Off_SW4 (PORTD &= ~_BV(PIND4)) 
#define Turn_On_Motor (PORTD |= _BV(PIND6)) 
#define Turn_Off_Motor (PORTD &= ~_BV(PIND6)) 

//Global Variables
volatile static bool gearbox_sensor_flag;	
volatile uint8_t value;

//Fucntion Prototypes
bool Fire(bool t_flag);
bool Stop_Firing(bool t_flag);
void Count_Gearbox_Cycles(bool gs_flag);

int main(){
	//Sets pin direction, PD6 Motor Drive, PB1 Motor Brake
	DDRD |= 0x40;
	DDRB |=	0x02;	

	//Sets initial state of PD6 and PB1
	PORTD &= ~0x40;	//Motor Drive off
	PORTB &= ~0x02;	//Motor Brake off

	//Enable Pull Up Resistors
	PORTC |= 0x05;	//PC0(Gbx. Pos.),PC2(Trig.) 
	PORTD |= 0xA0;	//PD5,PD7	
	PORTB |= 0x05;	//PB0,PB2

	//Enable Global Interrupts and PCINT8
	sei();				
	PCICR  |= 0x02;		
	PCMSK1 |= 0x01;			

	//Local Variables
	static bool trigger_flag;

		//Main Loop
		while(1){
			trigger_flag = Fire(trigger_flag);

			trigger_flag = Stop_Firing(trigger_flag);

			Count_Gearbox_Cycles(gearbox_sensor_flag);

			if( gearbox_sensor_flag ){
				Turn_On_SW2;
			}
			else{
				Turn_Off_SW2;
			}

			if( trigger_flag ){
				Turn_On_SW3;
			}
			else{
				Turn_Off_SW3;
			}

			if( value > 3 ){
				Turn_On_SW4;
			}
		}//End Main Loop		
}

//Main Interrupt
ISR(PCINT1_vect){	
	gearbox_sensor_flag = (Gearbox_Sensor != 0) ? true : false; 
}//End Main Interrupt

//Function Deifinitions--------------------------------------------------------------------------
bool Fire(bool t_flag){	
	if( t_flag ){
		if( Trigger == 0 )
		{
			Turn_On_Motor;
			t_flag = false;
		}
	}
	return t_flag;
}//End Fire

bool Stop_Firing(bool t_flag){
	if( Trigger != 0 )
	{
		Turn_Off_Motor;	
		t_flag = true;
	}
	return t_flag;
}//End Stop Firing

void Count_Gearbox_Cycles(bool gs_flag){
	static bool cgc_flag;
	if( cgc_flag != gs_flag )
	{
		if( gs_flag )
			value++;
		cgc_flag = gs_flag;
	}
}//End Gearbox Cycle Counter

We are concerned with the Count_Gearbox_Cycles function. I declared this function's return type void because it's only purpose is to increment value by 1 each time Gearbox_Sensor goes high in the main interrupt. However in order to do that properly cgc_flag needs to retain its value between calls and gs_flag needs to be brought into the function each time it is called. I don't see any issues with bringing in gearbox_sensor_flag as a local variable gs_flag in the Count_Gearbox_Cycles function, however it does not count properly when tested, I believe cgc_flag is the culprit, other than making it a global variable, which I actually tried and for some reason that didn't seem to work either, how to make it retain is value between calls?

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

Everything I see would indicate that value is incremented correctly.

What generates the signal to PINC0? If you are sensing a mechanical switch, you are getting bouncing which will totally screw up your counting. Check out:

Mechanical Switch Debouncing
Efficient Key Debounce Code

In particular, I would remove the gearbox sensor from an interrupt. No matter how fast you shift, it is incredibly slow compared to the rate that your AVR can handle interrupts. More to the point, a mechanical switch will generate tens (if not hundreds) of microsecond transitions when going from one state to the next. The AVR will treat each one of those as a shift (yeah, you're doing 10 uS shifts... in your dreams :twisted:).

Instead, simply poll for gear-shift changes in your main loop (using Danni's code above) and go from there.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

I don't see the problem. On a PC (where it's much easier to use printf) I wrote this based on your routine:

#include "stdbool.h"

typedef unsigned char uint8_t;

void Count_Gearbox_Cycles(bool);

uint8_t value;

int main(void) {
	bool local_flag = false;
	int i;
	
	for (i=0; i<20; i++) {
		Count_Gearbox_Cycles(local_flag);
		local_flag = !local_flag;
		printf("i=%02d value=%4d\n", i, value);
	}

	return 0;
}

void Count_Gearbox_Cycles(bool gs_flag){ 
   static bool cgc_flag; 
   if( cgc_flag != gs_flag ) 
   { 
      if( gs_flag ) 
         value++; 
      cgc_flag = gs_flag; 
   } 
}//End Gearbox Cycle Counter 

when run this gives:

D:\c>gear
i=00 value=   0
i=01 value=   1
i=02 value=   1
i=03 value=   2
i=04 value=   2
i=05 value=   3
i=06 value=   3
i=07 value=   4
i=08 value=   4
i=09 value=   5
i=10 value=   5
i=11 value=   6
i=12 value=   6
i=13 value=   7
i=14 value=   7
i=15 value=   8
i=16 value=   8
i=17 value=   9
i=18 value=   9
i=19 value=  10

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

The sensor is not a mechanical switch, but a digital IR photor sensor, there should be no issues as I looked at its output with an old 15mhz scope and it was clean as a whistle, it generates a nice square wave when I rotate the gearbox continuously, and it works perfectly when I place the logic in the function directly in the main loop. I could just place it back in the main loop, but I wanted to the make the code more readable for future modifications, and the time delay for a call is negligable in this applications, so I really want to make thsi work. Any ideas let me know. Thanks for the help!

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

How is the interrupt generated? is it level generated? is it the same line that drives PINC0, if so, won't Gearbox_Sensor always be in the same state in the interrupt, so gearbox_sensor_flag will stay the same, and if its low then value will never be incremented

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

Quote:

Any ideas let me know.

As my test program demonstrated there is NO fault in the routine you identified - it works as one would expect - what do you think is the problem?

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

For some reason I must have had the path for the hex file wrong, when I recompiled and ran it today without making any changes it works perfectly. On a side note, is there a way I can set the default font to consolas for all projects? For some reason when I set the font in a project, save it, close the project and re-open it, its always back to the default font. Thx.