Page 1 of 1
Pic 16f628a comparator intterupts
Posted: 29 Mar 2010 19:21
by rharmsen
Hello all,
I am trying to program a 16f628a to count objects passing by an infrared-sensor.
My sensor is working. Using the 2nd comparator in the 16f628a. If I use this code in a continues loop it shows OFF if I hold my hand in the sensor, and ON if I pull it out.
Code: Select all
if (CMCON.C2OUT == 1)
{
LCD_Out(1,5, "off");
PIR1.CMIF = 0;
}
else
{
LCD_Out(1,5, "on ");
}
But this is not fast/accure if something passes it (falling object). So I want to use interrupts, but I can't get it to work.
This is my code
Code: Select all
int counter = 8;
char *tekst;
void interrupt(){
counter++;
PIR1.CMIF = 0;
}
void main() {
VRCON = 0b11001111;
CMCON = 0b00100101;
TRISA = 0b11111111;
TRISB = 0b00000000;
Delay_ms(100);
PIR1.CMIF = 0;
PIR1.CMIE = 1;
INTCON.PEIE = 1;
INTCON.GIE = 1;
Lcd_Config(&PORTB, 2, 3, 1, 7, 6, 5, 4);
LCD_Cmd(LCD_CLEAR);
LCD_Cmd(LCD_CURSOR_OFF);
LCD_Out(2,2, "testing...");
do {
IntToStr(counter,tekst);
LCD_Out(1,1,tekst);
delay_ms(100);
} while(1);
}
What am I doing wrong with the interrupts?
Thanks in advance,
Ruud
Re: Pic 16f628a comparator intterupts
Posted: 30 Mar 2010 00:23
by Nick101
Hi,
Did you see number 8 on LCD line 1 and testing... on LCD line 2 at the first start program?
Re: Pic 16f628a comparator intterupts
Posted: 30 Mar 2010 09:44
by rharmsen
Yes, the LCD works fine. But the 8 doesn't increase when I put my hand in the sensor. So my comparator doesn't create an interrupts (at least, that is what I am thinking).
Re: Pic 16f628a comparator intterupts
Posted: 30 Mar 2010 12:57
by Nick101
Hi,
according to its datasheet, CMCON must be read or write to clear mismatch before CMIF can be clear. Try this :
Code: Select all
char temp;
void interrupt(){
counter++;
temp = CMCON;
PIR1.CMIF = 0;
}
Re: Pic 16f628a comparator intterupts
Posted: 30 Mar 2010 23:24
by rharmsen
Thnks for relpying,
I tried it, it seems it does something more, but it **** up my LCD screen, it keeps blinking with random characters.
Re: Pic 16f628a comparator intterupts
Posted: 31 Mar 2010 01:18
by Nick101
Hello,
The tekst is declare as a pointer. I think it's suppose to be an array. try this:
Re: Pic 16f628a comparator intterupts
Posted: 31 Mar 2010 17:12
by rharmsen
NICE thanks man, that was indeed the problem.
Re: Pic 16f628a comparator intterupts
Posted: 08 Apr 2010 17:15
by FreeMan
Peace be with you
how about changing in your program the line :
by the line :
PIR1 is a flag register, PIE1 is interrupt register. If possible let me know how it goes.
Peace be with you
freeman
Re: Pic 16f628a comparator intterupts
Posted: 08 Apr 2010 17:44
by rharmsen
This is my final working solution:
Code: Select all
int counter;
char tekst[7];
int increased = 0;
unsigned char y[4];
void interrupt(){
if(PIR1.CMIF){ // interrupt from comparators...
if (CMCON.C2OUT == 1 && !increased)
{
counter++; // increase counter
increased = 1;
}
if (CMCON.C2OUT == 0)
{
PIR1.CMIF = 0; // flag reset
}
}
}
void init() {
VRCON = 0b11001111; // Set voltage reference register
CMCON = 0b00100110; // Enable comparators
TRISA = 0b11111111; // Set Port A as input
TRISB = 0b00000000; // Set Port B as output
Delay_ms(100);
PIE1.CMIE = 1; // Enable comparator interrupt
PIR1.CMIF = 0; // Reset comparator interrupt
INTCON.PEIE = 1; // Peripheral interrupt enable bit
INTCON.GIE = 1; // Enable global interrupt
}
void loadFromEeprom() {
y[0] = EEprom_Read(0);
y[1] = EEprom_Read(1);
y[2] = EEprom_Read(2);
y[3] = EEprom_Read(3);
counter = (y[3]<<24)|(y[2]<<16)|(y[1]<<8)|(y[0]);
increased = 0;
}
void writeToEeprom() {
y[0] = counter & 0x000000ff;
y[1] = (counter & 0x0000ff00) >> 8;
y[2] = (counter & 0x00ff0000) >> 16;
y[3] = (counter & 0xff000000) >> 24;
EEprom_Write(0,y[0]);
EEprom_Write(1,y[1]);
EEprom_Write(2,y[2]);
EEprom_Write(3,y[3]);
}
void displayCount() {
IntToStr(counter,tekst);
LCD_Out(2,4,tekst);
}
void main() {
init();
Lcd_Config(&PORTB, 2, 3, 1, 7, 6, 5, 4);
LCD_Cmd(LCD_CLEAR);
LCD_Cmd(LCD_CURSOR_OFF);
LCD_Out(1,1, "Bierdopjescount");
loadFromEeprom();
displayCount();
do {
if (increased)
{
displayCount();
increased = 0;
writeToEeprom();
}
delay_ms(50);
} while(1);
}
Nice program you have there
Posted: 13 Apr 2010 15:19
by FreeMan
peace be with you
i notice you had did the changes, that is good that works now, and how about doing little improvment in the program:
Code: Select all
int counter Absolute 0x20 ' reserve the adress
char y[4] Absolute 0x20 ' over lapping variables
and those procedure by these:
Code: Select all
void loadFromEeprom() {
y[0] = EEprom_Read(0);
y[1] = EEprom_Read(1);
y[2] = EEprom_Read(2);
y[3] = EEprom_Read(3);
increased = 0;
}
void writeToEeprom() {
EEprom_Write(0,y[0]);
EEprom_Write(1,y[1]);
EEprom_Write(2,y[2]);
EEprom_Write(3,y[3]);
}
since the introduction of the 2 lines on the top then the conversion between the bytes and the int is not required anymore.
PS: i do not program in 'C' language, and i think that:
'int' is a 16 bits variable, and in the program a long variable is required, so maybe we should change 'int' by 'unsigned long' therefore the first 2 lines would be like this:
Code: Select all
unsigned long counter Absolute 0x20 ' reserve the adress
char y[4] Absolute 0x20 ' over lapping variables
I thank you for sharing your code and please if i made any mistake correct me, and maybe the compiler help would be possible so see diffrent variables and size which can be declared.
peace be with you
Re: Pic 16f628a comparator intterupts
Posted: 13 Apr 2010 20:43
by rharmsen
Thanks for replying,
The integer is value between (-32768 and 32767) so 17bit( i guess, not sure), but because I use the positive side only I could indeed use a 16 bit value, so I shouldn't need 4 bytes but 2 would be enough :p
I tried removing the 'counter' variable from the code but in my interrupt routine, I increase the counter. But just renaming counter ++ to y++ won't work (wich isn't strange ofcorse because y is an array of chars and not an integer).
I tried to solve this like this (not sure if it works yet, because a problem with writing the text to the screen, can't just write the byte array to string):
Code: Select all
void interrupt(){
if(PIR1.CMIF){ // interrupt from comparators...
if (CMCON.C2OUT == 1 && !increased)
{
// increase counter
y[1]++;
if (y[1] == 0)
y[0]++;
}
if (CMCON.C2OUT == 0)
{
PIR1.CMIF = 0; // flag reset
}
}
}
But now my problem is in the displayCount()
Code: Select all
void loadFromEeprom() {
y[0] = EEprom_Read(0);
y[1] = EEprom_Read(1);
//y[2] = EEprom_Read(2);
//y[3] = EEprom_Read(3);
//counter = (y[3]<<24)|(y[2]<<16)|(y[1]<<8)|(y[0]);
increased = 0;
}
void writeToEeprom() {
//y[0] = counter & 0x000000ff;
//y[1] = (counter & 0x0000ff00) >> 8;
//y[2] = (counter & 0x00ff0000) >> 16;
//y[3] = (counter & 0xff000000) >> 24;
EEprom_Write(0,y[0]);
EEprom_Write(1,y[1]);
//EEprom_Write(2,y[2]);
//EEprom_Write(3,y[3]);
}
void displayCount() {
IntToStr(y,tekst);
LCD_Out(2,4,tekst);
}