Re: Displaying RPM on LCD Help pls mikroc code

Thread Starter

vivek1925

Joined May 12, 2010
11
Hi People,

I am trying to calculate the RPM of a bicycle and I have written the code in mikroc for calculating the time it takes for falling and the rising edge of a reed switch which is connected to the rear wheel.

Therefore 1 pulse = 1 revolution in this case, so I have attached the code below and for testing purpose I have created a simulation phase which will display the RPM on a LCD but the LCD does not display it for some reason!

I used the CCP2CON register RC1 to capture the falling and the rising edge.

All I see is '1' displayed on the LCD with the welcome text.

This is the code:

//#include <stdio.h>
char *text = "Cadence";
char buffer[20];
//char *text1 = "RPM";
float Rpm;
unsigned int Rot_time = 0;
unsigned short Pulse_HSL; // holding falling edge time for start of timing sequence
unsigned int Pulse_HSH;
unsigned short Pulse_EL; // rising edge for end time sequence
unsigned int Pulse_EH;
//unsigned float Rot_PH = 0;
//unsigned float Rot_PL = 0;
void main()
{
Soft_Uart_Init(PORTC,7,6,57600,0);
delay_ms(500);
PORTB = 0;
TRISB = 0;
TRISD = 0; //Set all PORTD for output
PORTD = 0;
TRISC = 0x02; //RC1 as input for CCP2
Lcd_Init(&PORTB);
Lcd_Cmd(Lcd_clear);
Lcd_Out(1 ,1 ,text);

INTCON = 0; //Disable all Interrupts for initialization of other registers
T3CON = 0; //0000 0000 was $C0 Sets Timer1 as source clock for CCP1 and CCP2 leaves timer3 off
CCP2CON = 0x04; // set for every faling edge, 05 every rising edge capture
//CCP2CON = 0x06; //set for 4th rising edge, $07 Initially Set CCP2 for 16th Rising Edge Capture
T1CON = 0x01; //set for 8 bit time read, prescaler of 1 and turn timer 1 on
//T1CON = 0x81; // set for 16bit read, prescaler 1 and timer1on
TMR1L = 0x00; //zero timer registers
TMR1H = 0x00;
INTCON = 0xC0; //Enable Interrupts

while(1)
{
//Lcd_cmd(Lcd_clear);
//delay_ms(1000);
if(PIR2.CCP2IF == 0 && CCP2CON == 0x04) // if flag is set and pulse is trigerred
Rot_time = (Pulse_EH<<8|Pulse_EL) - (Pulse_HSH<<8|Pulse_HSL);
Rpm = 240000000/Rot_time;//combining both hi and low byte of rotation period
wordtostr(Rpm,buffer);
//sprintf(buffer, "%12s", Rpm); // this is taking F* lot of ROM locations
Lcd_Out(2,1,buffer); // Print text on LCD
Soft_Uart_write(buffer);

}
}

void interrupt()
{
//INTCON.GIE = 0; // clearing GIE to prevent any other interrupts while handling this one

if(PIR2.CCP2IF == 1)
{
switch(CCP2CON)
{
case 0x04: // start time of the sequence i.e. falling edge and gets start time
Pulse_HSL = CCPR2L; // capture pulse high start time
Pulse_HSH = CCPR2H; // get captured time high byte
CCP2CON = 0x05;
PIR2.CCP2IF = 0; // reset the flag
break;

case 0x05: // end time sequence so timing sequence complete, calculate time intervals
Pulse_EL = CCPR2L; // get time of the rising edge
Pulse_EH = CCPR2H;
//Rot_PL = Pulse_EL - Pulse_HSL; // rotation time = Pulse time HI + pulse time LOW
//if(STATUS == 0){ Pulse_EH = Pulse_EH - 1; }
//Rot_PH = Pulse_EH - Pulse_HSH;
CCP2CON = 0x04; // set start next timing sequence for falling edge.
PIR2.CCP2IF = 0;
break;

default: rpm = 0;
} // switch
} // if

} // interrupt

The text i.e in red is the code where I am printing the RPM on a LCD.
I have also attached the schematic where you can test the code and see the LCD output for your reference.

Please help me resolve this issue, I am using Mikroc v8.2 and PIC18f452 with 16mhz. I used Proteus professional simulation software for generating the schematic.

If you have any other question please feel free to reply me!

Cheers
vivek
 

Attachments

Thread Starter

vivek1925

Joined May 12, 2010
11
Hi,

Sorry for the previous post, here is what you asked for!

