esp8266+Pzem004t v3 ค่าไฟฟ้าสะสมลดลง

จากกระทู้

ว่าด้วยเรื่อง Pzem 004t v3.0 จะวัดพลังงาน+ค่าใช้จ่าย/เดือน

ค่าไฟฟ้าสะสมลดลงเรื่อยๆเลยค่ะ เกิดจากอะไรหรอคะ

ใช้โค้ตอะไร จากไหนครับ

ใช้โค้ตนี้ จากกระทู้ที่อ้างอิงค่ะ

//------  WiFi manager  ----------------------------------------------------------------------------------------------------//
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "WiFiManager.h"
#include <FS.h>
#include <DNSServer.h>
#include "ArduinoJson.h"

//--------Line Notify ------------------------------------------------------------------------------------------------------//
#include "TridentTD_LineNotify.h"
char line_token[45] = " ";
String LineText;
String string1 = "ค่าไฟฟ้าสะสม วันที่ ";
String string2 = "/";
String string3 = "  จำนวน ";
String string4 = " หน่วย เป็นจำนวนเงินทั้งสิ้น ";
String string5 = "  บาท ระบบทำการ Reset kWh = 0 แล้ว ***ให้ตรวจสอบค่า Ft ประจำเดือนด้วย*** ";
String string6 = "  บาท *** ";
String string7 = "  เวลา ";
String string8 = ":";
String string9 = "ขณะนี้กำลังไฟฟ้าเกินค่าที่กำหนดไว้";

//-------- Blynk  ----------------------------------------------------------------------------------------------------------//
#define BLYNK_MAX_SENDBYTES 1200
#include <BlynkSimpleEsp8266.h>
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
int blynkIsDownCount = 0;
char blynk_token[34] = " ";
BlynkTimer timer;

char server[] = "oasiskit.com";
int port = 8080;

//-------- PB Reset & PB AP Config ----------------------------------------------------------------------------------------//

#define D0 16 // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP8266 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน
#define D3 1  // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้

// -------  โหลดไลบารี่ของจอ LCD มาใช้งาน โดยแบบนี้จะสามารถ Create Characterได้  --------------------------------------------------//
#include <Wire.h>                         
#include <LiquidCrystal_I2C.h>            
LiquidCrystal_I2C lcd(0x27, 20, 4); //// ตั้งค่า Address ของอุปกรณ์จอ LCD ที่มีการเชื่อมต่อแบบ I2C

//----------การเก็บค่า จาก WiFimanager----------------------------------------------------------------------------------------//
bool shouldSaveConfig = false;
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

//------------------------------------------------------------------------------------------------------------------------//
#include <EEPROM.h>

//----------PZEM --------------------------------------------------------------------------------------------------------//
#include <PZEM004Tv30.h>

#define lcd_SDA D2
#define lcd_SCL D1
#define lcd_RX D6
#define lcd_TX D7
#define buzzer D8
#define Relay D5

int relayState = 1;

PZEM004Tv30 pzem(D6, D7); // 12(D6)=RX , 13(D7) = TX  :  TX->D6(GPIO012),RX->D7(GPIO013)
//ตัวแปรรับค่า Ft จาก Blynk มาเก็บใน EEPROM
float Ft;
String Ft_1;
float Ft_2;

//ตัวแปรรับค่า วันที่ จาก Blynk มาเก็บใน EEPROM
float Rst_D;
String Rst_D1;
float Rst_D2;

//ตัวแปรรับค่า ชั่วโมง จาก Blynk มาเก็บใน EEPROM
float Rst_H;
String Rst_H1;
float Rst_H2;

//ตัวแปรรับค่า นาที จาก Blynk มาเก็บใน EEPROM
float Rst_M;
String Rst_M1;
float Rst_M2;

//ตัวแปรรับค่า MaxPower จาก Blynk มาเก็บใน EEPROM
float Set_MP;
String Set_MP1;
float Set_MP2;

//ตัวแปรรับค่า ค่าไฟประจำเดือน
float Electric_bill;
float kWh_1;
float kWh_2;
float kWh_3;
float kWh_T;
float kWh_T1;

//---- กดปุ่ม Reset kWh จาก Blynk -----------------------------------------------------------------------------------------//
int Blynkreset_kWh;
WidgetLED led_rst_kWh(V12);//จะ ON เมื่อกดปุ่มค้างไว้ 5 วินาที

//---- กดปุ่ม ON/OFF จาก Blynk -----------------------------------------------------------------------------------------//
int Blynk_CB;
WidgetLED led_CB(V31);

//ชุดกำหนดการส่ง Line แค่ครั้งเดียว
//----- รายงาน ตามวันที่ตั้งค่าจาก Blynk-----
int Line_status = 0;
int Line_status1 = 0;

//----- รายงาน ทุกวัน-----
//06.00 น.
int Line1_status = 0;
int Line1_status1 = 0;
//12.00 น.
int Line12_status = 0;
int Line12_status1 = 0;
//23.50 น.
int Line13_status = 0;
int Line13_status1 = 0;

//----- Restart ทุกวัน-----
int Line2_status  ;
int Line2_status1 = 0;

int countcheck_Blynk = 0;

float energy1;
float energy2;

