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.

[PIC] PIC18f4431 and Micro-C Pro code for LCD display?

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
PIC18f4431 and Micro C Pro code for LCD display ?

Hello Friends,

I have a pic18f4431 and micro c pro to use dispaly LCD . and I use external oscillator 20MHz. but My problem is LCD take time to operate and not working in real time means lcd display but take to much time . below is my code
Code:
unsigned long RPM_Value;

// Define LCD module connections.
 sbit LCD_RS at RB3_bit;
 sbit LCD_EN at RB2_bit;
 sbit LCD_D4 at RB4_bit;
 sbit LCD_D5 at RB5_bit;
 sbit LCD_D6 at RB6_bit;
 sbit LCD_D7 at RB7_bit;
 sbit LCD_RS_Direction at TRISB3_bit;
 sbit LCD_EN_Direction at TRISB2_bit;
 sbit LCD_D4_Direction at TRISB4_bit;
 sbit LCD_D5_Direction at TRISB5_bit;
 sbit LCD_D6_Direction at TRISB6_bit;
 sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connection definition
 sbit IR_Tx at RD2_bit;

// Define Messages
 char message1[] = "Tachometer";
 char *RPM = "00000 RPM";
 void Display_RPM(unsigned long num){
  RPM[0] = num/10000 + 48;
  RPM[1] = (num/1000)%10 + 48;
  RPM[2] = (num/100)%10 + 48;
  RPM[3] = (num/10)%10 + 48;
  RPM[4] = num%10 + 48;
  Lcd_Out(2,4,RPM);
 }

 void main() {


 ANSEL0 = 0x00;
 ANSEL1 = 0x00;

  TRISD = 0x00;
  PORTC = 0x00;
  TRISC = 0b00001000;
  T0CON = 0b01101000; // TMR0 as 16-bit counter
  Lcd_Init();        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);             // CLEAR display
  Lcd_Cmd(_LCD_CURSOR_OFF);        // Cursor off
  Lcd_Out(1,4,message1);            // Write message1 in 1st row
  while(1)
  {
    T0CON.TMR0ON = 1;
    TMR0L = 0;
    TMR0H = 0;
    IR_Tx = 1;
    Delay_ms(1000); // Wait for 1 sec
    IR_Tx = 0;
    T0CON.TMR0ON = 0;    // Stop the timer
    RPM_Value = (256*TMR0H + TMR0L)*60;
    Display_RPM(RPM_Value);
    RPM_Value = 0;
  };             // Infinite Loop
 }

and also configuration register configuration.JPGfile.


and i would to say in proteus also print data on lcd but in real hardware take a more time to operate so what is the problem please tell me.
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

Ok freinds now i fix my problem and working LCD complete .

Now second problem i have to discuss.

when RPM is counted in one second that time i have getting value + or - 60 error on display . then i have getting Average of 20 Sample and getting result with more Accurate but that time i have a problem regarding Display Update 20 sec time slower.

so is that any solution to get display update in One second and taking 20 sample. below is my working code.
Code:
unsigned long RPM_Value;


// Define LCD module connections.
 sbit LCD_RS at RB3_bit;
 sbit LCD_EN at RB2_bit;
 sbit LCD_D4 at RB4_bit;
 sbit LCD_D5 at RB5_bit;
 sbit LCD_D6 at RB6_bit;
 sbit LCD_D7 at RB7_bit;
 sbit LCD_RS_Direction at TRISB3_bit;
 sbit LCD_EN_Direction at TRISB2_bit;
 sbit LCD_D4_Direction at TRISB4_bit;
 sbit LCD_D5_Direction at TRISB5_bit;
 sbit LCD_D6_Direction at TRISB6_bit;
 sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connection definition
 sbit IR_Tx at RD2_bit;

// Define Messages
 char message1[] = "Tachometer";
 char *RPM = "00000 RPM";
 void Display_RPM(unsigned long num){
  RPM[0] = num/10000 + 48;
  RPM[1] = (num/1000)%10 + 48;
  RPM[2] = (num/100)%10 + 48;
  RPM[3] = (num/10)%10 + 48;
  RPM[4] = num%10 + 48;
  Lcd_Out(2,4,RPM);
 }

 void main() {

  int i = 0;
 ANSEL0 = 0x00;
 ANSEL1 = 0x00;

  TRISD = 0x00;
  PORTC = 0x00;
  TRISC = 0b00001000;
  T0CON = 0b01101000; // TMR0 as 16-bit counter
  Lcd_Init();        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);             // CLEAR display
  Lcd_Cmd(_LCD_CURSOR_OFF);        // Cursor off
  Lcd_Out(1,4,message1);            // Write message1 in 1st row
  while(1)
  {
    [B]for(i = 0 ; i < 20 ; i++)
    {
         T0CON.TMR0ON = 1;
         TMR0L = 0;
         TMR0H = 0;
         Delay_ms(1000); // Wait for 1 sec
         T0CON.TMR0ON = 0;    // Stop the timer
         RPM_Value += (256*TMR0H + TMR0L)*60;
    }
    RPM_Value = RPM_Value /20;
    Display_RPM(RPM_Value);
    RPM_Value = 0;[/B]
  };             // Infinite Loop
 }

