Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PIC18F4550 based strboscope and Tachometer problem.

Status
Not open for further replies.

nick703

Advanced Member level 1
Joined
Oct 17, 2011
Messages
422
Helped
21
Reputation
44
Reaction score
22
Trophy points
1,298
Location
surat
Activity points
3,987
Hello,
Actually my application is i want to measure RPM and this RPM to flashing LED to generate freeze motion using PIC18F4550 and XC compiler. So after searching many artical and doing some code and below is the problem.
1) measure RPM is a half of Actual RPM.
means if i measure using instrument that time i can see 1800 RPM but in LCD i got 900 RPM.

2) And Second Problem is i didn't Freeze my motion using RPM .
My calculation is RPM = FPM (Frequency Per Minute).
So i have Genrate Delay using this RPM is that wrong?
Please help me to resolve the issue. below is my code
Code:
#include "Configuration_Header_File.h"
#include "LCD_8bit_file.h"

#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

// CONFIG1H
#pragma config FOSC = INTOSC_EC // Oscillator Selection bits (Internal oscillator, CLKO function on RA6, EC used by USB (INTCKO))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

void Timer1_start();
void Timer0_config();


#define StrobePulse      LATDbits.LATD2
#define MeasurePin       LATAbits.LATA4

#define _XTAL_FREQ 4000000

char message1[] = "Tachometer";
unsigned long int count = 0;
unsigned long RPM_Value;


void main()
{ 
    OSCCON=0x72;    /* Configure oscillator frequency to 8MHz */
    TRISB = 0;      /* Set as output Port */
    TRISA= 0x10;
    Pulse = 1;   /* send high on PortB */
    LCD_Init();
    Timer0_config();
    Timer1_start();
    LCD_Command(0xC0);
    LCD_String_xy(1,4,message1); 
    while(1)
    {
        TMR0ON = 1;
        TMR0L = 0;
        TMR0H = 0;
        MeasurePin = 1;
        __delay_ms(1000);
        MeasurePin = 0;
        TMR0ON = 0;    // Stop the timer
        RPM_Value = TMR0 * 60;
        Display_RPM(RPM_Value);
    };
    
}
/*********************Interrupt Service Routine for Timer1************************/

void interrupt Timer1_ISR()
{
    if(PIR1bits.TMR1IF)
    {

        TMR1 = RPM_Value / 60;
        StrobePulse= ~StrobePulse;
        PIR1bits.TMR1IF=0; /* Make Timer1 Overflow Flag to '0' */
        
    }
}

void Timer1_start()
{
    GIE=1;              /* Enable Global Interrupt */
    PEIE=1;             /* Enable Peripheral Interrupt */
    TMR1IE=1;           /* Enable Timer1 Overflow Interrupt */
    TMR1IF=0;
    T1CON=0x80;         /* Enable 16-bit TMR1 Register,No pre-scale,use internal clock,Timer OFF */
    //TMR1=0xF830;        /* Load Count for generating delay of 1ms */
    TMR1=0xF97D;        /* Load Count for generating delay of 1us */
    //TMR1=0xFF38;        /* Load Count for generating delay of 1us */
    TMR1ON=1;           /* Turn-On Timer1 */
}

void Timer0_config()
{
    T0CON = 0b00101000;
}


 
void Display_RPM(unsigned int num)
{
    char TempA = 0, TempB = 0, TempC = 0, TempD = 0, TempE = 0, TempF = 0;
    unsigned int Temp = num;
    char MessageFrame[8];
    
    TempA = Temp / 100000;
    Temp = Temp % 100000;
    TempB = Temp / 10000;
    Temp = Temp % 10000;
    TempC = Temp / 1000;
    Temp = Temp % 1000;
    TempD = Temp / 100;
    Temp = Temp % 100;
    TempE = Temp / 10;
    TempF = Temp % 10;

    MessageFrame[0] = TempA + 0x30;
    MessageFrame[1] = TempB + 0x30;
    MessageFrame[2] = TempC + 0x30;
    MessageFrame[3] = TempD + 0x30;
    MessageFrame[4] = TempE + 0x30;
    MessageFrame[5] = TempF + 0x30;
    
    LCD_String_xy(2,4,MessageFrame);
}

please give me Some advise i want to correct RPM and that RPM to flashing LED to freeze motion.
 