//------------------------------  ระบบเวลาและการเชื่อมต่อ Web Server  ของNTP Server  -----------------------------------------//
#include <time.h>
int timezone = 7 * 3600; //ตั้งค่า TimeZone ตามเวลาประเทศไทย
int dst = 0; //กำหนดค่า Date Swing Time

BLYNK_WRITE(V10) {
  Ft_1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String
  Ft_2 = Ft_1.toFloat();//แปลงค่าจาก String เป็น Float
  //เราป้อนค่า จาก Blynk เป็น String = -0.116 ให้ Ft_1 รับค่ามา
  //Ft จะรับค่าการแปลง จาก Ft_1 เป็น Float = -0.12
  //จะเห็นว่า ค่า Folat จะปัดค่าเป็นจุดทศนิยม ไปเป็น 2 ตำแหน่งจะไม่มากกว่านี้เนื่องด้วยความสามารถตัวของอุปกรณ์เอง
  //ทำให้ค่าเพี้ยนไป ประมาณ 3.44%  ทำให้ค่าไฟ/เดือน น้อยกว่าค่าจริงไป 3.44% ประมาณ 0.64(150หน่วย) - 2.14(500หน่วย) บาท
  //โปรเจคนี้จะไม่เปลี่ยนค่า ใดๆ เพราะค่าต่างกันเล็กน้อย (1 เดือน ใช้ไฟไม่ถึง 500 หน่วยแน่นอน)

  //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถดูค่าทั้งหมดได่อย่างถูกต้อง แต่ทุกครั้งที่มีการเปลี่ยนค่า Ft วันที่ ชั่วโมง นาที  จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง

  EEPROM.put(0, Ft_2); //เขียนค่า Ft_2 ที่เป็น Float ลงใน Address 0
  EEPROM.commit(); //จบการเขียน

  Ft = EEPROM.get(0, Ft_2);//อ่าน ค่า Ft_2 ที่เป็น Float จาก Address 0
  Serial.println(Ft);//แสดงค่า Ft ใน Serial Monitor
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("...... Sync Ft .....");
  lcd.setCursor(7, 2);
  lcd.print(Ft, 3);

  delay(2000);
  lcd.clear();
}

BLYNK_WRITE(V20)//Reset kWh Automatic  ตามวันที่  ที่ตั้งจาก Blynk เข้าเครื่อง
{
  Rst_D1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String
  Rst_D2 = Rst_D1.toFloat();//แปลงค่าจาก String เป็น Float

  //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา  จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง
  EEPROM.put(20, Rst_D2); //เขียนค่า Rst_D2 ที่เป็น Float ลงใน Address 20
  EEPROM.commit(); //จบการเขียน

  Rst_D = EEPROM.get(20, Rst_D2);//อ่าน ค่า Rst_2 ที่เป็น Float จาก Address 20
  Serial.println(Rst_D);//แสดงค่า Rst ใน Serial Monitor
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Sync Auto Rst By Day");
  lcd.setCursor(6, 2);
  lcd.print("Day : ");
  lcd.setCursor(12, 2);
  lcd.print(Rst_D, 0);
  delay(2000);
  lcd.clear();
}

BLYNK_WRITE(V21)//Reset kWh Automatic  ตามชั่วโมง  ที่ตั้งจาก Blynk เข้าเครื่อง
{
  Rst_H1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String
  Rst_H2 = Rst_H1.toFloat();//แปลงค่าจาก String เป็น Float

  //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา  จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง
  EEPROM.put(30, Rst_H2); //เขียนค่า Rst_H2 ที่เป็น Float ลงใน Address 30
  EEPROM.commit(); //จบการเขียน

  Rst_H = EEPROM.get(30, Rst_H2);//อ่าน ค่า Rst_H2 ที่เป็น Float จาก Address 30
  Serial.println(Rst_H);//แสดงค่า Rst ใน Serial Monitor
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Sync AutoRst By Hour");
  lcd.setCursor(5, 2);
  lcd.print("Hour : ");
  lcd.setCursor(12, 2);
  lcd.print(Rst_H, 0);
  delay(2000);
  lcd.clear();
}

BLYNK_WRITE(V22)//Reset kWh Automatic  ตามนาที  ที่ตั้งจาก Blynk เข้าเครื่อง
{
  Rst_M1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String
  Rst_M2 = Rst_M1.toFloat();//แปลงค่าจาก String เป็น Float

  //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา  จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง
  EEPROM.put(40, Rst_M2); //เขียนค่า Rst_M2 ที่เป็น Float ลงใน Address 40
  EEPROM.commit(); //จบการเขียน

  Rst_M = EEPROM.get(40, Rst_M2);//อ่าน ค่า Rst_M2 ที่เป็น Float จาก Address 40
  Serial.println(Rst_M);//แสดงค่า Rst ใน Serial Monitor
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Sync Auto Rst");
  lcd.setCursor(5, 1);
  lcd.print("By Minute");
  lcd.setCursor(4, 2);
  lcd.print("Minute : ");
  lcd.setCursor(13, 2);
  lcd.print(Rst_M, 0);
  delay(2000);
  lcd.clear();
}

