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.

[SOLVED] Why this Flow meter code not working ?

Status
Not open for further replies.

milan.rajik

Banned
Joined
Apr 1, 2013
Messages
2,524
Helped
540
Reputation
1,078
Reaction score
524
Trophy points
1,393
Activity points
0
Why this Flow meter code not working ?

I am using PIC16F877A at 4 MHz external crystal. I am feeding pulses to INT0 pin. My sensor gives 330 pulses per liter of fluid and 25 liters per minute is the flow rate.

In the code if I comment out the line

Code:
while(GIE_bit);
then it shows some continuously incrementing data but if I uncomment then nothing is displayed on LCD except "Flow Meter".

I am using mikroC PRO PIC Compiler. What is wrong in the code ?

- - - Updated - - -

I solved the problem. Now I have a new problem. It displays 0 for liters / min and liters / hour all the time. What is the problem ?
 

Attachments

  • Flow Meter.rar
    69.8 KB · Views: 57
  • Flow Meter rev1.rar
    68.3 KB · Views: 63

When first pulse is detected at INT0 then TMR1ON_bit is made 1 and after 1 sec TMR1ON_bit is turned OFF.

This is my new code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "float2ascii.h"
 
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD2_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D6 at RD4_bit;
sbit LCD_D7 at RD5_bit;
 
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD4_bit;
sbit LCD_D7_Direction at TRISD5_bit;
// End LCD module connections
 
char count = 0;
unsigned long counter = 0;
double litersPerSec = 0, litersFlowed, litersPerMinute = 0, litersPerHour = 0;
char str[30];
 
//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer1() {
    T1CON = 0x30;
    TMR1IF_bit = 0;
    TMR1H = 0x0B;
    TMR1L = 0xDC;
    TMR1IE_bit = 1;
}
 
void interrupt() {
    if(INTF_bit) {
         if(TMR1ON_bit == 0) {
              TMR1ON_bit = 1;              
         }
         else counter += 1;
         
         INTF_bit = 0;                                
    }
    
    if(TMR1IF_bit){ 
        TMR1IF_bit = 0;
        TMR1H = 0x0B;
        TMR1L = 0xDC;
        //Enter your code here
        if(++count == 2) {
             TMR1ON_bit = 0;              
             count = 0;
             INTE_bit = 0;                                
        }
        
               
    }
}
 
void main() {
    
    CMCON = 0x07;
    ADCON1 = 0x87;
    
    TRISA = 0xC0;
    TRISB = 0x01;
    TRISC = 0x00;
    TRISD = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
           
    LCD_Init();                        
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);               
              
    LCD_Out(1,5,"Flow Meter");
  
    INTEDG_bit = 1;
    INTE_bit = 1;
    PEIE_bit = 1;
    GIE_bit = 1;
    
    INTF_bit = 0;
  
    InitTimer1();
    
    while(1) {
       
        
        while(TMR1ON_bit);
        
        litersPerSec = (double)counter;
        litersPerSec /= 330.0;
        litersFlowed += litersPerSec;
        litersPerMinute = litersPerSec * 60.0;
        litersPerHour = litersPerMinute * 60.0;           
        
        Float2Ascii(litersFlowed, str, 2);
        strcat(str, " Liters");
        LCD_Out(2,1,str); 
        Float2Ascii(litersPerMinute, str, 2);
        strcat(str, " Ltr/min");
        LCD_Out(3,1,str); 
        Float2Ascii(litersPerHour, str, 2);
        strcat(str, " Ltr/hr");
        LCD_Out(4,1,str);
        
        InitTimer1();
        counter = 0;
        INTE_bit = 1;                              
        
    }
}




Problem solved. In Project settings I had selected HS instead of XT for oscillator type.

I am feeding 137 Hz (My sensor gives 330 pulses per liter and 25 liters per minute is the flow rate which gives 137 pulses per second).

So, it displays 24.x liter/minute

broken link removed

- - - Updated - - -

The system is giving correct values but there is one problem. Initially it takes 12 seconds to display data on LCD in Proteus. Have to test it in hardware. Why is the delay present ?

- - - Updated - - -

I think the delay of 12 seconds occurs only in Proteus as it has to simulate 6 clock generators. I removed 5 clock generators and it took 7 seconds to display data. I will test in hardware and update.
 

Attachments

  • flow meter.png
    flow meter.png
    46.9 KB · Views: 117
  • Flow Meter Working Project.rar
    108.5 KB · Views: 112
Last edited by a moderator:

I made the project. I have some problems. Please help me solve the problems. I made PIC16F877A version of flow meter. It worked like this in Proteus and also hardware.

1. It took 27 to 30 sec to display data on LCD in Proteus and took 20 seconds in hardware.
2. It displayed proper data. If 60 liters/min flows then liters flowed incremented 1 per second.

Just fine.

To solve the delay problem I made PIC18F26K22 version of flow meter. The delay problem was solved and it took 2 sec after start to display data on LCD both in Proteus and hardware.

One problem in this version is the liters flowed increases rapidly when 60 liters/minute flows. It has to increment once per second but it is too fast.

What might be the problem ?

