1
\$\begingroup\$

Hi I am using 8051 microcontroller. I do have a digital Water Meter which gives binary 0 1 0 1 type data. I attached it with 8051 INT1 so that i can get interrupt. Now when ever water flow through meter it will start sending interrupt (pulses of 0101) to 8051 INT1. Now i want to count total pulses and send it.

For that i am using this program in Kiel in C language : [2nd Updated]

#include<reg51.h> // include at89x51 . h
#include<stdio.h>// include stdio . h
#include<stdlib.h>// include stdlib . h

unsigned long  value,x;
unsigned long check;
unsigned long time_overflow_count=0;
void initialize_GSM_modem(void);
void initialize_serialcommunication(void);
unsigned char Command_CMGF[]="AT+CMGF=1\r"; 
// AT+CMGF for selecting Text Mode
unsigned char CtrlZ=0x1A;                   
// CTRL+Z for sedning SMS after the message has been entered
unsigned char Command_CMGS[]="AT+CMGS=\"+9xxxxxxxxx\"\r"; 
// recepient mobile number
unsigned char Command_AT[]="AT\r";
unsigned char msg02[]="Hello!";

unsigned char buf[10]={0};


void send(void)interrupt 1
{
time_overflow_count=time_overflow_count+1;
if (time_overflow_count==5){
if(value==x){

sprintf((char*)buf, "R %lu", value);

time_overflow_count=0;

initialize_GSM_modem();
value=0;
}
}
TR0=1;
}

void input_counting(void) interrupt 2
{
TR0=0;
TL0=0x00;
TH0=0x00;

value=value+1;
TR0=1;

}


void main (void) {

TMOD = 0x21;
TH1 = 0xFD;
TL0=0x55;
TH0=0x55;
SCON = 0x50;
TR1=1;
EX1=1;///Enable external intrrupt 1
EA=1;
IE1=1;
IT1=1;
PX1=1;
ET0=1;

TI=1;
while(1)
{
x=value;
}
}

void delay(void){
unsigned int i;
for(i=0;i<50;i++);
}


 void delay2(void){
unsigned long i;
for(i=0;i<15000;i++);
}

 void initialize_GSM_modem(void)
 {
 delay2();
puts(Command_CMGS);
delay2();
puts((char *)buf);
delay2();

while(!TI); TI = 0;SBUF = 0x1A;
 }

*Updated :*So using this I'm trying to get a timer interrupt which checks when there is no pulses for some time interval then it assumes that meter flow is complete and send the message.

But there an error : I don't know why but our program keeps on sending continues messages for a number of times even if I don't start water meter. If I start water meter it sends the total value at stop and if I don't, it keeps sending 0 at regular interval

What I want is that it waits for water flow (or interrupt to start) and then checks for last value and send it only one time.

Next time I start the meter, it should wait and send the value again, but it should not keep on sending 0s at regular intervals.

UPDATE : I have updated the code and its working fine but its not working as i wish

Please Suggest

Thanks

\$\endgroup\$
  • \$\begingroup\$ are you asking your digital water meter sending it's water level by sending a serial bit pattern and you need to read it ? \$\endgroup\$ – Standard Sandun Apr 18 '12 at 11:56
2
\$\begingroup\$

It sounds like your underlying architectural flaw is that you have the receiving of pulses coupled to sending out the flow rate or accumulated water information. Also, make sure that this water meter either produces clean digital pulses already, or that you debounce the signal in case it is just from a mechanical switch.

In the most general case where you have to debounce the water pulses, don't interrupt on the pulses at all. Interrupt regularly from a timer. This needs to be a minimum of 10s of times faster than the pulses at the maximum flow rate. The interrupt routine will require a minimum number of consecutive high or low states before considering the debounced signal to have changed to the new state. Once that happens, it increments a counter. Microcontrollers are much faster than water meters, especially mechanical ones, so interrupting fast enough should be no problem. Usually a 1 ms interrupt is good enough for this, and then you can use it for other system timing.

Now you can periodically send the counter value or any accumulated delta on ansynchronously. To avoid contention over the counter with the interrupt routine, the counter the interrupt routine increments can be a single byte. The foreground code keeps it own copy of the last known value of that byte. It periodically reads the interrupt routine counter, compares it to the last known value, processes any new ticks the difference represents, then updates the last known value. As long as the foreground routine does this often enough so that the single byte counter can't wrap between samples, no data will be lost.

The foreground code can then decide when to send information. This can be based on a timer tick and/or when there is new information to send.

\$\endgroup\$
0
\$\begingroup\$

Okay, here's a good one:

Set up a timer to interrupt every, say 10 seconds if you can. When you start your program, start the timer.

Every time you get in the input_counting function, stop the timer and clear its count back to 0 (or to the period value if it interrupts when it reaches zero - if it counts backwards that is). Then, right before you leave the interrupt, re-enable the timer.

The time is always counting, but every time you get a pulse and your interrupt runs it resets the timer. The timer will only generate an interrupt when there are no pulses for 10s (or whatever you set the period of the timer to).

So then, in the interrupt handler for the timer, just transmit value again and then disable the timer. That should do it.

\$\endgroup\$
  • \$\begingroup\$ "clear its count back to 0" what you mean by that...Please explain.. \$\endgroup\$ – TheBond Apr 18 '12 at 12:42
  • \$\begingroup\$ The timer counts either up from 0, or down from a certain value to 0. When you 'clear' the timer you set the count register back to its original value: if the timer counts up, you set the count to 0, if it counts down you set it back to the value you put in to generate the period you wanted. \$\endgroup\$ – AngryEE Apr 18 '12 at 13:15
  • \$\begingroup\$ Hi...Thanks and as per ur suggestions i have updated the code...[Updated in Question Also]...Please have a look and reply...I am still can't resolve. \$\endgroup\$ – TheBond Apr 18 '12 at 13:52
  • \$\begingroup\$ You don't reset the count in the interrupt - you just disable then re-enable the timer. Also, you have no timer overflow interrupt. I don't see that you ever enable the timer interrupt either - it could be in there but I'm not going to trawl through the datasheet to figure out which register it needs to be. \$\endgroup\$ – AngryEE Apr 18 '12 at 14:25
  • \$\begingroup\$ Hello Sir, I did as u suggested and updated the code and problem above in question...Please have a look and tell me why its sending continues messages even if i don't have start water meter. ? Please Suggest \$\endgroup\$ – TheBond Apr 20 '12 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.