电力监控系统 PZEM-004T模块
本帖最后由 轻轻海风 于 2020-4-21 12:39 编辑刚完成了一个可以监控家用交流电的电压、电流、负载功率、用电量的插座。
模块使用了PZEM-004T,断电也能保存电量的功能。在githua上找到了库文件。注意模块版本是V30。
分享库文件和测试阶段的源代码。成品插座用的是D1 mini板子,OLED用的是0.96寸。
程序很简单。
程序调试过程:
调试显示部分:
完成品:
手机端:
源代码:
#define BLINKER_WIFI
#include <Blinker.h>
#include <Wire.h>
#include <PZEM004Tv30.h>
#include <U8g2lib.h>
char auth[] = "********"; //改成自己在点灯app中生成的key码
char ssid[] = "********"; //改成自己的SSID
char pswd[] = "********"; //改成自己的WIFI密码
int Led = 2; //GPIO2为LED输出,低电平亮
int Led_Flag = HIGH; //默认当前灭灯
#define SCL5 //GPIO14
#define SDA4 //GPIO12
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL, SDA, U8X8_PIN_NONE); //scl,sda,rst
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); //ESP8266硬件I2C模式 GPIO5->SCL, GPIO4->SDA
/* Use software serial for the PZEM
Pin GPIO14 Rx (Connects to the Tx pin on the PZEM)
Pin GPIO12 Tx (Connects to the Rx pin on the PZEM)
*/
PZEM004Tv30 pzem(14, 12); //NodeMCU D5, D6 (RX,TX)
#define ELECTROVALENCE 0.5469 //电价
unsigned long time1;//Loop 延时用
//---------------------BLINKER_WIFI 相关参数---------------------
BlinkerNumber Voltage("voltage"); // 电压
BlinkerNumber Current("current"); // 电流
BlinkerNumber Power("power"); // 功率
BlinkerNumber Energy("energy"); // 电量
BlinkerNumber Frequency("frequency"); // 频率
BlinkerNumber Pf("pf"); // 功率因数
BlinkerNumber Electriccharge("electriccharge"); // 电费
float voltageValue;
float currentValue;
float powerValue;
float energyValue;
float frequencyValue;
float pfValue;
float electricchargeValue;
void dataRead(const String &data) // 如果未绑定的组件被触发,则会执行其中内容
{
BLINKER_LOG("Blinker readString: ", data);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print("millis", BlinkerTime);
}
void heartbeat()
{
readSensor();
Voltage.print(voltageValue);
Current.print(currentValue);
Power.print(powerValue);
Energy.print(energyValue);
Frequency.print(frequencyValue);
Pf.print(pfValue);
Electriccharge.print(electricchargeValue);
}
void readSensor() {
voltageValue = pzem.voltage();
if ( !isnan(voltageValue) ) {
Serial.print("Voltage: "); Serial.print(voltageValue); Serial.println("V");
} else {
Serial.println("Error reading voltage");
}
currentValue = pzem.current();
if ( !isnan(currentValue) ) {
Serial.print("Current: "); Serial.print(currentValue); Serial.println("A");
} else {
Serial.println("Error reading current");
}
powerValue = pzem.power();
if ( !isnan(powerValue) ) {
Serial.print("Power: "); Serial.print(powerValue); Serial.println("W");
} else {
Serial.println("Error reading power");
}
energyValue = pzem.energy();
if ( !isnan(energyValue) ) {
Serial.print("Energy: "); Serial.print(energyValue, 3); Serial.println("KWh");
electricchargeValue = energyValue * ELECTROVALENCE;//电费
} else {
Serial.println("Error reading energy");
}
frequencyValue = pzem.frequency();
if ( !isnan(frequencyValue) ) {
Serial.print("Frequency: "); Serial.print(frequencyValue, 1); Serial.println("Hz");
} else {
Serial.println("Error reading frequency");
}
pfValue = pzem.pf();
if ( !isnan(pfValue) ) {
Serial.print("PF: "); Serial.println(pfValue);
} else {
Serial.println("Error reading power factor");
}
Serial.println();
}
void showValues() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
u8g2.setCursor(0, 31);
u8g2.print("voltage");
u8g2.setCursor(64, 31);
u8g2.print("current");
u8g2.setCursor(0, 63);
u8g2.print("power");
u8g2.setCursor(64, 63);
u8g2.print("energy");
u8g2.setFont(u8g2_font_ncenB18_tr);
u8g2.setCursor(0, 20);
u8g2.print(voltageValue, 0);
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
u8g2.print(" V");
u8g2.setFont(u8g2_font_ncenB18_tr);
u8g2.setCursor(64, 20);
u8g2.print(currentValue, 2);
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
u8g2.print(" A");
u8g2.setFont(u8g2_font_ncenB18_tr);
u8g2.setCursor(0, 54);
u8g2.print(powerValue, 0);
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
u8g2.print(" W");
u8g2.setFont(u8g2_font_ncenB18_tr);
u8g2.setCursor(64, 54);
u8g2.print(energyValue * 1000, 0);
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
u8g2.print(" Wh");
u8g2.sendBuffer();
}
void setup() {
Serial.begin(115200);
pinMode(Led, OUTPUT); //初始化IO
digitalWrite(Led, HIGH); //高为关,低为开
u8g2.begin();
u8g2.setFontDirection(0);
u8g2.enableUTF8Print();
BLINKER_DEBUG.stream(Serial);
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);
Blinker.attachHeartbeat(heartbeat);
Blinker.delay(2000);
}
void loop() {
Blinker.run();
//digitalWrite(Led, !digitalRead(Led));
readSensor();
showValues();
Blinker.delay(2000);
}
本帖最后由 shark526 于 2020-4-21 11:03 编辑
看着不错哦。。。线路咋接的也分享下呗, 另PZEM-004T查了下, 有带CT线圈的,有不带的, 啥区别呢? shark526 发表于 2020-4-21 10:52
看着不错哦。。。线路咋接的也分享下呗, 另PZEM-004T查了下, 有带CT线圈的,有不带的, 啥区别呢? ...
接口简单,就是串口。
带线圈的是最大测量电流是100A,不带的是10A。 本帖最后由 雨梦随行 于 2020-5-3 21:45 编辑
你好,小白白请教下,ESP8266硬件I2C模式 GPIO5->SCL, GPIO4->SDA,GPIO5我能改成其他接口吗?比如GPIO12,13,15 老哥,接线没看懂,板子出线至4根到屏显,还有2根电源线,数据输入只有2根吗?左侧的线没看到怎么走过来的 本帖最后由 雨梦随行 于 2020-5-17 15:27 编辑
137098925 发表于 2020-5-4 09:43
老哥,接线没看懂,板子出线至4根到屏显,还有2根电源线,数据输入只有2根吗?左侧的线没看到怎么走过来的 ...
源代码有说,怎接线,你看下对不对,OLED屏使用SCL接GPIO5(D2),SDA接GPIO4(D1),PZEM模块RT接GPIO14(D5),TX接GPIO12(D6)模块串口要交叉接 雨梦随行 发表于 2020-5-4 11:09
源代码有说,怎接线,你看下对不对,OLED屏使用SCL接GPIO5(D2),SDA接GPIO4(D1),PZEM模块RT接GPIO14(D5),TX接 ...
细致,代码太多,没仔细看:lol 137098925 发表于 2020-5-4 09:43
老哥,接线没看懂,板子出线至4根到屏显,还有2根电源线,数据输入只有2根吗?左侧的线没看到怎么走过来的 ...
左边接两根数据,还有gnd和一个5v都要接到pzem-004t的,004t模块没有5v供电的。 137098925 发表于 2020-5-4 14:08
细致,代码太多,没仔细看
兄弟你那搞定了吗?我这设备买回来了,不知道我库有问题还是代码有问题,app里面一直离线,其他设备正常 老师们为什么我的什么都不显示,是不是哪里错了