Events management (Part 1)

Part 123

Managing events in an (hopefully) intelligent manner is the primary objective for designing a microcontroller based application. I am opening this endless topic in order to compare the various solutions apllicable to the management of events.

As a starter, we will only use one input line and one output led. Next exemple illustrates the most basic application. For the sake of code readability, the status reading and the related action are written in separate routines. The loop() routine will sequencially read the status and store it in a global variable in the readState() routine, while the writeState() routine will read this variable and turn the control led accordingly.

#define PIN_PUSHBUTTON PIND2
#define LED_PIN PINB5
byte pushButtonState = 0x00; // Ground true

void setup(void) {
  // Setup input pin
	DDRD  &= ~(1 << PIN_PUSHBUTTON);
	// Bias input pin
	PORTD |=  (1 << PIN_PUSHBUTTON);
	// Set led pin as output
	DDRB  |=  (1 << LED_PIN);	
	// Functions
	blinkLed(5, 200);
}

void loop(void) {
	// Read push button state and turn led on or off accordingly
  readState(); // read pushbutton state
	writeState(); // write pushbutton state on led output
	// Do something else here
	delay(10);
}

void readState(void) {
// Read pushbutton state (Ground true)
  pushButtonState = ((~PIND >> PIN_PUSHBUTTON) & 0x01); 
}

void writeState() {
// Write pushbutton state on led output
	if (pushButtonState) 
		PORTB |=  (1 << LED_PIN); // Turn led on
	else 
		PORTB &= ~(1 << LED_PIN); // Turn led off
}

 void blinkLed(int nbrBlinks, int intervals){
// Blink status led
	for (int i = 0; i < (nbrBlinks * 2); i++) {
		PORTB ^=  (1 << LED_PIN); // toggle status led
		delay (intervals);
	}
}

Problem is that the additional code in the loop() routine may last varaiable time, so that the pushbutton status is read on an undefined time basis (may be too fast or too slow).

A first approach would be to trigger the read and write routines at constant time intervals. This is done using the millis() function:

#define PIN_PUSHBUTTON PIND2
#define LED_PIN PINB5
byte pushButtonState = 0x00; // Ground true
long interval = 100;
long lastTime = 0; 

void setup(void) {
  // Setup input pin
	DDRD  &= ~(1 << PIN_PUSHBUTTON);
	// Bias input pin
	PORTD |=  (1 << PIN_PUSHBUTTON);
	// Set led pin as output
	DDRB  |=  (1 << LED_PIN);	
	// Set global variable
	lastTime = millis();
	// Functions
	blinkLed(5, 200);
}

void loop(void) {
	long now = millis();
	if ((now - lastTime) >= interval) {
		// Read push button state and turn led on or off accordingly
		readState(); // read pushbutton state
		writeState(); // write pushbutton state on led output
		lastTime = now; // record time at which last event management occured
	}
	// Do something else here
	delay(10);
}

void readState(void) {
// Read pushbutton state (Ground true)
  pushButtonState = ((~PIND >> PIN_PUSHBUTTON) & 0x01); 
}

void writeState() {
// Write pushbutton state on led output
	if (pushButtonState) 
		PORTB |=  (1 << LED_PIN); // Turn led on
	else 
		PORTB &= ~(1 << LED_PIN); // Turn led off
}

 void blinkLed(int nbrBlinks, int intervals){
// Blink status led
	for (int i = 0; i < (nbrBlinks * 2); i++) {
		PORTB ^=  (1 << LED_PIN); // toggle status led
		delay (intervals);
	}
}

Problem now is that we cannot track changes during the interval period of time. The answer to this is “external interrupts” that we will discuss in a next post

Next post on same subject

Leave a Reply

You must be logged in to post a comment.