BLYNK_WRITE(V23)//Setting MaxPower จาก Blynk
{
  Set_MP1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String
  Set_MP2 = Set_MP1.toFloat();//แปลงค่าจาก String เป็น Float

  //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา  จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง
  EEPROM.put(50, Set_MP2); //เขียนค่า Rst_MP2 ที่เป็น Float ลงใน Address 50
  EEPROM.commit(); //จบการเขียน

  Set_MP = EEPROM.get(50, Set_MP2);//อ่าน ค่า Rst_MP2 ที่เป็น Float จาก Address 50
  Serial.println(Set_MP);//แสดงค่า MaxPower ใน Serial Monitor
  lcd.clear();
  lcd.setCursor(2, 1);
  lcd.print("Setting MaxPower");
  lcd.setCursor(3, 2);
  lcd.print("MaxPower = ");
  lcd.setCursor(14, 2);
  lcd.print(Set_MP, 0);
  delay(2000);
  lcd.clear();
}

BLYNK_WRITE(V11)//Reset kWh ภายใน 5 วินาที จาก Blynk
{
  int pinValue = param.asInt();
  if (pinValue == 1) {
    Blynkreset_kWh = 1;
  }
  if (pinValue == 0) {
    Blynkreset_kWh = 0;
  }
}

BLYNK_WRITE(V30) { // ON/OFF Energy Meter
  int pinValue = param.asInt();
  if (pinValue == 1) {
    Blynk_CB = 1;
    digitalWrite(Relay, HIGH);
  }
  if (pinValue == 0) {
    Blynk_CB = 0;
    digitalWrite(Relay, LOW);
  }
}

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       void setup        **************************************************//
//------------------------------------------------------------------------------------------------------------------------//

