help to correct code speed meter , RPM and distance -pic 16f877 ( UART)

Thread Starter

MCU_1548107851

Joined Jan 21, 2019
30
as i understand i wrote this code and i know its not correct and have some problem

can any one correct it please
---------------------------------------------------------------------------
(( code in file attachment ))
pic16f877A --- result show in nextion lcd ( uart )
target of this code to show in nextion lcd speed ( km/h) and RPM and distance
important note ( wheel diameter 11 cm ) and one round = 36 puls
i use pin B0 ( int ) to count puls
and i used internal timer to give me 1 ms time

--------------------------------------------------------------------------------------
code - mikroc
----------------------------------------
C:
const wh_length=11;
const pulse=36;
const meter_pulse=(100/wh_length)*pulse;
int   meter=0;
char  speedshow[30];
char  RPMshow[30];
char  distanceshow[30];
int   count_puls=0;
int   speed ;
int   rpm=0;
void Interrupcion() iv 0x0004 ics ICS_AUTO
{

  if (INTF_bit==1)
   {
    rpm = (1000/count_puls) * 60;
    speed = meter/count_puls;

   }

  INTF_bit=0;

  if (TMR0IF_bit){
    TMR0IF_bit         = 0;
    TMR0  = 6;
    count_puls++;
  }

}
  void InitTimer0(){
  OPTION_REG         = 0x81;
  TMR0               = 6;
  INTCON             = 0xA0;
}
void main()
{
UART1_Init(115200);
trisb.b0=1;
trisd=0;
InitTimer0();
   t1con=0;
   T1CKPS1_bit=0;
   T1CKPS0_bit=0;

  INTEDG_bit=1;
  INTF_bit=0;
  INTE_bit=1;
   GIE_bit=1;

  while (1)
  {
    if (count_puls>=meter_pulse){
    meter++;
    count_puls=0;
    }
    sprinti(speedshow,"n0.val=%d",speed);
    UART1_Write_Text(speedshow);
    UART1_Write(0XFF);
    UART1_Write(0XFF);
    UART1_Write(0XFF);

    sprinti(RPMshow,"n1.val=%d",RPM);
    UART1_Write_Text(RPMshow);
    UART1_Write(0XFF);
    UART1_Write(0XFF);
    UART1_Write(0XFF);


    sprinti(distanceshow,"n2.val=%d",meter);
    UART1_Write_Text(distanceshow);
    UART1_Write(0XFF);
    UART1_Write(0XFF);
    UART1_Write(0XFF);

  }
}
Mod edit: code=C tag for better formatting - Welcome to AAC!
 

Attachments

Last edited by a moderator:

MaxHeadRoom

Joined Jul 18, 2013
20,707
What is your overall intention? to just measure speed/rate? Or is there any correction involved?
Why not use a timer input as the pulse counter over the time?
I only use Assembly so I cannot judge the code.
Max.
 

Thread Starter

MCU_1548107851

Joined Jan 21, 2019
30
yes i need to measure three thing 1- speed in km/h 2- RPM - 3 - distance

i believe that there is some thing missing in my code that why i ask here
 

LesJones

Joined Jan 8, 2017
2,639
Here is a link to a tachometer that I built several years ago. If you read the software description section I think it will help you to write your code. The source code is also in the link which is written in assembler. I can't help you to to write the code in "C" as I find it much more difficult than assembler.

Les.
 

jayanthd

Joined Jul 4, 2015
904
I ported the CCS PICC code in that book and I got precise result.

rps (revolution per sec) = 1
1 revolution per second
rpm = 1 * 60 = 60

rps = 5
rpm = 5 * 60 = 300

RPM Counter.png RPM Counter2.png
 

jayanthd

Joined Jul 4, 2015
904
The code in page 136 of the book uses 1:2 prescalar for timer1. I have used 1:1 prescalar with 4 MHz Fosc. Here is my working code.

Code:
unsigned long counter = 0;
unsigned long period = 0;
unsigned int currentCaptureTime = 0;
unsigned int previousCaptureTime = 0;
unsigned long rpm = 0;
char msg[17];