Edit: Problem solved. I cleaned the project folder and compiled and it worked fine. Don't know what was the problem.

This is for Horizontal mount of flow sensor. Now will implement vertical mount code.
 

Attachments

  • Flow Meter PIC16F877A.rar
    115.8 KB · Views: 58
  • Flow Meter PIC18F26K22.rar
    93.2 KB · Views: 54
  • Flow Meter PIC18F26K22 rev1.rar
    86 KB · Views: 56
Last edited:

I have modified the code the Microchip mechatronics board to use the external interrupt INT for the motor speed snsing

main.c is now
Code:
#include <htc.h>
#include "uart.h"
#include "picdem.h"


//extern int tenMillSecCounter, second, tenthsSecond;
// test program 
void main(void)
{
        int i=0, t, adc;
        systemInitialise();
        UARTInitialise();       // initalise UART for rS232 serial output
        ADCinitialise();        // initialise ADC to read RA0
        PWMinitialise();        // initilise motor control
        TRISA1=1;               // RA1 is switch input
        TRISB0=1;               // RB0 is motor speed opto input
        TRISD6=0;               // RD6 is LED output
        TRISD5=0;               // RD5 is LED output
        RD6=1;                  // set LED
        putString("\n\rTest program for Microchp PICDEM mechatronics board\n\r\n\r");
        putString("\n\rUsing external interrupt INT for motor speed sensing\n\r\n\r");
        putString(" connect POT1 to RA0         potentiometer input\n\r");
        putString(" connect RD7 to P1           motor ON/OFF control\n\r");
        putString(" connect RD2/CCP2 to N2      motor PWM control\n\r");
        putString(" connect Optical Interrupter (J7) to RB0 motor REV counter\n\r");
        putString("   \n\r");
        putString(" turn POT1 to control motor speed and display RPM\n\r");
        putString("\n\r");


        while(1)
        {                                        
             putString("ADC0  ");
             printInt(adc=ADCread(), 0, putchar);         // read and display ADC AN0 channel
             putString(" ");
             printInt(60*rpm/2, 0, putchar);            // display RPM
             rpm=0;                                     // reset RPM to 0
             putString(" RPM\n\r");
              RD6=!RD6;                                     // invert LED to blink it
             PWMcontrol((int) (adc * 100L /1023L));        // set PWM duty cycle 0 to 100
             tenthsSecondDelay(20);
       }
}

and the timer and speed sensing is
Code:
#define _LEGACY_HEADERS
#include <htc.h>

// Setup configuration bits
__CONFIG (EC & WDTDIS & PWRTDIS  & UNPROTECT &  MCLREN & BORDIS & FCMEN & IESOEN);

volatile int tenMillSecCounter=0;               // incremented every 10mSec
static volatile int tenMillSecCounter2=0;       // incremented every 10mSec - used for delays
static volatile int revolutionTimer=0;          // used for counting revs/min or motor
volatile int tenthsSecond=0;                    // incremented every tenth of a second
volatile int second=0;                          // incremeneted every second
volatile int rpm=0;                             // RPM interrupt counter

// Timer 0 is programmed to interrupt every 10mSeconds
//  T0 clock is FOSC/4 = 200000
//  with 256 prescaler decrements 2000000/256 times / second
//  to get an interrupt every T mSec the calculation for TMR0 overflow from 0xFF to 0 is
//    count = 255 - T * 2000/256
//    i.e. for 10mSec counter is
#define tenMillSec 177
static void interrupt isr(void)
{
    if (T0IF)                           // A TMR0 interupt occurred
    {
        TMR0=tenMillSec;                // increment counters every 10 mSec
        tenMillSecCounter2++;
        revolutionTimer++;
        if((++tenMillSecCounter % 10)==0) tenthsSecond++;
        if((tenMillSecCounter % 100)==0) { second++; tenMillSecCounter=0; }
        T0IF=0;                             // clear TMR0 interrupt flag
   }
    if(INTF)                                // external interrupt INT
    {
        INTF=0;
        rpm++;                              //increment RPM counter
    }

}

// delay for count tenths of a second
void tenthsSecondDelay(int count)
{
    tenMillSecCounter2=0;                         // zero counter
    while( tenMillSecCounter2  < (count*10)) ;    // wait
}
        
// delay for count seconds
void secondDelay(int count)
{
    tenMillSecCounter2=0;                         // zero counter
    while( tenMillSecCounter2  < (count*100)) ;   // wait
}
        
// initalise clock, set port A for digital input, set up timer 0, etc
void systemInitialise(void)
{
        OSCCON=0x70;             // Fosc use oscillator 8MHz
        ANSEL=0;                 // set digital inputs
        // PORTB PULL-UP DISABLED, TMR0 Timer mode Clock Source Select bit FOSC/4,  
        // Prescaler is assigned to the Timer0 module & TMR0 RATE 1:256
        OPTION=0x87;             
        TMR0=tenMillSec;         // initialise timer 0 counter
        T0IE = 1;                // enable interrupt on TMR0 overflow from 0xFF to 0
        GIE = 1;                 // Global interrupt enable
 }
when run teraterm output looks like (as I vary the potentiometer)
teraterm4.jpg
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top