void setup() {
  //-------IO NODE MCU Esp8266-------//
  pinMode(D0, OUTPUT);      //กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
  pinMode(D3, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา D4 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
  pinMode(buzzer, OUTPUT);
  pinMode(Relay, OUTPUT);
  digitalWrite(buzzer, LOW);
  digitalWrite(Relay, HIGH);
  
  // ให้ LED ทั้งหมดดับก่อน
  digitalWrite(D0, LOW);//ให้หลอด LED สีฟ้าดับก่อน

  Serial.begin(115200);
  Serial.setDebugOutput(true);
  EEPROM.begin(512);

  //ต้องการให้รู้ว่า ค่า Ft ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว
  Ft = EEPROM.get(0, Ft_2);
  Serial.print("Ft in Void setup : ");
  Serial.println(Ft);

  //ต้องการให้รู้ว่า ค่า วันที่ ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว
  Rst_D = EEPROM.get(20, Rst_D2);
  Serial.print("Day in Void setup : ");
  Serial.println(Rst_D);

  //ต้องการให้รู้ว่า ค่า ชั่วโมง ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว
  Rst_H = EEPROM.get(30, Rst_H2);
  Serial.print("Hour in Void setup : ");
  Serial.println(Rst_H);

  //ต้องการให้รู้ว่า ค่า นาที ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว
  Rst_M = EEPROM.get(40, Rst_M2);
  Serial.print("Minute in Void setup : ");
  Serial.println(Rst_M);

  Set_MP = EEPROM.get(50, Set_MP2);
  Serial.print("Setting MaxPower : ");
  Serial.println(Set_MP);

  //******ช่วงแรก เก็บค่าLine2_status ได้ = -1 ดังนั้น ต้องแก้ int Line2_status ;
  // และใส่ชุดนี้เข้าไปก่อน เพื่อให้เก็บค่า Line2_status ได้ = 0  ได้ จากนั้นไม่ต้องใช้อีก
//       EEPROM.put(90, 0);
//       EEPROM.commit(); //จบการเขียน
//       Serial.println("Line2_status:");
//       Serial.println(Line2_status);


  //Restart ทุกวัน  เพื่อให้รู้ว่าค่า  Line2_status อยู่ในสถานะอะไร แล้วเอาค่านี้ไปทำต่อ

  Line2_status = EEPROM.get(90, Line2_status);//อ่าน ค่า Rst_H2 ที่เป็น Float จาก Address 90
  Serial.print("Line2_status:");//แสดงค่า Rst ใน Serial Monitor
  Serial.println(Line2_status);//แสดงค่า Rst ใน Serial Monitor

  lcd.init();
  lcd.clear();

  //read configuration from FS json
  Serial.println("mounting FS...");//แสดงข้อความใน Serial Monitor
  if (SPIFFS.begin()) {
    Serial.println("mounted file system");//แสดงข้อความใน Serial Monitor
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");//แสดงข้อความใน Serial Monitor
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed json");//แสดงข้อความใน Serial Monitor
          strcpy(blynk_token, json["blynk_token"]);
          strcpy(line_token, json["line_token"]);
        } else {
          Serial.println("failed to load json config");//แสดงข้อความใน Serial Monitor
        }
      }
    }
  } else {
    Serial.println("failed to mount FS");//แสดงข้อความใน Serial Monitor
  }
  //end read

  //------------สร้างชื่อกำกับช่อง-----------------------------------------------------------------------//
  WiFiManagerParameter custom_text0("<p> </p>");
  WiFiManagerParameter custom_text1("<label>ป้อน Blynk Token</label>");
  WiFiManagerParameter custom_text2("<label>ป้อน LINE Token</label>");

  //------------สร้างช่อง----------------------------------------------------------------------------//
  WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 34);
  WiFiManagerParameter custom_line_token("LINE", "line_token", line_token, 45);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //------------เรียงลำดับ ชื่อกำกับช่อง + ช่อง-----------------------------------------------------------//
  wifiManager.addParameter(&custom_text0);
  wifiManager.addParameter(&custom_text1);
  wifiManager.addParameter(&custom_blynk_token);
  wifiManager.addParameter(&custom_text2);
  wifiManager.addParameter(&custom_line_token);

  delay(1000);

  for (int i = 5; i > -1; i--) {  // นับเวลาถอยหลัง 5 วินาทีก่อนกดปุ่ม AP Config
    digitalWrite(D0, HIGH);
    delay(500);
    digitalWrite(D0, LOW);
    delay(500);
    Serial.print (String(i) + " ");
  }

  if (digitalRead(D3) == LOW) {
    digitalWrite(D0, LOW);
    Serial.println("Button Pressed");

    wifiManager.resetSettings();//ให้ล้างค่า SSID และ Password ที่เคยบันทึกไว้

    // wifiManager.autoConnect(); ใช้สร้างชื่อแอคเซสพอยต์อันโนมัติจาก ESP + ChipID

    if (!wifiManager.autoConnect("AutoConnectAP")) {
      Serial.println("failed to connect and hit timeout");
      delay(3000);
      //reset and try again, or maybe put it to deep sleep
      ESP.reset();
      delay(5000);
    }
  }

  Serial.println(": Connected.......OK!)");

  strcpy(blynk_token, custom_blynk_token.getValue());
  strcpy(line_token, custom_line_token.getValue());
  //save the custom parameters to FS

  if (shouldSaveConfig) {
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    //------------------------------------------------------------------
    Serial.println("saving Blynk config");
    json["blynk_token"] = blynk_token;
    File configFile = SPIFFS.open("/config.json", "w");
    //------------------------------------------------------------------
    Serial.println("saving line config");
    json["line_token"] = line_token;
    File configFile1 = SPIFFS.open("/config.json", "w");
    //------------------------------------------------------------------

    if (!configFile) {
      Serial.println("failed to open config file for writing");//แสดงข้อความใน Serial Monitor
    }

    json.printTo(configFile);
    configFile.close();
    json.printTo(configFile1);
    configFile1.close();
  }
  //-----------------------------------------------------------------------------------------------------------------------//

  Serial.println();
  Serial.print("local ip   : ");
  delay(100);
  Serial.println(WiFi.localIP());
  delay(100);
  Serial.print("SSID       : ");
  delay(100);
  Serial.println(WiFi.SSID());
  Serial.print("Password   : ");
  delay(100);
  Serial.println(WiFi.psk());

  //-----------------------------------------------------------------------------------------------------------------------//
  Serial.println();
  //Print เพื่อเชคว่าค่าที่บันทึกไว้ยังอยู่หรือไม่
  Serial.println("เชคว่าค่าที่บันทึกไว้ยังอยู่หรือไม่");

  Serial.print("Blynk_token = ");
  Serial.println(blynk_token);
  Serial.print("Line_token = ");
  Serial.println(line_token);

  LINE.setToken(line_token);
  //-----------------------------------------------------------------------------------------------------------------------//
  configTime(timezone, dst, "1.th.pool.ntp.org", "0.asia.pool.ntp.org", "3.asia.pool.ntp.org"); //แสดงเวลาปัจจุบัน ดึงจากServer
  while (!time(nullptr)) {//วนจนกว่า ค่าเวลา จะถูกต้อง แล้วจึงปล่อยออกไป
    delay(500);
  }

  Blynk.config(blynk_token, server, port); // Blynk.config(blynk_token);////เริ่มการเชื่อมต่อ Blynk Server แบบปกติ
  ////เริ่มการเชื่อมต่อ Blynk Server*********สำหรับ Server local ที่แจกให้ เพิ่ม, server, port  แค่นี้จบ

  timer.setInterval(30000L, reconnecting);

  lcd.init();
  lcd.backlight();
  
  lcd.setCursor(5,0);
  lcd.print("PROJECT 4C1");
  lcd.setCursor(4,1);
  lcd.print("Smart Energy");
  lcd.setCursor(7,2);
  lcd.print("Meter");
  lcd.setCursor(5,3);
  lcd.print("GROUP 6321");
  delay(5000);
  lcd.clear();
}

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       void Loop        ***************************************************//
//------------------------------------------------------------------------------------------------------------------------//
void loop() {
  //-------  แสดงค่า เวลา -------------------------//
  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);

  String now_time = "";
  now_time = now_time + p_tm->tm_hour;      // hour
  now_time = now_time + ":";                // hour:
  now_time = now_time + p_tm->tm_min;       // hour:min
  now_time = now_time + ":";                // hour:min:
  now_time = now_time + p_tm->tm_sec;       // hour:min:sec
  // Serial.println(now_time);              // ส่งข้อความออกทาง Serial Monitor พร้อมขึ้นบรรทัดใหม่

  String now_day = "";
  now_day = now_day + p_tm->tm_mday;                // day
  now_day = now_day + "/";                          // -
  now_day = now_day + (p_tm->tm_mon + 1);           //  month
  now_day = now_day + "/";                          //  -
  now_day = now_day + (p_tm->tm_year + 1900 + 543); // year

  //Serial.println(now_day);                  // ส่งข้อความออกทาง Serial Monitor พร้อมขึ้นบรรทัดใหม่
  String dateTime = now_day + " ";            // day-mon-year

  lcd.setCursor(0, 3);
  //เติม 0 กรณีเป็นเลข วัน เดือน ชม. นาที วินาที ตัวเดียว
  if (p_tm->tm_mday < 10)  {
    lcd.print("0");
    lcd.print(p_tm->tm_mday);
  } else lcd.print(p_tm->tm_mday);
  lcd.print('/');

  if ((p_tm->tm_mon + 1) < 10)  {
    lcd.print("0");
    lcd.print((p_tm->tm_mon + 1));
  } else lcd.print((p_tm->tm_mon + 1));
  lcd.print('/');
  lcd.print((p_tm->tm_year + 1900 + 543 - 2500));

  lcd.setCursor(12, 3);
  if (p_tm->tm_hour < 10)  {
    lcd.print("0");
    lcd.print(p_tm->tm_hour);
  }  else lcd.print(p_tm->tm_hour);
  lcd.print(':');

  if (p_tm->tm_min < 10)  {
    lcd.print("0");
    lcd.print(p_tm->tm_min);
  } else lcd.print(p_tm->tm_min);
  lcd.print(':');

  if (p_tm->tm_sec < 10)  {
    lcd.print("0");
    lcd.print(p_tm->tm_sec);
  } else lcd.print(p_tm->tm_sec);

  if (Blynk_CB == 1) {
    Blynk.virtualWrite(V0, "ระบบเริ่มทำงาน");
    led_CB.on();
    }
  if (Blynk_CB == 0) {
    Blynk.virtualWrite(V0, "POWER OFF");
    led_CB.off();
    }
  
  // กดปุ่มจาก Blynk 5 วินาที เพื่อ Reset kWh กดค้างจนกว่า LED จะดับ  แบบที่ 2
  // จะมีการ Restart ระบบด้วย
  if (Blynkreset_kWh == 1) {
    led_rst_kWh.on();
    lcd.setCursor(5, 3);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    Blynk.virtualWrite(V0, "มีการ RESET ระบบ");
    delay(3000);
    pzem.resetEnergy();
    led_rst_kWh.off();
    ESP.restart();
  }
  if (Blynkreset_kWh == 0) {
    led_rst_kWh.off();
  }

  //  Reset kWh  แบบ Auto โดยการตั้งค่ามาจาก Blynk โดยเก็บไว้ใน EEPROM ของเครื่อง  แบบที่ 3  กรณีประจำเดือน
  // ส่ง Line 1 ครั้งเท่านั้น  กรณีประจำเดือน  จากนั้นระบบจะ Restart
  if (Rst_D == p_tm->tm_mday && Rst_H == p_tm->tm_hour &&  Rst_M == p_tm->tm_min && Line_status == 0) {
    //loop ป้องกันการอ่านค่าไม่ได้
loop9 :
    energy2 = pzem.energy();
    if (isnan(energy2)) {
      delay(1000);
      goto loop9 ;
    }
   
    LineText  = string1 + now_day + string7 + now_time +
                string3 + energy2 + string4 + Electric_bill + string5;

    //ค่าไฟฟ้าสะสม วันที่ x/x/xxx เวลา x:x:x  จำนวน 2.65 หน่วย เป็นจำนวนเงินทั้งสิ้น 49.78  บาท
    //ระบบทำการ Reset kWh = 0 แล้ว ***ให้ตรวจสอบค่า Ft ประจำเดือนด้วย*** 

    LINE.notify(LineText);
    delay(200);
    Blynk.virtualWrite(V0, "จะ RST ระบบใน 1นาที");

    //Serial.println("reset kWh");มันจะ Reset ซ้ำ กันใน 1 นาทีนี้ และยกเลิกจนกว่าจะขึ้นนาทีใหม่

    Line_status = 1;
    Line_status1 = 0;
  }
  else if (Rst_D == p_tm->tm_mday && Rst_H == p_tm->tm_hour &&  Rst_M == p_tm->tm_min && Line_status == 1) {
    delay(10);
    Line_status1 = 1;
  }
  //หลังจากส่งไลน์ เสร็จแล้ว อีก 1 นาที ให้ระบบ resetEnergy และ Restart
  if (Rst_M != p_tm->tm_min && Line_status1 == 1 ) {
    delay(10);
    Line_status = 0;
    delay(1500);
    pzem.resetEnergy();
    delay(1500);
    ESP.restart();
  }

  //  ส่ง Line ค่าไฟ ประจำวัน
  // ส่ง Line 1 ครั้งเท่านั้น  6.00 น.
  if (p_tm->tm_hour == 06 &&  p_tm->tm_min == 00 && Line1_status == 0) {
    Blynk.virtualWrite(V0, "Line Notify 6.00");
    delay(100);
loop10 :
    energy1 = pzem.energy();
    if (isnan(energy1)) {
      delay(1000);
      goto loop10 ;
    }
    LineText = string1 + now_day + string7 + now_time +
               string3 + energy1 + string4 + Electric_bill + string6;

    LINE.notify(LineText);
    delay(200);

    Line1_status = 1;
    Line1_status1 = 0;
  }
  else if (p_tm->tm_hour == 06 &&  p_tm->tm_min == 00 && Line1_status == 1) {
    delay(10);
    Line1_status1 = 1;
  }

  if (p_tm->tm_hour == 06 &&  p_tm->tm_min == 01 && Line1_status1 == 1 ) {
    delay(10);
    Line1_status = 0;
  }

  // ส่ง Line 1 ครั้งเท่านั้น  12.00 น.
  if (p_tm->tm_hour == 12 &&  p_tm->tm_min == 00 && Line12_status == 0) {
    Blynk.virtualWrite(V0, "Line Notify 12.00");
    delay(100);

loop11 :
    energy1 = pzem.energy();
    if (isnan(energy1)) {
      delay(1000);
      goto loop11 ;
    }
    LineText = string1 + now_day + string7 + now_time +
               string3 + energy1 + string4 + Electric_bill + string6;

    LINE.notify(LineText);
    delay(200);

    Line12_status = 1;
    Line12_status1 = 0;
  }
  else if (p_tm->tm_hour == 12 &&  p_tm->tm_min == 00 && Line12_status == 1) {
    delay(10);
    Line12_status1 = 1;
  }

  if (p_tm->tm_hour == 12 &&  p_tm->tm_min == 03 && Line12_status1 == 1 ) {
    delay(10);
    Line12_status = 0;
  }

  // ส่ง Line 1 ครั้งเท่านั้น  23.50 น.
  if (p_tm->tm_hour == 23 &&  p_tm->tm_min == 50 && Line13_status == 0) {
    Blynk.virtualWrite(V0, "Line Notify 23.50");
    delay(100);
loop12 :
    energy1 = pzem.energy();
    if (isnan(energy1)) {
      delay(1000);
      goto loop12 ;
    }
    LineText = string1 + now_day + string7 + now_time +
               string3 + energy1 + string4 + Electric_bill + string6;
    LINE.notify(LineText);
    delay(200);

    Line13_status = 1;
    Line13_status1 = 0;
  }
  else if (p_tm->tm_hour == 23 &&  p_tm->tm_min == 50 && Line13_status == 1) {
    delay(10);
    Line13_status1 = 1;
  }

  if (p_tm->tm_hour == 23 &&  p_tm->tm_min == 51 && Line13_status1 == 1 ) {
    delay(10);
    Line13_status = 0;
  }

  //---------------------- Restart ทุกวัน
  // สั่ง Restart 1 ครั้งเท่านั้น
  if (p_tm->tm_hour == 1 &&  p_tm->tm_min == 0 && Line2_status == 0) {
    //ถึงเวลาที่ตั้ง ส่ง Line บอกว่า เครื่อง Restart
    Blynk.virtualWrite(V0, "Pzem RST");
    delay(100);
    LINE.notify("PZEM SYSTEM RESTART");
    delay(200);
   
    // ให้ Line2_status = 1 แล้วเก็บใน EEPROMP จากนั้นเครื่องจะ Restart โดยเก็บค่า Line2_status = 1ไว้
    Line2_status = 1;
    Line2_status1 = 0;
    EEPROM.put(90, Line2_status); //เขียนค่า Line2_status = 1 ที่เป็น Float ลงใน Address 90
    EEPROM.commit(); //จบการเขียน
    Serial.println("Line2_status:");//แสดงค่า Rst ใน Serial Monitor
    Serial.println(Line2_status);//แสดงค่า Rst ใน Serial Monitor

    ESP.restart();
  }
  else if (p_tm->tm_hour == 1 &&  p_tm->tm_min == 0 && Line2_status == 1) {
    delay(10);
    Line2_status1 = 1;
  }
  //ต้องใส่วินาทีเข้าไปด้วย ไม่อย่างนั้นช่วงรอยต่อ 1 นาที จะมีการบันทึกค่าซ้ำ กัน 60 ครั้ง ซึ่งจะทำให้ EEPROMP อายุสั้นลง
  if (p_tm->tm_hour == 1 &&  p_tm->tm_min == 0 && p_tm->tm_sec <= 5  && Line2_status1 == 1 ) {
    delay(10);
    Line2_status = 0;
    EEPROM.put(90, Line2_status);//เขียนค่า Line2_status = 0 ที่เป็น Float ลงใน Address 90
    EEPROM.commit(); //จบการเขียน
    Serial.print("Line2_status:");
    Serial.println(Line2_status);
  }

  //--------- แสดงค่า ต่างๆ ของ PZEM --------------//
  float voltage = pzem.voltage();
  lcd.setCursor(0,0); 
  lcd.print("V");
  lcd.setCursor(3,0);
  if(isnan(voltage)){
    lcd.setCursor(5,0); 
    }
    lcd.print(voltage, 1);
    Blynk.virtualWrite(V1, voltage);

  float current = pzem.current();
  lcd.setCursor(12,0);
  lcd.print("A");
  lcd.setCursor(16,0);
   if(isnan(current)){
    lcd.setCursor(17,0); 
    }
    lcd.print(current, 2);
    Blynk.virtualWrite(V2, current);
  

  float power = pzem.power();
  lcd.setCursor(0,1);
  lcd.print("W");
  if(power < 10)         lcd.setCursor(5,1);
  else if(power < 100)   lcd.setCursor(4,1);
  else if(power < 1000)  lcd.setCursor(3,1);
  else if(power < 10000) lcd.setCursor(2,1);
  else {
    lcd.setCursor(5,1);
    }
    lcd.print(power, 1); 
    Blynk.virtualWrite(V3, power); 
  
  float energy = pzem.energy();
  lcd.setCursor(12,1);
  lcd.print("U");
  if(energy < 10)        lcd.setCursor(17,1);
  else if(energy < 100)  lcd.setCursor(16,1);
  else if(energy < 1000) lcd.setCursor(15,1);
  else {
    lcd.setCursor(17,1);
    }
    lcd.print(energy, 1);
    Blynk.virtualWrite(V4, energy); 

  float frequency = pzem.frequency();
  lcd.setCursor(0,2);
  lcd.print("Hz");
  lcd.setCursor(4,2);
  if(isnan(frequency)){
    lcd.setCursor(5,2); 
    }
    lcd.print(frequency, 1);
    Blynk.virtualWrite(V5, frequency);

  float pf = pzem.pf();
  if (isnan(pf)) {
    Blynk.virtualWrite(V6, 0);
  } else {
    lcd.setCursor(12,2);
    lcd.print("PF");
    lcd.setCursor(16,2);
    lcd.print(pf, 2);
    Blynk.virtualWrite(V6, pf);
  }

  //-------------------------overpower();------------------------------
  if (power - Set_MP >= Set_MP/5) {  //ถ้ากระแสมากกว่ากระแสสูงสุดที่กำหนดไว้ buzzer จะดังและ relay จะตัด
    LineText  = string9;
    LINE.notify(LineText);
    delay(100);
    Blynk.virtualWrite(V0, "Over Power");
    
    digitalWrite(buzzer, HIGH);
    delay(150);
    digitalWrite(buzzer, LOW);
    digitalWrite(Relay, LOW);
    }
  relayState = digitalRead(Relay);
  if (relayState == 0) {
    lcd.clear();
    lcd.setCursor(5,1);
    lcd.print("OVER POWER");
    lcd.setCursor(4,2);
    lcd.print("PLEASE RESET");
    delay(5000);
    lcd.clear();
    }
    
  //--------------------------------------------------------------------

  //1.2 อัตราปกติปริมาณการใช้พลังงานไฟฟ้าเกินกว่า 150 หน่วยต่อเดือน
  //ที่บ้านเราใช้ค่านี้ ประเภท 1125 คือ ใช้ไฟฟ้าเกิน 150 หน่วย/เดือน อัตราค่าบริการ 38.22 บาท/เดือน

  //1     -  150 หน่วยละ 3.2484  บาท
  if (energy >= 1 && energy <= 150) {
    kWh_1 = energy * 3.2484;
  }
  if (energy > 150) {
    kWh_1 = 150 * 3.2484;
  }

  //หน่วยที่  151    -  400 หน่วยละ 4.2218  บาท
  if (energy >= 151 && energy <= 400) {
    kWh_2 = (energy - 150) * 4.2218;
  }
  if (energy > 400) {
    kWh_2 = 250 * 4.2218;
    //401        -- >   หน่วยละ 4.4217  บาท
    kWh_3 = (energy - 400) * 4.4217;
  }

  //รวมค่าใช้จ่ายทั้งหมด
  kWh_T = kWh_1 + kWh_2 + kWh_3;
  kWh_T1 = kWh_T + 38.22 + (energy * Ft);

  Electric_bill = kWh_T1 + (kWh_T1 * 0.07);
  Blynk.virtualWrite(V7, Electric_bill);

  countcheck_Blynk ++;
  if (countcheck_Blynk  == 2) {//ทุกๆ 3 วินาที เชค temp + humid 1 ครั้ง
    check_Blynk();
  }
  if (countcheck_Blynk  == 3) {//ทุกๆ 3 วินาที เชค temp + humid 1 ครั้ง
    countcheck_Blynk  = 0;
  }

  timer.run();//ให้เวลาของ Blynk ทำงาน
  delay(2000);
}

