Pic 16f628a comparator intterupts

General discussion on mikroC.
Post Reply
Author
Message
rharmsen
Posts: 6
Joined: 11 Jan 2010 00:38

Pic 16f628a comparator intterupts

#1 Post by rharmsen » 29 Mar 2010 19:21

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

Nick101
Posts: 339
Joined: 06 Aug 2006 15:32
Location: Texas
Contact:

Re: Pic 16f628a comparator intterupts

#2 Post by Nick101 » 30 Mar 2010 00:23

Hi,
Did you see number 8 on LCD line 1 and testing... on LCD line 2 at the first start program?
Nick
[url]http://www.pic_examples.byethost3.com/[/url]

rharmsen
Posts: 6
Joined: 11 Jan 2010 00:38

Re: Pic 16f628a comparator intterupts

#3 Post by rharmsen » 30 Mar 2010 09:44

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).

Nick101
Posts: 339
Joined: 06 Aug 2006 15:32
Location: Texas
Contact:

Re: Pic 16f628a comparator intterupts

#4 Post by Nick101 » 30 Mar 2010 12:57

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;

}
Nick
[url]http://www.pic_examples.byethost3.com/[/url]

rharmsen
Posts: 6
Joined: 11 Jan 2010 00:38

Re: Pic 16f628a comparator intterupts

#5 Post by rharmsen » 30 Mar 2010 23:24

Thnks for relpying,

I tried it, it seems it does something more, but it **** up my LCD screen, it keeps blinking with random characters.

Nick101
Posts: 339
Joined: 06 Aug 2006 15:32
Location: Texas
Contact:

Re: Pic 16f628a comparator intterupts

#6 Post by Nick101 » 31 Mar 2010 01:18

Hello,
The tekst is declare as a pointer. I think it's suppose to be an array. try this:

Code: Select all

char tekst[7];
Nick
[url]http://www.pic_examples.byethost3.com/[/url]

rharmsen
Posts: 6
Joined: 11 Jan 2010 00:38

Re: Pic 16f628a comparator intterupts

#7 Post by rharmsen » 31 Mar 2010 17:12

NICE thanks man, that was indeed the problem.

FreeMan
Posts: 38
Joined: 25 Jul 2006 04:32

Re: Pic 16f628a comparator intterupts

#8 Post by FreeMan » 08 Apr 2010 17:15

Peace be with you

how about changing in your program the line :

Code: Select all

  PIR1.CMIE = 1;
by the line :

Code: Select all

   PIE1.CMIE = 1;
PIR1 is a flag register, PIE1 is interrupt register. If possible let me know how it goes.

Peace be with you
freeman

rharmsen
Posts: 6
Joined: 11 Jan 2010 00:38

Re: Pic 16f628a comparator intterupts

#9 Post by rharmsen » 08 Apr 2010 17:44

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);
}

FreeMan
Posts: 38
Joined: 25 Jul 2006 04:32

Nice program you have there

#10 Post by FreeMan » 13 Apr 2010 15:19

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

rharmsen
Posts: 6
Joined: 11 Jan 2010 00:38

Re: Pic 16f628a comparator intterupts

#11 Post by rharmsen » 13 Apr 2010 20:43

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);
}

Post Reply

Return to “mikroC General”