hello I am a Cameroonian student and my project consists in designing a prepaid meter which consists in subscribing to an energy consumption package to have power in his home and once the consumption is exhausted the relay contact opens and the consumer no longer has power in his home until he renews, the goal is to make payments using his phone, but I'm blocked at the payment level, here is my code below:
#include <SD.h>
#include <SPI.h>
#include <PZEM004Tv30.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
PZEM004Tv30 pzem(&Serial3);
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 RTC;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Variables utilisées pour la carte SD
const int sdCardPinChipSelect = 53; // Le lecteur de carte SD sera branché sur la pin 10 pour le CS (chip select),51/50/52 pour le MOSI/MISO/SCK du bus SPI
const char* compteur = "compteur.txt"; // Format 8.3 (c'est Ă dire 8 lettres maximum pour le nom, et optionnellement 3 pour l'extension)
#define nomDuFichier "stockage.txt"
File monFichier1;
File monFichier2;
// Autres variables
const long delaiIntervalleDeMesures = 1000; // Intervalle de mesure/enregistrement (exprimé en millis secondes)
// Variable pour stocker le message texte
String textMessage;
// Créer une variable pour stocker l'état de la lampe
String lampState = "HIGH";
// Relais connecté à la broche 2
char incomingChar;
// ========================
// Initialisation programme
// ========================
void setup () {
// Initialisation de la liaison série (pour retourner les infos au moniteur série de l'ordi)
Wire.begin();
RTC.begin();
Serial.begin(9600);
#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif
if (! RTC.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
if (RTC.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
Serial.println("Programe DATALOGGER (enregistrement de la tension, du courant, le facteur de puissance, la puissance et la frequece d'un PZEM004Tv30, et stokage des infos sur carte SD");
Serial.println("===================================================================================================");
Serial.println();
// ----------------------------------------------------------------------------
// Vérification : est-ce que la carte SD est bien accessible depuis l'arduino ?
// ----------------------------------------------------------------------------
Serial.print(F("Initialisation de la carte SD..."));
if (!SD.begin(sdCardPinChipSelect)) {
Serial.println();
Serial.println();
Serial.println(F("Échec de l'initialisation du lecteur de SD card. Vérifiez :"));
Serial.println(F("1. que la carte SD soit bien insérée"));
Serial.println(F("2. que votre câblage soit bon"));
Serial.println(F("3. que la variable 'sdCardPinChipSelect' corresponde bien au branchement de la pin CS de votre carte SD sur l'Arduino"));
Serial.println(F("Et appuyez sur le bouton RESET de votre Arduino une fois le pb résolu, pour redémarrer ce programme !"));
while (true);
}
Serial.println(F(" réussie !"));
Serial.println();
PZEM004Tv30();// Initialisation du PZEM004Tv30
lcd.init();
lcd.backlight();
lcd.clear();
// Activer automatiquement le bouclier
digitalWrite(9, HIGH);
delay(100);
digitalWrite(9, LOW);
delay(100);
// Définir le relais comme SORTIE
pinMode(2, OUTPUT);
// By default the relay is off
digitalWrite(2, LOW);
// Initialisation de la communication série
Serial.begin(9600);
Serial2.begin(9600);
// Donnez le temps à votre bouclier GSM de se connecter au réseau
delay(20000);
Serial.print("SIM900 ready...");
// Commande AT pour mettre SIM900 en mode SMS
Serial2.print("AT+CMGF=1r");
delay(100);
// Configurer le module pour envoyer des données SMS à la sortie série dès réception
Serial2.print("AT+CNMI=2,2,0,0,0r");
delay(100);
}
void loop () {
status();
serialEvent();
if(temp == 1)
{
decode();
confirmation_sms();
Serial.println(F("remplacement du fichier '" nomDuFichier "', si déjà existant :"));
if (!SD.exists(nomDuFichier)) {
Serial.println(F("Fichier '" nomDuFichier "' inexistant."));
}
else {
Serial.println(F("Fichier '" nomDuFichier "' déjà existant, donc lancement suppression."));
// Suppression du fichier déjà existant
if(!SD.remove(nomDuFichier)) {
Serial.println(F("Échec du remplacement du fichier '" nomDuFichier "' présent sur la SD card !"));
while (1); // Boucle infinie (arrĂŞt du programme)
}
else {
Serial.println(F("Remplacement du fichier existant réussie."));
}
}
Serial.println();
float voltage = pzem.voltage();
if(voltage != NAN){
Serial.print("Voltage: ");
Serial.print(voltage);
Serial.println("V");
} else {
Serial.println("Error reading voltage");
}
float current = pzem.current();
if(current != NAN){
Serial.print("Current: ");
Serial.print(current);
Serial.println("A");
} else {
Serial.println("Error reading current");
}
float power = pzem.power();
if(current != NAN){
Serial.print("Power: ");
Serial.print(power);
Serial.println("W");
} else {
Serial.println("Error reading power");
}
float energy = pzem.energy();
if(current != NAN){
Serial.print("Energy: ");
Serial.print(energy,3);
Serial.println("kWh");
} else {
Serial.println("Error reading energy");
}
float frequency = pzem.frequency();
if(current != NAN){
Serial.print("Frequency: ");
Serial.print(frequency, 1);
Serial.println("Hz");
} else {
Serial.println("Error reading frequency");
}
float pf = pzem.pf();
if(current != NAN){
Serial.print("PF: ");
Serial.println(pf);
} else {
Serial.println("Error reading power factor");
}
DateTime now = RTC.now();
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(':');
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print("___");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.println("-------------------------");
delay(1000);
// Enregistrement de ces données sur la carte SD
monFichier1 = SD.open(compteur, FILE_WRITE);
if (monFichier1) {
monFichier1.println("Tension:") ;
monFichier1.print(voltage);
monFichier1.print(" V: ");
monFichier1.println(voltage);
monFichier1.println("Intensité:") ;
monFichier1.print(current);
monFichier1.print(" A: ");
monFichier1.println(current);
monFichier1.println("Puissance:") ;
monFichier1.print(power);
monFichier1.print(" W: ");
monFichier1.println(power);
monFichier1.println("Energie:") ;
monFichier1.print(energy);
monFichier1.print(" KWh: ");
monFichier1.println(energy);
monFichier1.println("Frequence:") ;
monFichier1.print(frequency);
monFichier1.print(" ");
monFichier1.println(frequency);
monFichier1.println("Facteur de puissance:");
monFichier1.print(pf);
monFichier1.print(" ");
monFichier1.println(pf);
monFichier1.print(daysOfTheWeek[now.dayOfTheWeek()]);
monFichier1.print(':');
monFichier1.print(now.year(), DEC);
monFichier1.print('/');
monFichier1.print(now.month(), DEC);
monFichier1.print('/');
monFichier1.print(now.day(), DEC);
monFichier1.print("___");
monFichier1.print(now.hour(), DEC);
monFichier1.print(':');
monFichier1.print(now.minute(), DEC);
monFichier1.print(':');
monFichier1.print(now.second(), DEC);
monFichier1.println();
monFichier1.println("============================================================================");
monFichier1.close(); // L'enregistrement des données se fait au moment de la clôture du fichier
Serial.println(F("Enregistrement réussi du fichier historique"));
monFichier2 = SD.open(nomDuFichier, FILE_WRITE);
if (monFichier2) {
monFichier2.println("Tension:") ;
monFichier2.print(voltage);
monFichier2.print(" V: ");
monFichier2.println(voltage);
monFichier2.println("Intensité:") ;
monFichier2.print(current);
monFichier2.print(" A: ");
monFichier2.println(current);
monFichier2.println("Puissance:") ;
monFichier2.print(power);
monFichier2.print(" W: ");
monFichier2.println(power);
monFichier2.println("Energie:") ;
monFichier2.print(energy);
monFichier2.print(" KWh: ");
monFichier2.println(energy);
monFichier2.println("Frequence:") ;
monFichier2.print(frequency);
monFichier2.print(" ");
monFichier2.println(frequency);
monFichier2.println("Facteur de puissance:");
monFichier2.print(pf);
monFichier2.print(" ");
monFichier2.println(pf);
monFichier2.print(daysOfTheWeek[now.dayOfTheWeek()]);
monFichier2.print(':');
monFichier2.print(now.year(), DEC);
monFichier2.print('/');
monFichier2.print(now.month(), DEC);
monFichier2.print('/');
monFichier2.print(now.day(), DEC);
monFichier2.print("___");
monFichier2.print(now.hour(), DEC);
monFichier2.print(':');
monFichier2.print(now.minute(), DEC);
monFichier2.print(':');
monFichier2.print(now.second(), DEC);
monFichier2.println();
monFichier2.println("============================================================================");
monFichier2.close(); // L'enregistrement des données se fait au moment de la clôture du fichier
Serial.println(F("Enregistrement réussi du fichier d'accumulatuion"));
}
else {
Serial.println(F("Erreur lors de la tentative d'ouverture du fichier en écriture, sur la carte SD"));
}
Serial.println();
delay(delaiIntervalleDeMesures);
lcd.setCursor(0, 0);
lcd.print("Voltage:");
lcd.setCursor(8, 0);
lcd.print(voltage);
lcd.print("V");
lcd.setCursor(0, 1);
lcd.print("Current:");
lcd.setCursor(8, 1);
lcd.print(current);
lcd.print("A");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("PF:");
lcd.setCursor(3, 0);
lcd.print(pf);
lcd.setCursor(0, 1);
lcd.print("Freq.:");
lcd.setCursor(6, 1);
lcd.print(frequency,2);
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Power:");
lcd.setCursor(6, 0);
lcd.print(power);
lcd.print("W");
lcd.setCursor(0, 1);
lcd.print("Energy:");
lcd.setCursor(7, 1);
lcd.print(energy,3);
lcd.print("KWh");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Date: ");
lcd.print(now.day());
lcd.print('/');
lcd.print(now.month());
lcd.print('/');
lcd.print(now.year());
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Time: ");
lcd.print(now.hour());
lcd.print(':');
lcd.print(now.minute());
lcd.print(':');
lcd.print(now.second());
delay(2000);
lcd.clear();
delay(10);
}
if(Serial2.available()>0){
textMessage = Serial2.readString();
Serial.print(textMessage);
delay(10);
}
if(textMessage.indexOf("ON")>=0){
// Activer le relais et enregistrer l'état actuel
digitalWrite(2, HIGH);
String message = "Lamp is on";
sendSMS(message);
Serial.println("Relay set to ON");
textMessage = "";
return;
}
if(textMessage.indexOf("OFF")>=0){
// Désactiver le relais et enregistrer l'état actuel
digitalWrite(2, LOW);
String message = "Lamp is off";
sendSMS(message);
Serial.println("Relay set to OFF");
textMessage = "";
return;
}
}
// Fonction qui envoie des SMS
void sendSMS(String message){
// Commande AT pour mettre SIM900 en mode SMS
Serial2.println("AT+CMGF=1");
updateSerial();
// REMPLACER LES X PAR LE NUMERO DE MOBILE DU DESTINATAIRE
// UTILISER LE CODE DE FORMAT INTERNATIONAL POUR LES NUMÉROS MOBILES
Serial2.println("AT+CMGS=\"+237657057498\"");
updateSerial();
//Envoyer le SMS
Serial2.print(message);
updateSerial();
// Terminer la commande AT par un ^Z, code ASCII 26
Serial2.println((char)26);
updateSerial();
Serial2.println();
// Donner le temps au module d'envoyer des SMS
delay(10);
}
void updateSerial()
{
delay(10);
while (Serial.available())
{
Serial2.write(Serial.read());//Forward what Serial received to Software Serial Port
}
while(Serial2.available())
{
Serial.write(Serial2.read());//Forward what Software Serial received to Serial Port
}
delay(1000);
}
void status()
{
if(francs > 1000)
{
digitalWrite(relay, HIGH);
flag1=1;
flag2=0;
}
if(francs < 1000 && flag1 == 1)
{
delay(200);
Serial.Print();
init_sms();
Serial.Print();
Serial2.println("Energy Meter Balance Alert:");
Serial.Print();
Serial2.println("Low Balance\n");
Serial.Print();
Serial2.println("Balance :");
Serial.Print();
Serial2.print(francs);
Serial.Print();
Serial2.println("fcfa");
Serial.Print();
delay(200);
Serial2.println("Please recharge your energy meter soon.\n Thank you");
send_sms();
lcd.clear();
lcd.setCursor(0,1);
lcd.print("LOW Balance ");
message_sent();
flag1=0;
}
if(francs < 500 && flag2 == 0)
{
delay(200);
Serial.Print();
init_sms();
Serial.Print();
Serial2.println("Energy Meter Balance Alert:\nLight cut due to low Balance\nPlease recharge your energy meter soon.\n Thank you");
Serial.Print();
send_sms();
digitalWrite(relay, LOW);
lcd.clear();
lcd.setCursor(0,1);
lcd.print(" Light Cut Due to ");
lcd.setCursor(0,2);
lcd.print(" Low Balance ");
delay(2000);
lcd.clear();
lcd.setCursor(0,1);
lcd.print(" Please Recharge ");
lcd.setCursor(0,2);
lcd.print(" UR Energy Meter ");
delay(1000);
message_sent();
flag2=1;
}
}
void serialEvent()
{
while(Serial2.available())
{
char ch=(char)Serial2.read();
str[i++]=ch;
if(ch == '*')
{
temp=1;
lcd.clear();
lcd.print("Message Received");
delay(500);
break;
}
}
}
void confirmation_sms(){
int recharge_amount=bal.toInt();
francs+=recharge_amount;
lcd.clear();
lcd.print("Energy Meter ");
lcd.setCursor(0,1);
lcd.print("Recharged:");
lcd.print(recharge_amount);
Serial.Print();
init_sms();
send_data("System Ready");
Serial.Print();
Serial2.println("Your energy meter has been recharged.");
Serial.Print();
Serial2.print("You just recharged: ");
Serial2.print(recharge_amount);
Serial2.println("fcfa");
Serial.Print();
Serial2.print("Total Balance: ");
Serial.Print();
Serial2.print(francs);
Serial2.println("fcfa");
Serial.Print();
delay(200);
Serial2.println("Thank you to your recharge");
Serial.Print();
send_sms();
delay(500);
message_sent();
temp=0;
i=0;
x=0;
k=0;
}
}