I'm not sure I understand your logic (as embodied in the code) but there are some more fundamental questions to begin with.
How are you begin told about each revolution of the 'wheel under test' (for lack of a better name)?
Are you getting a pulse delivered to an input pin? If so then why not use the Capture mode of the CCP module in the MCU. That way the hardware will automatically capture the timer value and all you need to do is to measure the difference between each capture. If you set up the timer to count at a suitable rate (i.e. whatever resolution you require) then it can be straight forward to convert the time difference to RPM.
Side issue: in an ISR when you reset these 'old style' timers (that don't have the PRx registers, and that count up from a preset value to the 0xffff overflow situation), you need to take into account the fact that the timer can very well have counted more 'ticks' while reacting to the interrupt trigger. Therefore it is more usual to calculate the reset value (65536-the required count) and then add that to the TMRx register which provides a much more accurate timing for the next interrupt.
I don't think you have the setup and reset values for Timer1 correct (but I'm not sure - as I say I can;t really follow the logic here). As I mentioned before, these timers count UP from a preset value until they overflow. I don't think your simply setting the number to 'RPM_Value/60' is necessarily correct.
In your 'Display_RPM' function, how many bits are in the 'unsigned int' value that you pass in? According to the XC8 User Guide, the default for 'unsigned int' is 16 bits, so dividing by 100000 (which requires more than 16 bits to represent) will always result in TempA being 0.
Also you should explicitly make "MessageFrame[6]='\0'" (i.e. null terminating the string) rather than hoping the location on the stack will be 0. You might get additional characters displayed on the LCD becasue of a badly terminated string passed to 'LCD_String_xy'.
Finally, I'd cut down your code yo get the RPM counting code working first and later on add in the LED strobing code. Solve one problem at a time.
Susan
 

thanks for your reply Aussie Susan Now i just split my code and complete the RPM task using pic microcontorller CCP module. please find the below code and please tell me if i am wrong.

Code:
#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>

#define f_timer 2000000
void Display_RPM(unsigned long num);
void main()
{
    unsigned long pulse,data1,data2;
    float period;
    float frequency;
    unsigned long RPM;
    
    TRISCbits.TRISC2=1;
    OSCCON=0x72;        /* set internal clock to 8MHz */
    LCD_Init();
    PIE1bits.CCP1IE=1;
    PIR1bits.CCP1IF=0;     
    CCP1CON=0x05;       /* Capture mode is selected for detecting Rising edge */
    CCPR1=0x00;         /*CCPR1 is capture count Register which is cleared initially*/
    TMR1IF=0;           
    T1CON=0xB0;         /* Enable 16-bit TMR1 Register,1:8 pre-scale,use internal clock,Timer OFF */
    TMR1=0;
    T1CONbits.TMR1ON=1; /* Turn-On Timer1 */        
    while(1)        
    {               
        while(!(PIR1bits.CCP1IF));  /*Wait for Interrupt flag which is generated when edge is detected*/
            data1=CCPR1;            /*Copy count of 1st edge detected*/        
            PIR1bits.CCP1IF=0;
        while(!(PIR1bits.CCP1IF));  /*Wait for Interrupt flag which is generated when edge is detected*/
            data2=CCPR1;            /*Copy count of 2nd edge detected*/
            PIR1bits.CCP1IF=0;
          
        if(data1<data2)
            {    
            /*Calculation for Pulse width Measurement*/
            pulse = data2 - data1;
            period= ((float)pulse/(float)f_timer);    /*Count for 1 cycle*0.5us gives period */
            frequency = 1/ (period * 8);         /*  Prescale of timer 1 is 8*/
            RPM = frequency * 60;               /* for RPM */
            Display_RPM(RPM);
        }
        TMR1=0;
    }                              
}


void Display_RPM(unsigned long num)
{
    char MessageFrame[8];

    MessageFrame[0] =  num/10000 + 0x30;
    MessageFrame[1] = (num/1000)%10 + 0x30;
    MessageFrame[2] = (num/100)%10 + 0x30;
    MessageFrame[3] = (num/10)%10  + 0x30;
    MessageFrame[4] =  num%10 + 0x30;
    
    LCD_String_xy(2,4,MessageFrame);
}


Now please tell me how can i do with this RPM to generate stroboscope to freeze motion. as per i reading article RPM = FPM . SO i have to genrate frequency as RPM rate or else?
 

Firstly does the code you have written for the RPM measurement work?
You have not posted all of your code - it finishes part way through the first 'if' in the main loop - but I suspect that it might be a test to see if the counter has wrapped around. If so, remember that you are dealing with 16-bit unsigned values and therefore you don't need to worry about the wrap around. Simply subtract the 1st value from the 2nd and you will always get the correct difference. (Try it on paper if you are not sure about this.)
Also, I suspect that you are mixing interrupt and non-interrupt usage of the peripheral. I can see that you are setting the IE bit which means that when the peripheral raises it s IF bit, it will trigger an interrupt. Unless you write an ISR to handle this, your program will (probably) reset. However you have code that tests for the IF bit being set so you don't need the interrupt (at this stage - you might later on but that is for another time). I'd take out the code that sets the IE bit.
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top