void check_Blynk() {
  //------------- Blynk Connect ---------------//
  if (Blynk.connected())  {
    Blynk.run();
    digitalWrite(D0, LOW);
  } else {
    digitalWrite(D0, LOW);
    delay(200);
    digitalWrite(D0, HIGH);
    delay(100);
  }
}

void reconnecting() {
  if (!Blynk.connected())  {
    blynkIsDownCount++;
    BLYNK_LOG("blynk server is down! %d  times", blynkIsDownCount);
    Blynk.connect(5000);
    }
}

BLYNK_CONNECTED() {
  Blynk.syncAll();//ให้ซิงค์ข้อมูลทั้งหมดล่าสุดจาก Blynk Server
  }

1 Like

คุณพระ! เกิดอะไรขึ้นกับค่า​ FT​ ครับ​ ทำไมมันมีค่าติดลบอยู่ครับ

ดูค่า ft จาก https://www.mea.or.th/content/detail/2985/2987/474 แล้วก็นำมาใช้ปกติเลยนะคะ แต่ทำไมค่าลดลงก็ไม่รู้ค่ะ

ตอนนี้ตั้งขอสังเกตอะไรไว้บ้างครับ สงสัย ตรงจุดไหนเป็นพิเศษว่าอาจจะเป๋นสาเหตุนั้นๆ