Rich (BB code):
//#include <stdio.h>
char *text = "Cadence";
char buffer[20];
//char *text1 = "RPM";
float Rpm;
unsigned int Rot_time = 0;
unsigned short Pulse_HSL;   // holding falling edge time for start of timing sequence
unsigned int Pulse_HSH;
unsigned short Pulse_EL;   // rising edge for end time sequence
unsigned int Pulse_EH;
//unsigned float Rot_PH = 0;
//unsigned float Rot_PL = 0;
void main()
{
      Soft_Uart_Init(PORTC,7,6,57600,0);
      delay_ms(500);
      PORTB = 0;
      TRISB = 0;
      TRISD = 0;  //Set all PORTD for output
      PORTD = 0;
      TRISC = 0x02;  //RC1 as input for CCP2
      Lcd_Init(&PORTB);
      Lcd_Cmd(Lcd_clear);
      Lcd_Out(1 ,1 ,text);

      INTCON  = 0;  //Disable all Interrupts for initialization of other registers
      T3CON   = 0;  //0000 0000  was $C0 Sets Timer1 as source clock for CCP1 and CCP2 leaves timer3 off
      CCP2CON = 0x04; // set for every faling edge, 05 every rising edge capture
      //CCP2CON = 0x06;  //set for 4th rising edge, $07 Initially Set CCP2 for 16th Rising Edge Capture
      T1CON   = 0x01;  //set for 8 bit time read, prescaler of 1 and turn timer 1 on
      //T1CON = 0x81; // set for 16bit read, prescaler 1 and timer1on
      TMR1L   = 0x00; //zero timer registers
      TMR1H   = 0x00;
      INTCON  = 0xC0;  //Enable Interrupts

while(1)
{
      //Lcd_cmd(Lcd_clear);
      //delay_ms(1000);
      if(PIR2.CCP2IF == 0 && CCP2CON == 0x04) // if flag is set and pulse is trigerred
      Rot_time = (Pulse_EH<<8|Pulse_EL) - (Pulse_HSH<<8|Pulse_HSL);
      Rpm = 240000000/Rot_time;//combining both hi and low byte of rotation period
      wordtostr(Rpm,buffer);
      //sprintf(buffer, "%12s", Rpm);     // this is taking F* lot of ROM locations
      Lcd_Out(2,1,buffer);     // Print text on LCD
      Soft_Uart_write(buffer);

}
}
void interrupt()
{
      //INTCON.GIE = 0; // clearing GIE to prevent any other interrupts while handling this one

      if(PIR2.CCP2IF == 1)
      {
        switch(CCP2CON)
        {
          case 0x04: // start time of the sequence i.e. falling edge and gets start time
          Pulse_HSL = CCPR2L; // capture pulse high start time
          Pulse_HSH = CCPR2H; // get captured time high byte
          CCP2CON = 0x05;
          PIR2.CCP2IF = 0; // reset the flag
          break;

          case 0x05: // end time sequence so timing sequence complete, calculate time intervals
          Pulse_EL = CCPR2L; // get time of the rising edge
          Pulse_EH = CCPR2H;
          //Rot_PL = Pulse_EL - Pulse_HSL; // rotation time = Pulse time HI + pulse time LOW
          //if(STATUS == 0){ Pulse_EH = Pulse_EH - 1; }
          //Rot_PH = Pulse_EH - Pulse_HSH;
          CCP2CON = 0x04; // set start next timing sequence for falling edge.
          PIR2.CCP2IF = 0;
          break;

          default:  rpm = 0;
         } // switch
       }  // if
       
}   // interrupt
Cheers
vivek
 

Motardo

Joined Sep 21, 2011
22
In your main(), while(1) you write
if(PIR2.CCP2IF == 0 && CCP2CON == 0x04) // if flag is set and pulse is trigerred
Do you mean if(PIR2.CCP2IF == 1 ...?
Also your Pulse_HSL, etc variables should be defined as volatile or the compiler might skip generating code to actually read their values.
 

Yako

Joined Nov 24, 2011
245
I like MikroC, it is a very underrated compiler in my opinion.

It can be tricky sometimes; things need to be in the right order.

PIC18f452 is bit of an overkill for your project.
 
Last edited:

absf

Joined Dec 29, 2010
1,968
I am trying to calculate the RPM of a bicycle and I have written the code in mikroc for calculating the time it takes for falling and the rising edge of a reed switch which is connected to the rear wheel.

Therefore 1 pulse = 1 revolution in this case, so I have attached the code below and for testing purpose I have created a simulation phase which will display the RPM on a LCD but the LCD does not display it for some reason!

I used the CCP2CON register RC1 to capture the falling and the rising edge.

All I see is '1' displayed on the LCD with the welcome text.
I found a couple of mistakes in your schematic. You put your xtal on pin 7 and 14 which should be 13 & 14. Though this doesn't hurt as you already defined the osc freq inside the PIC. But on the real HW it would not work.

You also connected the counter/timer to the input CCP2A with a switch pulled high with 100K. I know you want to send pulses to the CCP using the switch but how fast can you press the switch? What you need to connect to this point is a function generator. Set it to square wave of about 10 Hz should do.

Have you corrected your software and try again?

Allen
 
Top