Pre paid energy meter with Arduino and GSM sim 800C recharge and "pulsein" counting problem

I have built this project, it working fine but there are two problem I’m facing

1.Unit recharge limited to two digits (units does not exceed 99 units)If I recharge more than 99,it resets to lower number.

example if I send sms with #1000* the system does not accept it, returns 0 recharged.

other number is being accepted like #52*,#99* etc

2.Units is being reduced after every single pulse from meter, instead of every 3200 pulses.

Circuit diagram

here is the code

#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int led = 13;
#define pulsein 8
#define relay 12
unsigned int pusle_count = 0;
float units = 0;
unsigned int tk = 0;

float watt_factor = 0.3125;
unsigned int temp = 0, i = 0, x = 0, k = 0;
char str[70], flag1 = 0, flag2 = 0;

String bal = "";

void setup()
{
    lcd.begin(16, 2);
    Serial.begin(9600);
    pinMode(led, OUTPUT);
    pinMode(pulsein, INPUT);
    pinMode(relay, OUTPUT);
    digitalWrite(pulsein, HIGH);
    lcd.setCursor(0, 0);
    lcd.print("Automatic Energy");
    lcd.setCursor(0, 1);
    lcd.print(" Meter ");
    delay(2000);
    lcd.clear();
    lcd.print("Welcome");
    delay(2000);
    lcd.clear();
    lcd.print("GSM Initilizing...");
    gsm_init();
    lcd.clear();
    lcd.print("System Ready");
    Serial.println("AT+CNMI=2,2,0,0,0");
    init_sms();
    delay(2000);
    send_data("SmsSystem Ready");
    send_sms();
    delay(1000);
    digitalWrite(led, LOW);
    lcd.clear();
    // EEPROM.write(1,0);
    // tk=EEPROM.read(1);
}

void loop()
{
    serialEvent();
    tk = EEPROM.read(1);
    units = tk / 5.0;
    lcd.setCursor(0, 0);
    lcd.print("Units:");
    lcd.print(units);
    lcd.print(" ");
    lcd.setCursor(0, 1);
    if (tk < 15)
        lcd.print("LOW Balance:");
    else
        lcd.print("Balance:");
    lcd.print(tk);
    lcd.print(" ");
    read_pulse();
    check_status();
    if (temp == 1) {
        decode_message();
        send_confirmation_sms();
    }
}
void serialEvent()
{
    while (Serial.available()) {
        char ch = (char)Serial.read();
        str[i++] = ch;
        if (ch == '*') {
            temp = 1;
            lcd.clear();
            lcd.print("Message Received");
            delay(500);
            break;
        }
    }
}

void init_sms()
{
    Serial.println("AT+CMGF=1");
    delay(200);
    Serial.println("AT+CMGS=\"+255xxxxxxxxxx\"");
    delay(200);
    Serial.println("AT+CRES");
    delay(2000);
    Serial.println("AT+CSQ");
    delay(2000);
}

void send_data(String message)
{
    Serial.println(message);
    delay(200);
}

void send_sms()
{
    Serial.write(26);
}

void read_pulse()
{
    if (!digitalRead(pulsein)) {
        digitalWrite(led, HIGH);
        //count++;
        //units=watt_factor*count/1000;
        if (units < 1) {
        }
        else
            units--;
        tk = units * 5;
        EEPROM.write(1, tk);
        while (!digitalRead(pulsein))
            ;
        digitalWrite(led, LOW);
        // delay(2000);
    }
}