ขอ​ capture ของblynk.เต็มๆ​ ได้มั๊ยครับ

นี่ค่ะ

ค่า แรงดัน กระแส PF ถูกแล้วครับ ลองดู code ที่นำค่า 38.60W ไปเป็นค่าเงิน ดูสูตร แล้วลองคำนวณดูก่อนครับ ถ้าคำนวณถูก ก็มาดูตัวแปรที่รับค่ามาว่า มันแสดงค่าถูกหรือปล่าวครับ อีกส่วนหนึ่ง code ที่แสดงให้ดูคือ code ที่กำลังใช้อยู่ใช่มั๊ยครับ

1 Like

ผมลองคำนวนเล่นๆ เหมือนว่าเราไปดึงค่า ft มาจาก eeprom ผมไม่แน่ใจว่า มันดึงมาถูกหรือไม่ ตอนนี้ผมสนใจอยู่ 2 ค่าคือ energy กับ Ft ในระดับจุดทศนิยม หากมีการเพี้ยนไป 0.1 หรือ 0.01 มันสามารถ ส่งผลต่อผลลัพธ์ ได้ใกล้เคียงกับ พิกัดค่าไฟที่ถ่ายมาให้ดู

ภาพ

ภาพ

ลอง prinf 2 ค่านี้ออกมาดูก่อนที่จะให้ส่ง line ก็ได้ครับ สัก 2 - 3 รอบ

