使用 ESP32 计算电能表中的电能的问题

Posted

技术标签:

【中文标题】使用 ESP32 计算电能表中的电能的问题【英文标题】:Problem in Computing the Energy in Energy Meter using ESP32 【发布时间】:2020-12-15 12:54:27 【问题描述】:

所以我和我的队友一直在研究我们关于能量计的论文项目。在我们的项目中,esp32 是我们使用的主板。我们的主板上还有电压传感器(ZMPT101B)和电流传感器(SCT013 100V:50mA)。

这里是 ZMPT101B 的链接...https://www.autobotic.com.my/ac-voltage-sensor-module-zmpt101b-single-phase

这里是 SCT013 的链接...https://innovatorsguru.com/sct-013-000/

我也在使用 https://www.arduino.cc/reference/en/libraries/emonlib/ 的 Emon 库来读取电流和电压传感器抛出的值。

为了获得功率,我将电流值和电压值相乘。

然后要获得能量值,我将需要时间,因为能量 = 功率 x 时间。我在网上看到公式,它使用millis()函数来获取时间......但说实话我不知道millis是如何工作的。

 last_time = current_time;
 current_time = millis();
 Wh = Wh + power *(( current_time -last_time) /3600000.0) ; 

能量值将被发送到数据库,在我们的例子中,我们的数据库是 firebase 实时数据库。使用此代码...

  Firebase.setDouble(firebaseData, path , KWh);

如果断电,ESP32 也会死机,停止工作。所以我们决定加上这行代码……

Firebase.getInt(firebaseData, path);
totalEnergyDB = (firebaseData.intData());
preKWh = totalEnergyDB;

....一旦再次打开esp32,此代码用于从firebase获取数据......其中从firebase获取的数据将用作pre-kwh。

我使用这行代码添加了预千瓦时的当前读数。

KWh = (Wh/1000) + preKWh;

我将电压和电流传感器的校准设置为高,这样变化就会很容易被看到。

我的问题是我能够从数据库中获取值,但能量公式似乎无法正常工作。

这是串行监视器的结果...(171 KWH 是数据库的初始值) enter image description here

我无法向您展示功率的结果,但它在 lcd 上说它大约是 3000W!但是即使打开了一个多小时,能量读数仍然没有改变:(

这是我们项目的完整代码...

#include "EmonLib.h"  
#define VOLT_CAL 52.5000
#define CURRENT_CAL 10.07
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

EnergyMonitor emon1;
int i;

// Wifi
#include <WiFi.h>
#include "FirebaseESP32.h"
   
#define FIREBASE_HOST "#!@#!@$!@a.firebaseio.com" 
#define FIREBASE_AUTH "RRw3u$!@%!@#%@#%$@%^#$^oI8LpQyVo0AWBC"
#define WIFI_SSID "WIFI"
#define WIFI_PASSWORD "PASSWORD"

// Define Firebase Data object
FirebaseData firebaseData;

// Root Path
String path = "/USER INFO/jdc/totalEnergy";

unsigned long last_time =0;
unsigned long current_time =0;
int Wh = 0;  
int preKWh;
int KWh;
int totalEnergyDB;

void setup() 
  // put your setup code here, to run once:
  Serial.begin(115200);
  initWifi();
  lcd.init();
  lcd.backlight();
  lcd.begin(4, 20);
  
  lcd.clear();
  lcd.setCursor(1,4);
  lcd.print("LOADING...");
  Serial.print("LOADING...");
  emon1.voltage(32, VOLT_CAL, 1.7);  // Voltage: input pin, calibration, phase_shift
  emon1.current(33, CURRENT_CAL); 
  for ( i = 0; i < 5; i++ ) 
  emon1.calcVI(20,2000); 
  float currentDraw            = emon1.Irms;  
  float supplyVoltage          = emon1.Vrms; 
      
  
delay(1); 
  Firebase.getInt(firebaseData, path);
  totalEnergyDB = (firebaseData.intData()); 
  preKWh = totalEnergyDB;
   


void loop() 
  emon1.calcVI(20,2000);
  float currentDraw     = emon1.Irms;             //extract Irms into Variable
  float supplyVoltage   = emon1.Vrms;
  float power = currentDraw * supplyVoltage;
  last_time = current_time;
  current_time = millis();
  Wh = Wh + power *(( current_time -last_time) /3600000.0) ; 
  KWh = (Wh/1000) + preKWh;

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("VOLTAGE: ");
  lcd.print(supplyVoltage);
  lcd.print(" V");
  lcd.setCursor(0,1);
  lcd.print("CURRENT: ");
  lcd.print(currentDraw);
  lcd.print(" A");
  lcd.setCursor(0,2);
  lcd.print("POWER: ");
  lcd.print(power);
  lcd.print(" W");
  lcd.setCursor(0,3);
  lcd.print("ENERGY: ");
  lcd.print(KWh);
  lcd.print(" KWh");
  
  delay(100);  

    if (isnan(Wh))                        // if Wh is Not A Number
    Serial.println(F("Error reading Energy!"));
  
  else 
    Serial.print(F("preKWh: "));
    Serial.print(preKWh);
    Serial.println(F("KWH"));
    Serial.print(F("Energy: "));
    Serial.print(KWh);
    Serial.println(F("KWH"));
    Firebase.setDouble(firebaseData, path , KWh);
    
    delay(100);
  
    
    
  

void initWifi()
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  
    Serial.print(".");
    delay(300);
  
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);
  
  //Set database read timeout to 1 minute (max 15 minutes)
  Firebase.setReadTimeout(firebaseData, 1000 * 60);
  //tiny, small, medium, large and unlimited.
  //Size and its write timeout e.g. tiny (1s), small (10s), medium (30s) and large (60s).
  Firebase.setwriteSizeLimit(firebaseData, "tiny");

谁能帮我写代码。应该做哪些改变?

【问题讨论】:

【参考方案1】:

查看您的数据类型,您将WhKWh 存储为一个整数,并且您向它们添加了可能非常小的浮点数(想象(current_time - last_time)1000(1 秒),然后是@987654325 @ 会变成Wh + power * 2.78e-5,这会导致舍入错误,除非你的功耗很大。要解决这个问题,你不应该舍入为整数,并将WhKWh 保留为浮点数。

【讨论】:

抱歉回复晚了...所以你的意思是代码应该是这样的.....?浮动 Wh = 0;浮动千瓦时; 是的。试一试,打印一些中间值,看看现在是否符合您的期望。 当我尝试浮动时,lcd 中的值会超时冻结。 但它解决了WhkWh 值吗?您是否打印它们以查看它们是否正确?您是否在将值写入 LCD 的同时打印了该值,以查看当 LCD 冻结时该代码是否仍然运行,以及结果是否仍然正确? LCD 本身是一个单独的问题。

以上是关于使用 ESP32 计算电能表中的电能的问题的主要内容,如果未能解决你的问题,请参考以下文章

精选 || 深度学习与流式计算在电能质量分析评估中的机遇与挑战

试图解释从电能表返回的数据

如何用VB通过485串口来读取电能表的数据?

电能表中的旋转木马

三相四线电能表检定TD4550三相电能表携式校验装置

功率放大器在电容耦合型无线电能传输系统中的应用