void interrupt() {
     if((TMR1IE_bit) && (TMR1IF_bit)) {
         TMR1IF_bit = 0;
         ++counter;
     }
     
     if((CCP1IE_bit) && (CCP1IF_bit)) {
         CCP1IF_bit = 0;
         currentCaptureTime = CCPR1;
         period = counter * (unsigned long)0xFFFF - (unsigned long)previousCaptureTime + (unsigned long)currentCaptureTime;
         rpm = (unsigned long)(60.0e6 / (double)period);
         previousCaptureTime = currentCaptureTime;
         counter = 0;
     }
}

void Delay_XSec(unsigned char sec) {
     while(sec) {
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        sec--;
     }
}

void main() {
    asm clrwdt
    OPTION_REG = 0x8F;
   
    TRISC = 0x84;
    PORTC = 0x00;
   
    UART1_Init(9600);
    Delay_ms(100);
   
    T1CON = 0x01;
    TMR1H = 0x00;
    TMR1L = 0x00;
    TMR1IE_bit = 1;

    CCP1CON = 0x04;
    CCP1IE_bit = 1;

    PEIE_bit = 1;
    GIE_bit = 1;
   
    while(1) {
          asm clrwdt
          LongToStr(rpm,msg);
          Ltrim(msg);
          asm clrwdt
          strcat(msg,"\r\n");
          UART1_Write_Text(msg);
          asm clrwdt
          Delay_XSec(1);
    }
}
 

Thread Starter

MCU_1548107851

Joined Jan 21, 2019
30
The code in page 136 of the book uses 1:2 prescalar for timer1. I have used 1:1 prescalar with 4 MHz Fosc. Here is my working code.

Code:
unsigned long counter = 0;
unsigned long period = 0;
unsigned int currentCaptureTime = 0;
unsigned int previousCaptureTime = 0;
unsigned long rpm = 0;
char msg[17];

void interrupt() {
     if((TMR1IE_bit) && (TMR1IF_bit)) {
         TMR1IF_bit = 0;
         ++counter;
     }
    
     if((CCP1IE_bit) && (CCP1IF_bit)) {
         CCP1IF_bit = 0;
         currentCaptureTime = CCPR1;
         period = counter * (unsigned long)0xFFFF - (unsigned long)previousCaptureTime + (unsigned long)currentCaptureTime;
         rpm = (unsigned long)(60.0e6 / (double)period);
         previousCaptureTime = currentCaptureTime;
         counter = 0;
     }
}

void Delay_XSec(unsigned char sec) {
     while(sec) {
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        sec--;
     }
}

void main() {
    asm clrwdt
    OPTION_REG = 0x8F;
  
    TRISC = 0x84;
    PORTC = 0x00;
  
    UART1_Init(9600);
    Delay_ms(100);
  
    T1CON = 0x01;
    TMR1H = 0x00;
    TMR1L = 0x00;
    TMR1IE_bit = 1;

    CCP1CON = 0x04;
    CCP1IE_bit = 1;

    PEIE_bit = 1;
    GIE_bit = 1;
  
    while(1) {
          asm clrwdt
          LongToStr(rpm,msg);
          Ltrim(msg);
          asm clrwdt
          strcat(msg,"\r\n");
          UART1_Write_Text(msg);
          asm clrwdt
          Delay_XSec(1);
    }
}
thanks alot this code in page 136 :) work fine i will uplode video i show you
the most important with me speed caculation
how to add to this code speed in km/h and mile
and distance
 

jayanthd

Joined Jul 4, 2015
904
thanks alot this code in page 136 :) work fine i will uplode video i show you
the most important with me speed caculation
how to add to this code speed in km/h and mile
and distance
It will be difficult to get the other parameters. I have to think more before I can answer you.

What is your min and max rpm ?
Wheel dia is 11 cm ? So, circumference = 34.56 cm. What vehicle is it ?

I will try to make a code in 1 or 2 days and post it here.

36 pulses = 1 revolution.

In Timer ISR use another counter named pulse (ulong) and test

Code:
if(++pulse >= 36) {
    pulse = 0;
    //distance = distance + (2.0 * 3.14149265 * 11.0 / 2.0);
    distance = distcance + (3.14159265 * 11.0);
}