If any solution Please give me.
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

hello friends please tell me is there any solution to refresh my RPM in 1 second only but take 20 sample of RPM ?

Please give me some hint or any other solution provide how to resolve this problem?
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

hello,
what is the maxi frequency ?
what is FOSC value ?
the only one soluce, could be to measure the periode of signal
instead frequency.
via CCP capture mode & timer.
1rst edge .. count start
end edge ..stop counter.

see frequenceneter or periodmeter..
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

Thanks for reply,

hello FOSC value is 8 MHz . and not use any prescale value of timer above code is giving me correct value but i would to get more accuracy like 1 rpm. At high speed object given me best result but at very low speed i didn't get any RPM so. is there any way to get 1 to 60 rpm in my code please give me some trick of code.
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

is there any way to get 1 to 60 rpm in my code please give me some trick of code.

paulfjujo may not have given you the code, however he has certainly given you the "trick."

Reference: PIC18F2331/2431/4331/4431 Datasheet, Section: 16.0 CAPTURE/COMPARE/PWM (CCP) MODULES, Subsection: 16.3 Capture Mode Page: 146

Reference: Principles of CCP Module Implementation and Functionality

Reference: The PIC18F Microcontroller: Timers and CCP Modules

Reference: **broken link removed**

I might also add, you can take advantage of the CCP modules trigger every fourth or sixteenth event option, which are binary multiples and effectively generates an averaging of period values when right shifted the appropriate number of positions, which will then assist in generating a stable display of RPM.


BigDog
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

but i would to get more accuracy like 1 rpm.
.. At high speed ... 60rpm

if your lowest speed is 1 rpm , and if your primary information is 1 pulse every 60 secondes..
you have now way than waiting 60 secondes to take your speed measure !

Have you got elsewhere any other speed measurment point with higher speed ?
before a gear reducer ?

at this so low speed, you can also use RB0 (edge change) interrupt .
A Rising edge start a 16 bits timer ..
don't forget to count also all overflow of timer= Nb of interrupts
the next Rising edge Stop timer counting
so you have a lot of counts ( Timer result + 65536* Overcounts) =>to store in long int)
wich represent the periode.
.. then Calculate the speed 1/T (to scale in RPM)

with a so big resolution, i think no need to average the measure.

- - - Updated - - -
 
re: PIC18f4431 and Micro C Pro code for LCD display ?

with a so big resolution, i think no need to average the measure.

The requirement to average would largely depend on the stability of rotation of the device being measured and display stability requirements.

For example, if the device is rotating an average of 60 RPM, with a range of 58 to 62, even at these low speeds the LCD could be quite difficult to read if updated directly by each calculated value.


BigDog
 
re: PIC18f4431 and Micro C Pro code for LCD display ?

hello I have tried below code but didn't give me result. i have use 8 MHz crystal .
please correction my code.

Code:
unsigned long RPM_Value;


// Define LCD module connections.
 sbit LCD_RS at RB3_bit;
 sbit LCD_EN at RB2_bit;
 sbit LCD_D4 at RB4_bit;
 sbit LCD_D5 at RB5_bit;
 sbit LCD_D6 at RB6_bit;
 sbit LCD_D7 at RB7_bit;
 sbit LCD_RS_Direction at TRISB3_bit;
 sbit LCD_EN_Direction at TRISB2_bit;
 sbit LCD_D4_Direction at TRISB4_bit;
 sbit LCD_D5_Direction at TRISB5_bit;
 sbit LCD_D6_Direction at TRISB6_bit;
 sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connection definition
// sbit IR_Tx at RD2_bit;

