With the continuous advancement of the Internet of Things and smart city construction, traditional mechanical water meters can no longer meet the demands of modern water management. As an important component of smart water management, smart water meters possess features such as remote measurement, automatic billing, and prepaid control, significantly enhancing the efficiency and safety of water resource management. This article introduces an IC card smart water meter control system based on the 51 microcontroller, integrating the MFRC522 RFID reader and Hall flow sensor to achieve core functions such as water consumption collection, IC card read/write, valve control, and cutoff for unpaid bills.
The overall architecture of the system is centered around the STC89C52 microcontroller, with an external MFRC522 RFID module for IC card (M1 card) read/write operations. The Hall sensor collects water flow pulse signals, and an electromagnetic valve is used to control water flow. The system is equipped with an LCD1602 display to show balance, water consumption, and other information, along with a buzzer for abnormal alerts (such as insufficient balance or illegal cards).
The system workflow is as follows: the user brings the IC card close to the reader, and the system reads the balance information from the card; if the balance is greater than zero, the electromagnetic valve is opened to supply water. The Hall sensor continuously detects water flow and converts it into pulse signals, with the microcontroller calculating water consumption based on the pulse count and simultaneously deducting the balance from the card. When the balance is insufficient or the user removes the card, the valve is automatically closed, implementing prepaid control.
Main hardware components include:
- Main control chip: STC89C52 (8-bit microcontroller, 40 pins, 12MHz crystal)
- RFID module: MFRC522, SPI interface communication
- Flow detection: Hall water flow sensor (outputs pulse signals, approximately 450 pulses per liter)
- Actuator: 12V DC electromagnetic valve, driven by a relay
- Display module: LCD1602, 4-bit data mode
- Power supply: 5V DC regulated power supply
Software design and source code implementation:
Below is the core code of the system, written in C language, using the Keil C51 development environment.
#include <reg52.h>
#include "lcd1602.h"
#include "mfrc522.h"
#include "delay.h"
sbit BEEP = P2^3; // Buzzer pin
sbit RELAY = P2^4; // Relay control for electromagnetic valve
sbit FLOW_SENSOR = P3^2; // Hall sensor input
unsigned long pulse_count = 0; // Pulse count
unsigned int water_used = 0; // Water used (liters)
unsigned int balance = 0; // Balance on card (cents)
bit card_valid = 0; // Is the card valid?
// External interrupt 0 service function: Hall sensor pulse counting
void INT0_ISR() interrupt 0 {
pulse_count++; // Every 450 pulses ≈ 1 liter of water
if(pulse_count >= 450) {
water_used++;
pulse_count = 0;
// Deduct cost from balance (assume 2 yuan/liter)
if(balance >= 200) {
balance -= 200; // Deduct 200 cents (2 yuan)
} else {
RELAY = 0; // Insufficient balance, close valve
BEEP = 1; // Buzzer alarm
delay_ms(500);
BEEP = 0;
}
}
}
// Initialization function
void init_system() {
IT0 = 1; // External interrupt 0 triggered on falling edge
EX0 = 1; // Enable external interrupt 0
EA = 1; // Enable global interrupt
RELAY = 0; // Initially close the valve
BEEP = 0;
LCD_Init(); // Initialize LCD
MFRC522_Init(); // Initialize RFID module
LCD_ShowString(1, 1, "Smart Water Meter");
LCD_ShowString(2, 1, "Ready...");
delay_ms(1000);
}
// Read IC card balance (simulating actual card reading operation)
bit read_card_balance() {
unsigned char status;
unsigned char str[MAX_LEN];
// Seek card
status = MFRC522_Request(PICC_REQIDL, str);
if(status != MI_OK) return 0;
// Anti-collision
status = MFRC522_Anticoll(str);
if(status != MI_OK) return 0;
// Select card
status = MFRC522_SelectTag(str);
if(status != MI_OK) return 0;
// Verify password (default key A)
status=MFRC522_Auth(PICC_AUTHENT1A,8, DefaultKey, str);
if(status != MI_OK) return 0;
// Read block 8 data (assumed to store balance)
status = MFRC522_Read(8, str);
if(status == MI_OK) {
balance = str[0] + (str[1]<<8); // Read 16-bit balance
return 1;
}
return 0;
}
// Write back card balance (after recharge or deduction)
void write_card_balance() {
unsigned char status;
unsigned char data[16] = {0};
// Write balance into data buffer
data[0] = balance & 0xFF;
data[1] = (balance >> 8) & 0xFF;
// Verify key
status= MFRC522_Auth(PICC_AUTHENT1A,8, DefaultKey, NULL);
if(status == MI_OK) {
MFRC522_Write(8, data); // Write to block 8
}
}
// Main function
void main() {
init_system();
while(1) {
// Clear screen
LCD_Clear();
// Try to read card
if(read_card_balance()) {
card_valid = 1;
LCD_ShowString(1,1,"Card Detected");
LCD_ShowNum(2,1,balance,5); // Display balance (cents)
LCD_ShowString(2,7,"Cent");
// If there is balance, open water supply
if(balance > 0) {
RELAY = 1; // Open electromagnetic valve
LCD_ShowString(1,10,"Supplying");
// Continuously check water usage and card status
while(card_valid) {
// Real-time update water usage and balance
LCD_ShowNum(1,1,water_used,4);
LCD_ShowString(1,5,"L Used");
LCD_ShowNum(2,1,balance,5);
LCD_ShowString(2,7,"Cent");
// Check again if card is removed
if(!read_card_balance()) {
card_valid = 0; // Card has been removed
}
delay_ms(200);
}
// Close valve
RELAY = 0;
write_card_balance(); // Write back remaining balance
LCD_ShowString(1,1,"Valve Closed");
} else {
LCD_ShowString(2,1,"No Balance!");
BEEP = 1;
delay_ms(300);
BEEP = 0;
}
} else {
LCD_ShowString(1,1,"Hold Card...");
delay_ms(500);
}
}
}