Try this and tell me what happens.

Code:
void interrupt() {
     if((TMR1IE_bit) && (TMR1IF_bit)) {
         TMR1IF_bit = 0;
         ++counter;
     }
     
     if((CCP1IE_bit) && (CCP1IF_bit)) {
         CCP1IF_bit = 0;
         currentCaptureTime = CCPR1;
         period = counter * (unsigned long)0xFFFF - (unsigned long)previousCaptureTime + (unsigned long)currentCaptureTime;
         rpm = (unsigned long)(60.0e6 / (double)period);
         rps = rpm / 60;
         distance = distance + ((double)rps * 34.55751915e-5);
         
         previousCaptureTime = currentCaptureTime;
         counter = 0;
     }
}
 
Last edited:

Thread Starter

MCU_1548107851

Joined Jan 21, 2019
30
this is video first test for normal counting --

11 dia ( this is not for car this for dc motor

i will uplode another video for test rpm code and more picture for wheel and ir sensor
 

jayanthd

Joined Jul 4, 2015
904
In the video you are showing pulse count and not rpm.

Try this code.

Code:
unsigned long counter = 0;
unsigned long period = 0;
unsigned int currentCaptureTime = 0;
unsigned int previousCaptureTime = 0;
unsigned long rpm = 0;
unsigned int rps = 0;
double distance = 0.0;
double speedKmsPerHour = 0.0;
double speedMilesPerHour = 0.0;
char msg[17];

const code char msg1[] = "RPM:      ";
const code char msg2[] = "Distance: ";
const code char msg3[] = "Speed:    ";

const code char msg4[] = " kms\r\n";
const code char msg5[] = " kms/h\r\n";
const code char msg6[] = " miles/h\r\n";

void interrupt() {
     if((TMR1IE_bit) && (TMR1IF_bit)) {
         TMR1IF_bit = 0;
         ++counter;
     }
  
     if((CCP1IE_bit) && (CCP1IF_bit)) {
         CCP1IF_bit = 0;
         currentCaptureTime = CCPR1;
         period = counter * (unsigned long)0xFFFF - (unsigned long)previousCaptureTime + (unsigned long)currentCaptureTime;
         rpm = (unsigned long)(60.0e6 / (double)period);
         rps = rpm / 60;
         distance = distance + (double)rps * 34.55751915e-5;
         speedKmsPerHour = (double)rps * 34.55751915e-5 * 2.77778e-4;
         speedMilesPerHour = (double)rps * 34.55751915e-5 * 6.21371e-6 * 2.77778e-4;

         previousCaptureTime = currentCaptureTime;
         counter = 0;
     }
}

// copy const to ram string
char *CopyConst2Ram(char *dest, const char *src) {
    char *d;

    d = dest;

    for(;*dest++ = *src++;);

    return d;
}

void Delay_XSec(unsigned char sec) {
     while(sec) {
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        asm clrwdt
        Delay_ms(200);
        sec--;
     }
}

void main() {
    asm clrwdt
    OPTION_REG = 0x8F;

    TRISC = 0x84;
    PORTC = 0x00;

    UART1_Init(9600);
    Delay_ms(100);

    T1CON = 0x01;
    TMR1H = 0x00;
    TMR1L = 0x00;
    TMR1IE_bit = 1;

    CCP1CON = 0x04;
    CCP1IE_bit = 1;

    PEIE_bit = 1;
    GIE_bit = 1;

    while(1) {
          asm clrwdt
          UART1_Write_Text(CopyConst2Ram(msg,msg1));
          LongToStr(rpm,msg);
          Ltrim(msg);
          asm clrwdt
          strcat(msg,"\r\n");
          UART1_Write_Text(msg);
          asm clrwdt
      
          UART1_Write_Text(CopyConst2Ram(msg,msg2));
          FloatToStr(distance,msg);
          Ltrim(msg);
          asm clrwdt
          UART1_Write_Text(msg);
          UART1_Write_Text(CopyConst2Ram(msg,msg4));
          asm clrwdt
      
          UART1_Write_Text(CopyConst2Ram(msg,msg3));
          FloatToStr(speedKmsPerHour,msg);
          Ltrim(msg);
          asm clrwdt
          UART1_Write_Text(msg);
          UART1_Write_Text(CopyConst2Ram(msg,msg5));
          asm clrwdt
      
          UART1_Write_Text(CopyConst2Ram(msg,msg3));
          FloatToStr(speedMilesPerHour,msg);
          Ltrim(msg);
          asm clrwdt
          UART1_Write_Text(msg);
          UART1_Write_Text(CopyConst2Ram(msg,msg6));
          asm clrwdt
      
          Delay_XSec(1);
    }
}

These are same if you use my code or yours.

Code:
[*]rps = rpm / 60;
[*]         distance = distance + (double)rps * 34.55751915e-5;
[*]         speedKmsPerHour = (double)rps * 34.55751915e-5 * 2.77778e-4;
[*]         speedMilesPerHour = (double)rps * 34.55751915e-5 * 6.21371e-6 * 2.77778e-4;
[*]
Try and tell me if you get correct values for distance, speed in kms/hr and miles/hr.
 
Last edited:

Thread Starter

MCU_1548107851

Joined Jan 21, 2019
30
rpm code work vary nice but speed km/h and distance code not working

i change for rpm code some thing and working
but i do same change in code for speed code but not working
((( change only in uart to display to lcd ( nextion )

LongToStr(rpm,msg);
if i keep any converter to string lcd will not work
if delete it it will work (( only rpm code ))
while(1) {
asm clrwdt
// LongToStr(rpm,msg); ////////////////////////// comment
Ltrim(msg);
asm clrwdt
strcat(msg,"\r\n");
sprinti(envia,"n0.val=%d",rpm/1000);
UART1_Write_Text(envia);
UART1_Write(0XFF);
UART1_Write(0XFF);
UART1_Write(0XFF);
asm clrwdt
Delay_XSec(1);
}
}



and
rpm ... speed ...distance code ((not working ))

here what i change
----------------------------------------------------------------------

while(1) {
asm clrwdt
// UART1_Write_Text(CopyConst2Ram(msg,msg1)); ///////////////////// comment
// LongToStr(rpm,msg);
sprinti(show_rpm,"n0.val=%d",rpm/1000);
UART1_Write_Text(show_rpm);
UART1_Write(0XFF);
UART1_Write(0XFF);
UART1_Write(0XFF);*/
Ltrim(msg);
asm clrwdt
strcat(msg,"\r\n");
// UART1_Write_Text(msg);
asm clrwdt

UART1_Write_Text(CopyConst2Ram(msg,msg2));
FloatToStr(distance,msg);
sprinti(show_distance,"n1.val=%d",distance);
UART1_Write_Text(show_distance);
UART1_Write(0XFF);
UART1_Write(0XFF);
UART1_Write(0XFF);
Ltrim(msg);
asm clrwdt
// UART1_Write_Text(msg);
// UART1_Write_Text(CopyConst2Ram(msg,msg4));
asm clrwdt

// UART1_Write_Text(CopyConst2Ram(msg,msg3));
//FloatToStr(speedKmsPerHour,msg);
sprinti(show_speed_km,"n2.val=%d",speedKmsPerHour);
UART1_Write_Text(show_speed_km);
UART1_Write(0XFF);
UART1_Write(0XFF);
UART1_Write(0XFF);
Ltrim(msg);
asm clrwdt
// UART1_Write_Text(msg);
// UART1_Write_Text(CopyConst2Ram(msg,msg5));
asm clrwdt

// UART1_Write_Text(CopyConst2Ram(msg,msg3));
// FloatToStr(speedMilesPerHour,msg);
sprinti(show_speed_Miles,"n3.val=%d",speedMilesPerHour);
UART1_Write_Text(show_speed_Miles);
UART1_Write(0XFF);
UART1_Write(0XFF);
UART1_Write(0XFF);
Ltrim(msg);
asm clrwdt
//UART1_Write_Text(msg);
// UART1_Write_Text(CopyConst2Ram(msg,msg6));
asm clrwdt

Delay_XSec(1);
}
}
 
Top