ISR and LCD

Thread Starter

ActivePower

Joined Mar 15, 2012
155
I have recently started reading on interrupts properly to optimize my code and to prepare for my next project on DC motor control.

To start with, I thought I'd write a small piece of code which increments a counter by 1 every time the motor completes a revolution. I am using the INT interrupt feature of the PIC16F877A and while the interrupt works correctly (I assume. I had an LED glow ON and OFF on each call), it would be nice if I could display the value of the counter on an LCD for debugging/measurement.

I had written a LCD module for a previous project and it worked fine then. However, in conjugation with the interrupt the LCD doesn't seem to be able to display anything yet (in Proteus).

As the LCD routines are working fine (I checked again) and so does the interrupt, could there be any speed issues (is the interrupt occuring too fast to allow the LCD to display/update any values?

Here's the code:


Rich (BB code):
//main.c
//Measure speed of a DC motor using a position encoder

#include <htc.h>
#include "lcd.h"

#define _XTAL_FREQ 200000

__CONFIG (FOSC_HS & WDTE_OFF & PWRTE_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & CP_OFF & WRT_OFF);

#define MOTOR_POS RD3
#define MOTOR_NEG RD4
#define LED RD5

#define COMPLEMENT(x) x=~x

volatile double counter;

void interrupt ISR()
{
	if(INTF)
	{
		__delay_us(500);
		COMPLEMENT(LED);
		counter++;
		INTF=0;
	}	
}



void init()
{
	LCD_Init();
	INTCON=0x10;			//set INT interrupt enable bit
	OPTION_REG=0x80;				//Pullups enabled and rising edge triggering
	TRISB=0xFF;			//configure as inputs
	TRISD=0x00;
	TRISC=0x00;
}

void move_forward()
{
	MOTOR_POS=1;
	MOTOR_NEG=0;
}

void main()
{
	counter=0;
	init();
	ei();					//Global interrupt enable macro
	while(1)
	{
		move_forward();
		LCD_Write((char)counter+48);			//For debug only; write a proper integer to ascii routine later
		__delay_ms(300);
	}
}
Thanks!
 

Attachments

tshuck

Joined Oct 18, 2012
3,534
you really shouldn't use a delay in an interrupt... during this time, your uC can't do anything.... especially since the 16F doesn't have different priority interrupts... my bet is the delay...
 

spinnaker

Joined Oct 29, 2009
7,830
You should NOT be delaying inside the ISR. That is a huge amount of time. Remember everything else stops while the ISR is being processed.

It is what is messing up your timing for your LCD.

Take out the delay and either change the frequency of your timer and/or put in a counter and only process when the counter reaches X.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
I added the delay later to avoid any unwanted updates. Now that I think of it, it was a very stupid thing to do (its not a switch to debounce, after all). I tried removing the delay though and nothing has shown up on the LCD yet.
 

tshuck

Joined Oct 18, 2012
3,534
you have your crystal frequency set to 200kHz, is this correct?

..though I don't think you could run this low in FOSC_HS mode....
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
I am sorry that was a typing mistake. The crystal frequency is 20 MHz, I have edited it now.

Here's the final code:

Rich (BB code):
//main.c
//Measure speed of a DC motor using a position encoder

#include <htc.h>
#include "lcd.h"

#define _XTAL_FREQ 20000000

__CONFIG (FOSC_HS & WDTE_OFF & PWRTE_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & CP_OFF & WRT_OFF);

#define MOTOR_POS RD3
#define MOTOR_NEG RD4
#define LED RD5

#define COMPLEMENT(x) x=~x

volatile double counter;

void interrupt ISR()
{
	if(INTF)
	{
		COMPLEMENT(LED);
		counter++;
		INTF=0;
	}	
}



void init()
{
	LCD_Init();
	INTCON=0x10;			//set INT interrupt enable bit
	OPTION_REG=0x80;				//Pullups enabled and rising edge triggering
	TRISB=0xFF;			//configure as inputs
	TRISD=0x00;
	TRISC=0x00;
}

void move_forward()
{
	MOTOR_POS=1;
	MOTOR_NEG=0;
}

void main()
{
	counter=0;
	init();
	ei();					//Global interrupt enable macro
	while(1)
	{
		move_forward();
		LCD_Write(((char)counter+48));			//For debug only; write a proper integer to ascii routine later
		__delay_ms(500);
	}
}
Nothing yet though! :(
 

tshuck

Joined Oct 18, 2012
3,534
You should try to remove the interrupt portion and ensure the LCD module works, since, you said you compiled it for a different project...
 

ErnieM

Joined Apr 24, 2011
8,415
Unless your motor is turning less then 300 RPM (or 5 Revs Per Second) you stand the chance of updating the display so frequently nothing gets seen. It may seem to work in a simulator but NOT in the real world.

Somewhere in your main loop of code (ie, not inside the ISR) check the revs once or twice a second, and if a new value then update the LCD. Anything much quicker and you may just see a blur on the display.
 

spinnaker

Joined Oct 29, 2009
7,830
I added the delay later to avoid any unwanted updates. Now that I think of it, it was a very stupid thing to do (its not a switch to debounce, after all). I tried removing the delay though and nothing has shown up on the LCD yet.

Have you tried debugging the code? Is it ever reaching the code that writes to the LCD?
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
I am sorry I could not follow up on this thread sooner. Finals are indeed a tough time for any productive work. :)

I am trying to go through my LCD routine again and see if there is anything I might have missed. I'll get back as soon as I am done combing through it.

Thanks for the replies.
 

t06afre

Joined May 11, 2009
5,934
I would also have made it simple. By just writing a hello world message on the display. Just to be sure that part of the program works. In your current setting
 
Last edited:

Thread Starter

ActivePower

Joined Mar 15, 2012
155
I got the program working! It was a very stupid mistake of not having enabled the TRIS registers before I initialized the LCD in my main program. Working on the ASCII conversion now.

Thanks everyone for the useful help :)
 

tshuck

Joined Oct 18, 2012
3,534
I got the program working! It was a very stupid mistake of not having enabled the TRIS registers before I initialized the LCD in my main program. Working on the ASCII conversion now.

Thanks everyone for the useful help :)
Glad to hear it, though we probably could have gotten there sooner if you had posted what LCD_Init(); did.:p

I had assumed that it simply set up ports, obviously I, instead, managed to make a donkey out of us....
 

ErnieM

Joined Apr 24, 2011
8,415
... Working on the ASCII conversion now.
You should have those in your libraries. Look for atoi() (ASCII to int) or itoa() (int to ASCII). atoi() lives inside stdlib.h, and in some versions so does itoa(), but that is so simplemany people just make their own (or copy code off the web).
 
Top