จอ LCD2004 IIC 20x4 ไม่แสดงผลบนหน้าจอ เมื่อนำมาต่อกับ esp8266

สวัสดีครับ หลังจากรออะไหล่มานานผมได้ลองทำตาม

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

ผมยังติดปัญหา จอ LCD ไม่แสดงผลตรงจอ สามารถแก้ไขได้อย่างไรบ้างครับ

ไม่เข้าใจตรง คำตอบ ของพี่ @PUYIOT

อยากรู้ว่าต้องไปแก้ตรงไหน ขอบคุณครับ

//------  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 ประจำเดือนด้วย*** By PUYIOT";
String string6 = "  บาท *** By PUYIOT";
String string7 = "  เวลา ";
String string8 = ":";
//-------- 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[] = "host.";
int port = 8080;

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

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

// -------  โหลดไลบารี่ของจอ LCD มาใช้งาน โดยแบบนี้จะสามารถ Create Characterได้  --------------------------------------------------//

#include <LCD.h>                          // บรรทัดที่ 1 และ 2 สามารถสลับบรรทัดกันได้
#include <Wire.h>                         // บรรทัดที่ 1 และ 2 สามารถสลับบรรทัดกันได้
#include <LiquidCrystal_I2C.h>            //บรรทัดนี้ต้องอยู่ในบรรทัดที่ 3 เท่านั้น ถ้าไปอยู่บรรทัดที่ 1 และ 2 จะคอมไพล์ไม่ผ่าน
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //// ตั้งค่า Address ของอุปกรณ์จอ LCD ที่มีการเชื่อมต่อแบบ I2C

//----------การเก็บค่า จาก WiFimanager----------------------------------------------------------------------------------------//

bool shouldSaveConfig = false;
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}


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



//----------PZEM --------------------------------------------------------------------------------------------------------//

#include <PZEM004Tv30.h>
PZEM004Tv30 pzem(12, 13); // 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;

//ตัวแปรรับค่า ค่าไฟประจำเดือน
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 วินาที

//-----------------------------------------------------------------------------------------------------------------------//

//ชุดกำหนดการส่ง 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;
//18.00 น.
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(0, 2);
  lcd.print("     Day:  ");
  lcd.setCursor(10, 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(0, 2);
  lcd.print("      Hour:  ");
  lcd.setCursor(13, 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_H2 ที่เป็น Float ลงใน Address 0
  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(0, 0);
  lcd.print("   Sync Auto Rst    ");
  lcd.setCursor(0, 1);
  lcd.print("     By Minute      ");
  lcd.setCursor(0, 2);
  lcd.print("     Minute:  ");
  lcd.setCursor(13, 2);
  lcd.print(Rst_M, 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;
  }
}








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

void setup() {

  //-------IO NODE MCU Esp8266-------//
  pinMode(D0, OUTPUT);      //กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
  pinMode(D4, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา D4 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config


  // ให้ LED ทั้งหมดดับก่อน
  digitalWrite(D0, LOW);//ให้หลอด LED สีฟ้าดับก่อน


  Serial.begin(115200);




  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);

  //******ช่วงแรก เก็บค่าLine2_status ได้ = -1 ดังนั้น ต้องแก้ int Line2_status ;
  // และใส่ชุดนี้เข้าไปก่อน เพื่อให้เก็บค่า ine2_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.begin(20, 4);
  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(D4) == LOW) {
    digitalWrite(D0, LOW);
    Serial.println("Button Pressed");

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

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

    if (!wifiManager.autoConnect("PUY IOT")) {
      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();


    //end save
  }
  //-----------------------------------------------------------------------------------------------------------------------//

  Serial.println();
  Serial.print("local ip   : ");
  delay(100);
  Serial.println(WiFi.localIP());
  delay(100);
  Serial.print("gateway    : ");
  delay(100);
  Serial.println(WiFi.gatewayIP());
  Serial.print("subnetMask : ");
  delay(100);
  Serial.println(WiFi.subnetMask());
  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);




}//void setup

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************   จบ  void setup        **************************************************//
//------------------------------------------------------------------------------------------------------------------------//