void check_status()
{
    if (tk > 1) //change hoise 15 to 1
    {
        digitalWrite(relay, HIGH);
        flag1 = 0;
        flag2 = 0;
    }
    if (tk < 1 && flag1 == 0) //change hoise 15 to 1
    {
        lcd.setCursor(0, 1);
        lcd.print("LOW Balance ");
        init_sms();
        send_data("Energy Meter Balance Alert:");
        send_data("Low Balance\n");
        Serial.println(tk);
        delay(200);
        send_data("Please recharge your energy meter soon.\n Thank you");
        send_sms();
        message_sent();
        flag1 = 1;
    }
    if (tk < 5 && flag2 == 0) {
        digitalWrite(relay, LOW);
        lcd.clear();
        lcd.print("Light Cut Due to");
        lcd.setCursor(0, 1);
        lcd.print("Low Balance");
        delay(2000);
        lcd.clear();
        lcd.print("Please Recharge ");
        lcd.setCursor(0, 1);
        lcd.print("UR Energy Meter ");
        init_sms();
        send_data("Energy Meter Balance Alert:\nLight cut due to low Balance\nPlease recharge your energy meter soon.\n Thank you");
        send_sms();
        message_sent();
        flag2 = 1;
    }
}

void decode_message()
{
    x = 0, k = 0, temp = 0;
    while (x < i) {
        while (str[x] == '#') {
            x++;
            bal = "";
            while (str[x] != '*') {
                bal += str[x++];
            }
        }
        x++;
    }
    bal += '\0';
}

void send_confirmation_sms()
{
    int recharge_amount = bal.toInt();
    tk += recharge_amount;
    EEPROM.write(1, tk);
    lcd.clear();
    lcd.print("Energy Meter ");
    lcd.setCursor(0, 1);
    lcd.print("Recharged:");
    lcd.print(recharge_amount);
    init_sms();
    send_data("Energy Meter Balance Alert:\nYour energy meter has been recharged Rs:");
    send_data(bal);
    send_data("Total Balance:");
    Serial.println(tk);
    delay(200);
    send_data("Eelctricity Has Been Connected\nThank you");
    send_sms();
    temp = 0;
    i = 0;
    x = 0;
    k = 0;
    delay(1000);
    message_sent();
}

void message_sent()
{
    lcd.clear();
    lcd.print("Message Sent.");
    delay(1000);
}

void gsm_init()
{
    lcd.clear();
    lcd.print("Finding Module..");
    boolean at_flag = 1;
    while (at_flag) {
        Serial.println("AT");
        //delay(1000);

        while (Serial.available() > 0) {
            if (Serial.find("OK"))
                at_flag = 0;
        }
        delay(1000);
    }

    lcd.clear();
    lcd.print("Module Connected..");
    delay(1000);
    lcd.clear();
    lcd.print("Disabling ECHO");
    boolean echo_flag = 1;
    while (echo_flag) {
        Serial.println("ATE0");
        while (Serial.available() > 0) {
            if (Serial.find("OK"))
                echo_flag = 0;
        }
        delay(1000);
    }

    lcd.clear();
    lcd.print("Echo OFF");
    delay(1000);
    lcd.clear();
    lcd.print("Finding Network..");
    boolean net_flag = 1;
    while (net_flag) {
        Serial.println("AT+CPIN?");
        while (Serial.available() > 0) {
            if (Serial.find("+CPIN: READY"))
                net_flag = 0;
        }
        delay(1000);
    }
    lcd.clear();
    lcd.print("Network Found..");
    delay(1000);
    lcd.clear();
}

Possibly not the cause of the problem but why do you call serialEvent()? It is already called from main() (which is hidden for you).

Then there is the risk that you have a corrupt string in str.

For debugging, I’d suggest moving the GSM module away from the standard RX and TX and use two of the free analog pins and Software Serial instead. Alternatively, use a USBTTL device on two free analog pins. This would allow you to print debug messages, intermediate values, etc. to the serial console.

1 Like

Consider giving your global variables some better names. Things like i, x and k make it harder to follow.

It is also unusual to terminate a String object explicitly with a NULL character:

String bal = "";
. . .
bal += '\0';

tk is an int; you can’t use EEPROM.write() and EEPROM.read() on integer variables like you do. Read up on the use of EEPROM.put() and EEPROM.get().

  if (!digitalRead(pulsein))

How long does a pulse last? You might want to detect if a pulse changes from low to high instead of the pulse being high.

I would suggest to read Robin’s updated Serial Input Basics to get some ideas about the reading of serial input.

1 Like