ใช่ค่ะ เดี๋ยวจะลองสั่งให้ print ค่า ft กับ energy ดูว่าค่าปกติมั้ย

ค่ากลับมาปกติแล้วค่ะ เหมือน library มันรวนเลยอัพเดทเวอร์ชั่นแล้วอัพโหลดโค้ดใหม่

ขอสอบถามหน่อยค่ะ

//---------------------- Restart ทุกวัน
  // สั่ง Restart 1 ครั้งเท่านั้น
  if (p_tm->tm_hour == 1 &&  p_tm->tm_min == 0 && Line2_status == 0) {
    //ถึงเวลาที่ตั้ง ส่ง Line บอกว่า เครื่อง Restart
    Blynk.virtualWrite(V0, "Pzem RST");
    delay(100);
    LINE.notify("PZEM SYSTEM RESTART");
    delay(200);
   
    // ให้ Line2_status = 1 แล้วเก็บใน EEPROMP จากนั้นเครื่องจะ Restart โดยเก็บค่า Line2_status = 1ไว้
    Line2_status = 1;
    Line2_status1 = 0;
    EEPROM.put(90, Line2_status); //เขียนค่า Line2_status = 1 ที่เป็น Float ลงใน Address 90
    EEPROM.commit(); //จบการเขียน
    Serial.println("Line2_status:");//แสดงค่า Rst ใน Serial Monitor
    Serial.println(Line2_status);//แสดงค่า Rst ใน Serial Monitor

    ESP.restart();
  }
  else if (p_tm->tm_hour == 1 &&  p_tm->tm_min == 0 && Line2_status == 1) {
    delay(10);
    Line2_status1 = 1;
  }
  //ต้องใส่วินาทีเข้าไปด้วย ไม่อย่างนั้นช่วงรอยต่อ 1 นาที จะมีการบันทึกค่าซ้ำ กัน 60 ครั้ง ซึ่งจะทำให้ EEPROMP อายุสั้นลง
  if (p_tm->tm_hour == 1 &&  p_tm->tm_min == 0 && p_tm->tm_sec <= 5  && Line2_status1 == 1 ) {
    delay(10);
    Line2_status = 0;
    EEPROM.put(90, Line2_status);//เขียนค่า Line2_status = 0 ที่เป็น Float ลงใน Address 90
    EEPROM.commit(); //จบการเขียน
    Serial.print("Line2_status:");
    Serial.println(Line2_status);
  }

โค้ดตรงส่วนนี้เอาไว้ใช้ทำอะไรหรอคะ

1 Like

เป็นการสั่งให้ esp8266 Restart ทุกวันครับ ไม่ต้องใช้ก็ได้ ลบส่วนนี้ กับส่วนที่เกี่ยวข้องตามตำแหน่งที่ต่างๆ ออกไปได้เลยครับ

2 Likes

อยากรู้ว่าอัพเป็น version อะไรถึงหายครับ อยากให้ระบุไว้หน่อย เผื่อ ใช้อ้างอิง version ที่ เสถียรที่สุด

Arduino 1.8.7
Json 5.13.3
WifiManager อัพเดทเป็นเวอร์ชั่นล่าสุด 2.0.3 alpha ค่ะ

1 Like

ถ้าอยากให้แจ้งเตือนว่าแต่ละวันใช้ไปกี่ยูนิตต้องทำยังไงหรอคะ

เยี่ยมมากครับ เผื่อ(ผมนี้แหละ) อาจจะมีใครติดปัญหาเดียวกัน จะได้มีแนวทาง

you're right seth meyers GIF by Late Night with Seth Meyers