//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       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);     //  mon
  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, 2);

  //เติม 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));

  lcd.setCursor(12, 2);

  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 (digitalRead(D4) == LOW) {

    lcd.setCursor(5, 3);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    delay(3000);

    pzem.resetEnergy();
    delay(1500);
    ESP.restart();


  }


  // กดปุ่มจาก 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 + p_tm->tm_mday +
    //                string2 + (p_tm->tm_mon + 1) + string2 + (p_tm->tm_year + 1900 + 543) +
    //                string3 + energy2 + string4 + Electric_bill + string5;

    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 ประจำเดือนด้วย*** By PUYIOT


    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 == 6 &&  p_tm->tm_min == 0 && Line1_status == 0) {
    Blynk.virtualWrite(V0, "Line Nitify 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 == 6 &&  p_tm->tm_min == 0 && Line1_status == 1) {
    delay(10);
    Line1_status1 = 1;
  }

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


  // ส่ง Line 1 ครั้งเท่านั้น  12.00 น.
  if (p_tm->tm_hour == 12 &&  p_tm->tm_min == 2 && Line12_status == 0) {
    Blynk.virtualWrite(V0, "Line Nitify 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 == 2 && Line12_status == 1) {
    delay(10);
    Line12_status1 = 1;
  }

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


  // ส่ง Line 1 ครั้งเท่านั้น  18.00 น.
  if (p_tm->tm_hour == 18 &&  p_tm->tm_min == 0 && Line13_status == 0) {
    Blynk.virtualWrite(V0, "Line Nitify 18.00");
    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 == 18 &&  p_tm->tm_min == 0 && Line13_status == 1) {
    delay(10);
    Line13_status1 = 1;
  }

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




  //---------------------- Restart ทุกวัน
  // สั่ง Restart 1 ครั้งเท่านั้น
  if (p_tm->tm_hour == 5 &&  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 == 5 &&  p_tm->tm_min == 0 && Line2_status == 1) {
    delay(10);
    Line2_status1 = 1;
  }
  //ต้องใส่วินาทีเข้าไปด้วย ไม่อย่างนั้นช่วงรอยต่อ 1 นาที จะมีการบันทึกค่าซ้ำ กัน 60 ครั้ง ซึ่งจะทำให้ EEPROMP อายุสั้นลง
  if (p_tm->tm_hour == 5 &&  p_tm->tm_min == 1 && p_tm->tm_sec <= 6  && 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 ออกมา----------//
loop1 :
  float voltage = pzem.voltage();

  if (isnan(voltage)) {

    //    lcd.setCursor(1, 0);
    //    lcd.print((char)0x20);
    //    lcd.print((char)0x20);
    //    lcd.print((char)0x20);
    //    lcd.setCursor(4, 0);
    //    lcd.print("Vac");
    //    Blynk.virtualWrite(V1, 0);
    Serial.println("อ่านค่า V ไม่ได้");
    delay(1000);
    goto loop1 ;
  } else {

    lcd.setCursor(1, 0);
    lcd.print(voltage, 0);
    lcd.setCursor(4, 0);
    lcd.print("Vac");
    Blynk.virtualWrite(V1, voltage);

  }


  float current = pzem.current();

  if (isnan(current)) {

    lcd.setCursor(13, 0);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print(" A");
    Blynk.virtualWrite(V2, 0);

  } else {

    lcd.setCursor(13, 0);
    lcd.print(current, 2);
    lcd.print(" A");
    Blynk.virtualWrite(V2, current);

  }



  float power = pzem.power();

  if (isnan(power)) {

    lcd.setCursor(0, 1);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.print((char)0x20);
    lcd.setCursor(8, 1);
    lcd.print("W");
    Blynk.virtualWrite(V3, 0);

  } else {

    lcd.setCursor(0, 1);
    lcd.print(power, 2);
    lcd.setCursor(8, 1);
    lcd.print("W");
    Blynk.virtualWrite(V3, power);

  }


loop4 :
  float energy = pzem.energy();

  if (isnan(energy)) {

    //    lcd.setCursor(10, 1);
    //    lcd.print((char)0x20);
    //    lcd.print((char)0x20);
    //    lcd.print((char)0x20);
    //    lcd.print((char)0x20);
    //    lcd.print(" kWh");
    //    Blynk.virtualWrite(V4, 0);
    delay(1000);
    goto loop4 ;
  } else {

    lcd.setCursor(10, 1);
    lcd.print(energy, 2);
    lcd.print(" kWh");
    Blynk.virtualWrite(V4, energy);

  }



loop5 :
  float frequency = pzem.frequency();

  if (isnan(frequency)) {
    //    lcd.setCursor(8, 0);
    //    lcd.print((char)0x20);
    //    lcd.print((char)0x20);
    //    lcd.setCursor(10, 0);
    //    lcd.print("Hz");
    //    Blynk.virtualWrite(V5, 0);
    Serial.println("อ่านค่า Hz ไม่ได้");
    delay(1000);
    goto loop5 ;
  } else {

    lcd.setCursor(8, 0);
    lcd.print(frequency, 0);
    lcd.setCursor(10, 0);
    lcd.print("Hz");
    Blynk.virtualWrite(V5, frequency);

  }



  float pf = pzem.pf();
  if (isnan(pf)) {
    Blynk.virtualWrite(V6, 0);
  } else {
    Blynk.virtualWrite(V6, pf);
  }
  //----------------------------------------------//


  //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);

  lcd.setCursor(0, 3);
  lcd.print("BM: ");
  lcd.setCursor(4, 3);
  lcd.print(Electric_bill , 2);
  lcd.setCursor(12, 3);
  //lcd.print("Bath");
  Blynk.virtualWrite(V7, Electric_bill);


  lcd.setCursor(12, 3);
  lcd.print(Rst_D, 0);
  //lcd.print("D");
  lcd.setCursor(15, 3);
  lcd.print(Rst_H, 0);
  lcd.setCursor(17, 3);
  lcd.print(":");
  //lcd.print("H");
  lcd.setCursor(18, 3);
  lcd.print(Rst_M, 0);

  //  Serial.print("kWh_1 : ");
  //  Serial.print(kWh_1);
  //  Serial.print(" kWh_2 : ");
  //  Serial.print(kWh_2);
  //  Serial.print(" kWh_3 : ");
  //  Serial.println(kWh_3);
  //  Serial.print("kWh_T : ");
  //  Serial.print(kWh_T);
  //  Serial.print(" kWh_T1 : ");
  //  Serial.println(kWh_T1);
  //  Serial.print("Electric_bill : ");
  //  Serial.println(Electric_bill);
  //  Serial.println();

  //----------------------------------------------//


  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 loop

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************      จบ void Loop       **************************************************//
//------------------------------------------------------------------------------------------------------------------------//


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
  Blynk.virtualWrite(V0, "ระบบเริ่มทำงาน");
}

นำภาพที่ติดปัญหากับโค้ตที่ใช้มาลงไว้ด้วยนะครับ

อัพเดทแล้วครับ

หน้าจอมันขึ้นอะไรครับ ดูไม่ออก

ว่างเปล่าเลยครับไม่มีอะไรขึ้นเลย

1 Like

เวลาที่เราสงสัยอะไร เราควรจะเริ่มต้นจากการ Confrim สิ่งนั้น เพียงอย่างเดียวก่อน การมัดรวมกันมา เพื่อนำมาแก้บ้างจุด อันนี้ จะผิดวิสัยไปซักนิด

คำถาม คือแล้วเราควรทำอย่างไร กับปัญหา
ตอบ ย้อนกลับไปที่ปัญหานั้น และโฟกัสมันอย่างจริงจัง เช่น ใช้ตัวอย่าง จาก Basic library LCD นำมารันดูว่า ได้หรือไม่ เราต่ออะไรผิดพลาดไปหรือเปล่า เมื่อโค้ตเบสิกได้แล้ว ก็กลับไปที่ โค้ตหลัก ซึ่งเราจะมั่นใจแน่ๆ ว่าการต่อเราไม่ผิด โค้ตเบสิกเราก็ออก อาจจะสรุปได้ว่า ต้องแก้ไขโค้ต หลักบางจุด ก็น่าจะออกแล้ว

ขอบคุณครับ ได้ keyword เพิ่ม

เดียวถ้าแก้ไขได้แล้วจะมารายงานครับ

เกี่ยวหรือเปล่าครับผมไม่ได้ต่อ rtc module ds3231

ทำให้ไม่แสดงผลบนหน้าจอ LCD

มันขึ้นอยู่กับว่า โค้ตหลักดึกค่าจาก rtc module ds3231 มาแสดงหรือไม่ ถ้าใช่ ก็มีส่วนครับ แนะนำทดสอบตามที่แนะนำไปก่อน การเดา อาจทำให้เราหลงประเด็นครับ

เริ่มต้น จากกระทู้นี้ครับ

ตอนนี้ได้หน้าจอขึ้นมาแบบนี้แล้วครับ เนื่องจากปรับความเข้มข้างหลัง LCD

เดียวลองเช็คสายที่ต่อไว้ใหม่แล้วกันครับ

ลองเปลี่ยนเป็น

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //// ตั้งค่า Address ของอุปกรณ์จอ LCD

เหมือนเดิมครับ ยังไม่มีข้อมูลอะไรขึ้นมาครับ

ลองเปลี่ยนเป็น 0x26 ดู คือตอนนี้เหมือน address ไม่ตรง ต้องใช้โค้ตสแกนหา address

ถ่าย lcd ด้านหลังมาดูหน่อยเป็น I2C หรือไม่

ผมไล่ตั้งแต่ 0x22 ไป ถึง 0x27 แล้วครับ

นี้ครับรูปด้านหลัง

ลง library ตัวไหนครับ เข้าไปแคปไฟล์มาให้ดูหน่อย ถ้ามีลิ้งค์ก็เอามาแปะด้วย

โหลดจากที่นี้ครับ

Screenshot_4

ลองทดสอบจาก example LCD ดูรึยัง

ลองดูแล้วครับ เป็นยังไม่มีอะไรขึ้นมาเหมือนกันครับ

ขอดูโค้ตที่ใช้หน่อยครับ