// Define Messages
 char message1[] = "Tachometer";
 char *RPM = "00000 RPM";
 void Display_RPM(unsigned long num){
  RPM[0] = num/10000 + 48;
  RPM[1] = (num/1000)%10 + 48;
  RPM[2] = (num/100)%10 + 48;
  RPM[3] = (num/10)%10 + 48;
  RPM[4] = num%10 + 48;
  Lcd_Out(2,4,RPM);
 }
  unsigned int ov_cnt, temp;
  unsigned  long period;
  void interrupt()
  {
      if(PIR1.TMR1IF)
      {
         PIR1.TMR1IF = 0;
         ov_cnt ++;
      }
  }
   void main()
   {
        unsigned int temp1;
        ov_cnt = 0;
        ANSEL0 = 0x00;
        ANSEL1 = 0x00;

        TRISD = 0x00;
        PORTC = 0x00;
        TRISC = 0b00000100;
        INTCON.GIE = 0;
        RCON.IPEN = 1;
        PIR1.TMR1IF = 0;
        IPR1.TMR1IP = 1;
        T1CON = 0x81;
        CCP1CON = 0x05;
        PIE1.CCP1IE = 0;
        PIR1.CCP1IF = 0;

        Lcd_Init();        // Initialize LCD
        Lcd_Cmd(_LCD_CLEAR);             // CLEAR display
        Lcd_Cmd(_LCD_CURSOR_OFF);        // Cursor off
        Lcd_Out(1,4,message1);            // Write message1 in 1st row
       while(1)
       {
                while (!(PIR1.CCP1IF));
                temp = CCPR1;
                PIR1.CCP1IF = 0;
                PIR1.TMR1IF = 0;
                INTCON |= 0xC0;
                PIE1.TMR1IE = 1;
                while (!(PIR1.CCP1IF));
                CCP1CON = 0x00;
                temp1 = CCPR1;
                if (temp1 < temp)
                {
                   ov_cnt--;
                }
                period = ov_cnt * 65536 + temp1 - temp;
                RPM_Value =  period ;
                Display_RPM(RPM_Value);
                ov_cnt = 0;
                temp1 = 0 ;
                temp = 0;
        };             // Infinite Loop
  }

Is that code correct or not?
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

Hi,

didn't give me result
No result at all? or no meaningful result?

Your math:
In your code you take the period, this is proprtional to time.
But you want to disply RPM, which proprtional to 1/period.

So you need a to do a division.
RPM = your_const / period

I didn´t go thorugh all the data to calcualate the "your_const" value. But I´m sure you get trough this.

Klaus
 

re: PIC18f4431 and Micro C Pro code for LCD display ?

Hello klausST thanks for reply.

i would to say is that ok code for Period measurement?

And yes i have display RPM so i can use 60 / Period to calculate RPM right?

but when I use above method then i didn't get any result? please explain me how?
 

Re: PIC18f4431 and Micro C Pro code for LCD display ?

nick703;1456918M so i can use 60 / Period to calculate RPM right?[/QUOTE said:
No , what is the raw value do you get at 60 RPM ?

example : you get a raw value period of 1.000 at 60 RPM => K calibration is 60.000
speed= K/ Raw value => 60.000/1.000 => 60 RPM
at 6 RMP
Raw value will be 10.000
speed= K /Raw value (10.000) => 60.000 / 10.000 => 6 RPM

you must use long int or float for calculus..
 
Re: PIC18f4431 and Micro C Pro code for LCD display ?

Hello Sorry But still i didn't get any value please below is my complete project file and proteus file.


1 Hz = 60 RPM RIGHT then when i applied 1Hz signal that means i have to display 60 RPM . So in capture mode I have to measure pulse time rising edge ok so this value i got in micro second right.
Now i have mesure rpm so i got this value in sec. so i have calculate

RPM = (1000000/ capture value) * 60.

below is the code and proteus file.

so At Low frequency i didn't get accurate RPM. please see the attachment and give me reply soon.
 

Attachments

  • pic18f4431rpmcounter.rar
    101.2 KB · Views: 82

Re: PIC18f4431 and Micro C Pro code for LCD display ?

ok now below program is giving me a result of 1 rpm to 1800 rpm

Code:
unsigned long RPM_Value;


// Define LCD module connections.
 sbit LCD_RS at RB3_bit;
 sbit LCD_EN at RB2_bit;
 sbit LCD_D4 at RB4_bit;
 sbit LCD_D5 at RB5_bit;
 sbit LCD_D6 at RB6_bit;
 sbit LCD_D7 at RB7_bit;
 sbit LCD_RS_Direction at TRISB3_bit;
 sbit LCD_EN_Direction at TRISB2_bit;
 sbit LCD_D4_Direction at TRISB4_bit;
 sbit LCD_D5_Direction at TRISB5_bit;
 sbit LCD_D6_Direction at TRISB6_bit;
 sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connection definition
// sbit IR_Tx at RD2_bit;

// Define Messages
 char message1[] = "Tachometer";
 char *RPM = "00000 RPM";
 void Display_RPM(unsigned long num){
  RPM[0] = num/10000 + 48;
  RPM[1] = (num/1000)%10 + 48;
  RPM[2] = (num/100)%10 + 48;
  RPM[3] = (num/10)%10 + 48;
  RPM[4] = num%10 + 48;
  Lcd_Out(2,4,RPM);
 }
  unsigned int ov_cnt, temp;
  unsigned long period;
  void interrupt()
  {
      if(PIR1.TMR1IF)
      {
         PIR1.TMR1IF = 0;
         ov_cnt ++;
      }
  }
   void main()
   {
        unsigned int temp1;
        ov_cnt = 0;
        ANSEL0 = 0x00;
        ANSEL1 = 0x00;

        TRISD = 0x00;
        PORTC = 0x00;
        TRISC = 0b00000100;
        INTCON.GIE = 0;
        RCON.IPEN = 1;
        PIR1.TMR1IF = 0;
        IPR1.TMR1IP = 1;
        T1CON = 0xC1;
        CCP1CON = 0x05;
        PIE1.CCP1IE = 0;
        PIR1.CCP1IF = 0;

        Lcd_Init();        // Initialize LCD
        Lcd_Cmd(_LCD_CLEAR);             // CLEAR display
        Lcd_Cmd(_LCD_CURSOR_OFF);        // Cursor off
        Lcd_Out(1,4,message1);            // Write message1 in 1st row
       while(1)
       {
                while (!(PIR1.CCP1IF));
                temp = CCPR1;
                PIR1.CCP1IF = 0;
                PIR1.TMR1IF = 0;
                INTCON |= 0xC0;
                PIE1.TMR1IE = 1;
                while (!(PIR1.CCP1IF));
                CCP1CON = 0x00;
                temp1 = CCPR1;
                if (temp1 < temp)
                {
                   ov_cnt--;
                }
                period = ov_cnt * 65536 + temp1 - temp;
                RPM_Value =  period ;     // this is micro second value
                RPM_Value = 60000000 / RPM_Value;      // this value multiplied by 60
                RPM_Value = RPM_Value * 2;             // and whole period * 2
                Display_RPM(RPM_Value);
                ov_cnt = 0;
                temp1 = 0 ;
                temp = 0;
        };             // Infinite Loop
  }

but in this code when i have achieve 1 rpm LCD take a time 1 min refresh to data print. so is there same problem in my post # 1 . my goal is achieve 1 rpm to 99999 rpm. and update data on LCD 1 sec.
in above code when freq. is above 35 Hz then rpm remain 00000.
below is my Proteus file change the frequency and see what happened?

PIC 18f4431 and running 8MHz crystal.
 

Attachments

  • pic18f4431rpmcounter.rar
    86.5 KB · Views: 88

Re: PIC18f4431 and Micro C Pro code for LCD display ?

ok now below program is giving me a result of 1 rpm to 1800 rpm but in this code when i have achieve 1 rpm LCD take a time 1 min refresh to data print. so is there same problem in my post # 1 . my goal is achieve 1 rpm to 99999 rpm. and update data on LCD 1 sec.

Considering your application is measuring the period of a single revolution as a basis for further calculations, once the RPM of the device being measured drops below 60 RPM, the measured period is greater than one second. At one RPM the period is in fact one minute, so unless you devise a noncausal system, a system which utilizes values from the future, a greater than one minute LCD update is inevitable.

In short, you would need to develop a time machine, jump forward to the future, measure the period, jump back to the present and update the LCD. Such a technique would enable less than one second LCD updates for all measurements under 60 RPM. :wink:

BigDog
 

Re: PIC18f4431 and Micro C Pro code for LCD display ?

In short, you would need to develop a time machine, jump forward to the future, measure the period, jump back to the present and update the LCD. Such a technique would enable less than one second LCD updates for all measurements under 60 RPM. :lol:

BigDog

ha ha ha right but thinking about it in real term what was the more affective code to Measure RPM in my post # 1 or in my post #14 .

suppose i have go with my post #1 that time i have a measure rpm 60 to 99999 rpm . and update lcd every 1 sec. but accuracy 1 : 60 . and i go with average value that means i have to wait 1min to update LCD in 60 sample avrage right.
 

Re: PIC18f4431 and Micro C Pro code for LCD display ?

The current implementation of utilizing period measurement is certainly a much more efficient and faster algorithm compared to counting cycles for a one minute duration. Once the RPM of the device under test drops below 60 RPM, the time required to measure the period will gradually increase from one second to one minute, it's the laws of physics and there is nothing short of a time machine which will change these facts.

I have not examined your code, however you might consider implementing a moving/rolling average which removes the oldest period measurement from the data queue when adding the latest period measurement to the data queue. Such a technique will allow a smoother display update during RPM transitions.

Moving Average

BigDog
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top