ESP8266 WiFi物联网智能插座—电能计量

这篇具有很好参考价值的文章主要介绍了ESP8266 WiFi物联网智能插座—电能计量。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、芯片功能

2、性能指标

3、寄存器说明

4、UART通信协议

4.1、写操作帧格式和时序

4.2、读操作帧格式和时序

4.3、读取全电参数数据包

4.4、配置波特率

4.5、UART保护机制

5、功能说明

5.1、电流电压瞬态波形计量

5.2、有功功率

5.3、有功功率防潜动

5.4、电能计量 

5.5、电流电压有效值

5.6、过流检测

5.7、过零检测

5.8、线电压频率检测

6、应用电路

7、驱动程序

8、替代方案


WiFi物联网智能插座硬件设计的重点就是电能计量,为此单独写一篇博文讲解电量计量的设计方案和实现原理。

电量计量选用上海贝岭的BL0942芯片,最主要有原因是:硬件方案设计简单、计量精度不错且免校准、价格便宜以及软件驱动方法简单。

1、芯片功能

BL0942 能够测量电流、电压有效值、有功功率、有功电能量等参数,可输出快速电流有效值(用于过流保护),以及波形输出等功能,外围元件满足一定条件下可以免校准,当然BL0942 也是支持校准的。

芯片特性如下:

  • 两路独立的 Sigma-Delta ADC,一路电流和一路电压。 
  • 电流有效值范围(10mA~30A)@1mohm。
  • 有功电能(1w~6600w)@1mohm@220V 。
  • 可输出电流、电压有效值,快速电流有效值,有功功率。 
  • 批次出厂增益误差小于 1%,外围元件满足一定条件下可以免校准。 
  • 电流通道具备过流监控功能,监控阈值及响应时间可设置。 
  • 电压/电流过零信号输出。 
  • 内置波形寄存器,可输出波形数据用于负载类型分析。 
  • SPI(最快速率支持 900KHz)/UART(4800-38400bps)通信方式(TSSOP14L 封装支持最多 4 片级联 UART通信)。 
  • 电源掉电监测,低于 2.7V 时,芯片进入复位状态。 
  • 内置 1.218V 参考电压源 。
  • 内置振荡电路,时钟约 4MHz 。
  • 芯片单工作电源 3.3V,低功耗 10mW(典型值) 。
  • SSOP10L/TSSOP14L 封装。

本项目选用SSOP10L封装,UART驱动。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

2、性能指标

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

3、寄存器说明

本项目通过UART总线读取或设置BL0942芯片寄存器,寄存器说明如下图所示:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

4、UART通信协议

BL0942芯片UART通信特性如下:

  • 通过管脚 SEL 选择,与SPI 复用,UART模式SEL=0。
  • 芯片工作在从模式。
  • 半双工通讯,波特率可软硬件配置为 4800bps,9600bps,19200bps,38400bps。
  • 8-bit 数据传输,无校验位,停止位 1 。
  • 支持数据包读取。

TSSOP14L 封装可支持器件片选功能,硬件片选地址管脚为[A2_NCS,A1],可选器件 0~3。可支持 4 片 BL0942 挂在 UART 总线上进行数据通信,只占用 MCU 的一个 UART 接口。

在UART通信模式下,先发送 8bit 识别字节(0x58) 或(0xA8),(0x58)是读操作识别字节,(0xA8)是写操作识别字节,然后再发送寄存器地址字节,决定访问寄存器的地址(请参见 BL0942 寄存器列表),一帧数据传送完成,BL0942 重新进入通信模式。

4.1、写操作帧格式和时序

帧结构有两种,写操作帧和读操作帧。

写操作帧格式如下所示:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

主机UART 写数据时序如下图所示,主机先发送命令字节{1,0,1,0,1,0,A2,A1},然后发送需要写入数据的寄存器字节(ADDR),接下来依次发送数据字节(低字节在前,高字节在后,数据有效字节不足 3 字节的,无效位补 0),最后校验和字节。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

{1,0,1,0,1,0,A2,A1}为写操作的帧识别字节。假设{A2,A1}=10,器件地址 2,帧识别字节为0xAA。 

ADDR 为写操作对应的 BL0942 的内部寄存器地址。 

CHECKSUM 字节为({1,0,1,0,1,0,A2,A1}+ADDR+DATA[7:0]+DATA[15:8]+DATA[23:16])&0xFF 取反。

4.2、读操作帧格式和时序

读操作帧格式如下所示:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

主机UART 读数据时序如下图所示,主机先发送命令字节{0,1,0,1,1,0,A2,A1},然后发送需要读取的寄存器地址字节(ADDR),接下来 BL0942 依次发送数据字节(低字节在前,高字节在后,数据有效字节不足 3 字节的,无效位补 0),最后校验和字节。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

{0,1,0,1,1,0,A2,A1}为读操作的帧识别字节,假设{A2,A1}=10,器件地址 2,帧识别字节为0x5A。 

ADDR 为读操作对应的 BL0942 的内部寄存器地址。 

CHECKSUM 字节为({0,1,0,1,1,0,A2,A1}+ADDR+DATA[7:0]+DATA[15:8]+DATA[23:16])&0xFF 取反。 

注意:SSOP10L 封装的器件地址是 0,即{A2,A1}=00。

时序要求如下图所示:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

4.3、读取全电参数数据包

本项目读取BL0942电能计量参数,就是读取全电参数数据包。

通过命令“{0,1,0,1,1,0,A2,A1}+ 0xAA”,BL0942 会返回一个全电参数数据包。返回的数据包共 22 个字节,当使用 4800bps 时,用时约 48ms。 

全电参数包格式如下:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

checksum=(({0,1,0,1,1,0,A2,A1} + 0x55 + data1_l + data1_m + data1_h +…….)& 0xff)再按位取反。

4.4、配置波特率

使用模式寄存器 UART_RATE_SEL(MODE[9:8])和管脚 SCLK_BPS 可以配置波特率。 芯片每次上电时 RATE_SEL 复位值为 0x0,此时根据管脚 SCLK_BPS 确定波特率。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

4.5、UART保护机制

BL0942芯片内置了一些保护机制,如下所示:

  • 帧超时复位,如果字节与字节之间的间隔时间超过 20ms,UART 接口复位。 
  • 手动复位,UART 连续收到超过 32 个“0”,UART 接口复位。 
  • 帧识别字节或者 checksum 字节错误,则该帧数据放弃。 
  • UART 模式多片通信时,每发送一帧等待一个帧超时时间后或者发送一个手动复位后才能发送下一帧。 

5、功能说明

BL0942 主要分为模拟信号处理和数字信号处理两块,模拟部分主要包括两通道 PGA、两通道Sigma-Delta ADC、内置时钟(internal clock)、上下电监测(Power on/reset)、LDO 等相关模拟模块,数字部分为数字信号处理模块(DSP)。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

5.1、电流电压瞬态波形计量

电流和电压分别通过模拟模块放大器(PGA)和高精度的模数转换(ADC)得到两路1bit PDM 给数字模块,数字模块经过降采样滤波器(SINC3)、高通滤波器(HPF)、通道偏置校正等模块,得到需要的电流波形数据和电压波形数据(I_WAVE,V_WAVE)。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

采集到的负载电流和电压波形数据以 7.8k 的速率更新,每个采样数据为 20bit 有符号数,并分别存入波形寄存器(I_WAVE,V_WAVE),SPI 速率配置大于 375Kbps,可连续读取一个通道的波形值。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

注:寄存器为 24bit,不足位数,高位补零。 

5.2、有功功率

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

有功功率计算公式:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

其中,𝐼(𝐴),𝑉(𝑉)为通道管脚输入信号的有效值(mV),φ为 I(A)、V(V)交流信号的相位夹角,Vref 为内置基准电压,典型值为 1.218V。

该寄存器表示当前有功功率是正功还是负功,Bit[23]为符号位,Bit[23]=0,当前功率为正功,Bit[23]=1,当前功率为负功,补码形式。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

5.3、有功功率防潜动

BL0942 具有专利功率防潜功能,保证无电流输入的时候板级噪声功率不会累积电量。 

有功防潜动阈值寄存器(WA_CREEP),为 8bit 无符号数,缺省为 0BH。该值与有功功率寄存器值对应关系见下面公式,当输入有功功率信号绝对值小于这个值时,输出有功功率设为 0。这可以使在无负载情况下,即使有小的噪声信号,输出到有功功率寄存器中的值为 0,电能不累积。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

可以根据功率寄存器 WATT 的值设置 WA_CREEP,它们的对应关系如下:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

注:当前通道处于防潜状态时,该通道的电流有效值不测量,也切除到 0。

5.4、电能计量 

BL0942 提供电能脉冲计量,有功瞬时功率按时间进行积分,可获得有功能量,并可进一步输出校验脉冲 CF。CF_CNT 寄存器保存输出电能脉冲 CF 的个数,具体如下图所示:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

可直接从有功电能脉冲计数寄存器 CF_CNT 读取用电量,也可通过配置 OT_FUNX 寄存器后,由 I/O 中断从 CF1/CF2/ZX 引脚直接对脉冲个数进行计数,CF 的周期小于 160ms 时,为 50%占空比的脉冲,大于等于 160ms 时,高电平固定脉宽 80ms。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

CF_EN 为能量脉冲输出总开关,关闭后,CF_CNT 停止计数,CF1/CF2/ZX 引脚停止输出电能脉冲计数。 

可通过 CF_CNT_CLR_SEL 寄存器,选择 CF 计数寄存器(CF_CNT)读后是否清零。可通过CF_CNT_ADD_SEL 对脉冲能量累加模式进行选择。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

注:CF_CNT 寄存器默认电能脉冲绝对值累积方式。 

每个 CF 脉冲的累积时间如下所示:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

其中WATT 为对应的有功功率寄存器值(WATT)。

5.5、电流电压有效值

电流和电压通道的有效值如下图所示,经过平方电路(X 2)、低通滤波器(LPF_RMS)、开根电路(ROOT),得到有效值的瞬时值 RMS_t,再经过平均得到两个通道的平均值(I_RMS 和 V_RMS)。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

设置 MODE[3].RMS_UPDAT_SEL,可选择有效值平均刷新时间是 400ms 或 800ms,默认 400ms。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

当通道处于防潜状态时,该电流通道的有效值为零。 

电流有效值转换公式:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

电压有效值转换公式:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

𝑉𝑟𝑒𝑓是参考电压,典型值是 1.218V。 

注:I(A)是 IP,IN 管脚间的输入信号(mV),V(V)是 VP 管脚的输入信号(mV)。

5.6、过流检测

BL0942 可快速采集电流有效值实现过流检测功能。I_WAVE_F 取绝对值后进行半周波或周波时间累加,存于 I_FAST_RMS 寄存器,与电流快速有效值阈值寄存器 I_FAST_RMS_TH 进行比较后通过引脚输出过流中断。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

通过 I_FAST_RMS_TH 快速有效值阈值寄存器,设定快速有效值阈值(即过流阈值)。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

取 I_FAST_RMS 寄存器的 Bit[23:8]与过流阀值 I_FAST_RMS_TH [15:0]比较,若大于等于设置的阀值,则过流报警输出指示管脚 CF1/CF2/ZX 输出高电平。CF1/CF2/ZX 由 OT_FUNX 输出配置寄存器进行设置。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

通过 I_FAST_RMS_CYC 快速有效值刷新周期寄存器,设定快速有效值刷新周期。其中周波根据MODE[5]的设置值可选 50H 或者 60Hz。如选择 50hz,默认 1 周波即 20ms 刷新一次。如选择最快的 0.5周波累加时,I_FAST_RMS 寄存器的误差会相对较大。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

需要注意,快速有效值和有效值的算法不一样。快速有效值仅用于大信号时的测量判断。在小信号时快速有效值的测量会由于包含直流偏置成分不准确。如果需要去除直流偏置成分,设置FAST_RMS_SEL(MODE[4])=1,I_WAVE_F 选择 HPF 后的波形。 

通过 MODE[5]设置交流电频率。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

5.7、过零检测

BL0942 提供电压和电流过零检测,可由引脚 CF1/CF2/ZX 输出过零信号,管脚输出零表示波形正半周,管脚输出 1 表示波形负半周。与实际输入信号的时延 570us 。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

通过 OT_ FUNX 对输出管脚进行配置(SSOP10L 封装只有 CF1)。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

若电压或电流有效值过低,过零检测输出信号不稳定。 

当电压有效值V_RMS高5bit等于0时,V_ZX_LTH_F为1,表示电压有效值过低,小于满量程的1/32,电压过零指示关闭,保持为 0。 

当电流有效值 I_RMS 高 6bit 等于 0 时,I_ZX_LTH_F 为 1,表示电流有效值过低,小于满量程的 1/64,电流过零指示关闭,保持为 0。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

5.8、线电压频率检测

BL0942 具有线电压频率检测功能,每个若干设定的周期(FREQ_CYC)刷新一次,所检测的是全波电压波形。 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

线电压测量的分辨率为 2us/LSB(500KHz 时钟),相当于 50Hz 线路频率时的 0.01%或 60Hz 线路频率时的 0.012%。线电压寄存器(FREQ)与实际线电压频率的折算关系: 

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

其中默认模式下 fs=500KHz;对于 50Hz 的市电网络,测得 FREQ 的值为 20000(十进制),对于 60Hz 的市电网络,测得 FREQ 的值为 16667(十进制)。 

另外,电压有效值低于过零判断阈值时,线电压频率检测关闭。

6、应用电路

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

7、驱动程序

使用Arduino IDE驱动ESP8266周期读取全电参数数据包,源文件如下所示:

/******************************************************************************
 *
 * File Name : bl0942.cpp
 *
 * Functional Description:
 * bl0942驱动库文件
 *
 * Change Logs:
 * Date         Author         Notes        explain
 * 2022-12-6    yangjunjie      V1.0         
 *
*******************************************************************************/

/******************************************************************************
 * Include files
 ******************************************************************************/
#include "bl0942.h"

/******************************************************************************
 * Global variable definitions
 ******************************************************************************/
static char serial_data[SERIAL_RX_MAXLEN];

// 串口接收数据队列句柄 
extern struct tk_queue serial_receive_dataqueue;

// 此参数尚未使用,可用作二次校准设备
static float adjust_volrate = 1;
static float adjust_currentrate = 1;
static float adjust_powerrate = 1;

/******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/
static void sendCommand(void);
static status_t receiveData(void);

/******************************************************************************
 * function realize
 ******************************************************************************/

 /**
 ******************************************************************************
 ** \brief  初始化BL0942芯片
 **
 ** \param  无
 **
 ** \retval 无
 **
 ******************************************************************************/
void Init_BL0942(void)
{
  Serial.begin(4800, SERIAL_8N1);  // 4800bps 无校验
  Serial.setTimeout(30);           // 设置串口超时时间为30ms

  memset(serial_data, 0, SERIAL_RX_MAXLEN);  
}

 /**
 ******************************************************************************
 ** \brief  每秒钟刷新一次,依次读(电压或者电流,和功率)
 **
 ** \param  无
 **
 ** \retval 无
 **
 ******************************************************************************/
void Updata_BL0942(void)
{
  sendCommand();  // 发送指令
  receiveData();  // 处理串口接收数据
}

 /**
 ******************************************************************************
 ** \brief  串口发送指令获取电参数据
 **
 ** \param  无
 **
 ** \retval 无
 **
 ******************************************************************************/
static void sendCommand(void)
{
    Serial.write((byte)0X58);
    Serial.write((byte)0XAA);
}

 /**
 ******************************************************************************
 ** \brief  接收并解析串口接收到的电参指令
 **
 ** \param  无
 **
 ** \retval STATUS_SUCCESS:数据校验成功 STATUS_ERROR:数据校验失败
 **
 ******************************************************************************/
static status_t receiveData(void)
{
	status_t ret = STATUS_SUCCESS;
	bool temp_flag = false, receive_flag = false;
	char temp_data = 0X00;
	uint8_t data_index = 0X00;
	uint8_t checksum = 0X58;
	char temp_serial_data[SERIAL_RX_MAXLEN];
   
	while(Serial.available()) 
	{
		temp_data = (char)Serial.read();

		if(temp_data == 0X55)  // 判断帧头
		{
			temp_flag = true;
		}

		if(temp_flag == true)
		{
		  temp_serial_data[data_index++] = temp_data;
		}

		if (data_index >= SERIAL_RX_MAXLEN)
		{
		  // tk_queue_push_multi(&serial_receive_dataqueue, temp_serial_data, SERIAL_RX_MAXLEN);  // 装数据长度到缓存
		  
		  data_index = 0;
		  temp_flag = false;
		  receive_flag = true;
		  // memset(temp_serial_data, 0, SERIAL_RX_MAXLEN);  
		}
		else
		{
			receive_flag = false;
		}
	}

	// 未用到中断接收,缓存模式暂时用不到,此功能保留
	// if(tk_queue_empty(&serial_receive_dataqueue) == false)  // 缓存有数据
	// {
		// tk_queue_pop_multi(&serial_receive_dataqueue, temp_serial_data, SERIAL_RX_MAXLEN);  // 从缓存区获取数据
	
	if(receive_flag == true)
	{
		for(uint8_t i = 0; i < SERIAL_RX_MAXLEN - 1; i++)  // 校验数据
		{
			checksum += temp_serial_data[i];
		}
		
		checksum = ~(checksum & 0XFF);
		
		if(checksum == temp_serial_data[SERIAL_RX_MAXLEN - 1])
		{
			memcpy(serial_data, temp_serial_data, SERIAL_RX_MAXLEN);

			Log.verboseln("serial receive OK");
		}
		else
		{
			Log.errorln("serial receive ERROR");

			ret = STATUS_ERROR;
		}
	}

    return ret;
}

 /**
 ******************************************************************************
 ** \brief  获取电流
 **
 ** \param  无
 **
 ** \retval 电流数据
 **
 ******************************************************************************/
float getCurrent(void)
{
    uint32_t parm = 0;
	  float current = 0.0;
	
    parm = ((uint32_t)serial_data[3] << 16) + ((uint32_t)serial_data[2] << 8) + serial_data[1];
    current = (float)parm * V_REF * adjust_currentrate * 1000 / (305978 * RL_CURRENT);  // mA

    return current;
}

 /**
 ******************************************************************************
 ** \brief  获取电压
 **
 ** \param  无
 **
 ** \retval 电压数据
 **
 ******************************************************************************/
float getVoltage(void)
{
    uint32_t parm = 0;
	  float voltage = 0.0;
	
    parm = ((uint32_t)serial_data[6] << 16) + ((uint32_t)serial_data[5] << 8) + serial_data[4];
    voltage = (float)parm * V_REF * (R2_VOLTAGE + R1_VOLTAGE) * adjust_volrate / (73989 * R1_VOLTAGE * 1000);

    return voltage;
}

 /**
 ******************************************************************************
 ** \brief  过流检测,快速采集电流有效值实现过流检测功能
 **
 ** \param  无
 **
 ** \retval 电流快速有效值数据
 **
 ******************************************************************************/
float getFastCurrent(void)
{
    uint32_t parm = 0;
    parm = ((uint32_t)serial_data[9] << 16) + ((uint32_t)serial_data[8] << 8) + serial_data[7];
    float fcurrent = (float)parm * V_REF * adjust_currentrate * 1000 / (305978 * RL_CURRENT); // mA

    return fcurrent;
}

 /**
 ******************************************************************************
 ** \brief  获取有功功率
 **
 ** \param  无
 **
 ** \retval 有功功率数据
 **
 ******************************************************************************/
float getActivePower(void)
{
    uint32_t parm = 0;
	  float power = 0.0;
	
    parm = ((uint32_t)serial_data[12] << 16) + ((uint32_t)serial_data[11] << 8) + serial_data[10];

    if (1 == bitRead(serial_data[12], 7))
    {
        parm = 0xFFFFFF - parm + 1;  // 取补码
    }
	
    power = (float)parm * adjust_powerrate * V_REF * V_REF * (R2_VOLTAGE + R1_VOLTAGE) / (3537 * RL_CURRENT * R1_VOLTAGE * 1000);

    return power;
}

 /**
 ******************************************************************************
 ** \brief  获取用电量
 **
 ** \param  无
 **
 ** \retval 用电量数据
 **
 ******************************************************************************/
float getEnergy(void)
{
    uint32_t parm = 0;
	  float energy = 0.0;
	
    parm = ((uint32_t)serial_data[15] << 16) + ((uint32_t)serial_data[14] << 8) + serial_data[13];
    energy = (float)parm * 1638.4 * 256 * V_REF * V_REF * (R2_VOLTAGE + R1_VOLTAGE) / (3600000.0 * 3537 * RL_CURRENT * R1_VOLTAGE * 1000);

    return energy;
}

 /**
 ******************************************************************************
 ** \brief  线电压频率检测功能
 **
 ** \param  无
 **
 ** \retval 线电压频率数据
 **
 ******************************************************************************/
float getFREQ(void)
{
    uint32_t parm = 0;
	  float FREQ = 0.0;
	
    parm = ((uint32_t)serial_data[18] << 16) + ((uint32_t)serial_data[17] << 8) + serial_data[16];
    
    if (parm > 0)
    {
        FREQ = 500 * 1000 * 2 / (float)parm;
    }

    return FREQ;
}

 /**
 ******************************************************************************
 ** \brief  工作状态
 **
 ** \param  无
 **
 ** \retval 工作状态数据
 **
 ******************************************************************************/
uint8_t getSTATUS(void)
{
    return (uint8_t)serial_data[19];
}

/******************************************************************************/
/* EOF (not truncated)                                                        */
/******************************************************************************/

头文件如下所示:

/******************************************************************************
 *
 * File Name : bl0942.h
 *
 * Functional Description:
 * bl0942驱动库文件
 *
 * Change Logs:
 * Date         Author         Notes        explain
 * 2022-12-6    yangjunjie      V1.0         
 *
*******************************************************************************/

#ifndef __BL0942_H__
#define __BL0942_H__

/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include <Arduino.h>
#include "tk_queue.h"

/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
 
//@{

/******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
#define V_REF 1.218
#define RL_CURRENT 1     // 0.001欧,单位为毫欧
#define R2_VOLTAGE 1950  // 390K*5,单位为K欧
#define R1_VOLTAGE 0.51  // 0.51K,单位为K欧

#define SERIAL_RX_MAXLEN 23

/******************************************************************************
 ** Local type definitions ('typedef')
 ******************************************************************************/

/******************************************************************************
 * Global variable definitions ('extern')
 ******************************************************************************/
// 判断队列是否为空 
extern bool tk_queue_empty(struct tk_queue *queue);

// 向队列压入(入队)多个元素数据
extern uint16_t tk_queue_push_multi(struct tk_queue *queue, char *pval, uint16_t len);

// 从队列弹出(出队)多个元素数据
extern uint16_t tk_queue_pop_multi(struct tk_queue *queue, char *pval, uint16_t len);

/*****************************************************************************
 * Function definitions - global ('extern') and local ('static')
 ******************************************************************************/
// 初始化BL0942芯片
void Init_BL0942(void);

// 每秒钟刷新一次,依次读(电压或者电流,和功率)
void Updata_BL0942(void);

// 获取电流
float getCurrent(void);

// 获取电压
float getVoltage(void);

// 过流检测,快速采集电流有效值实现过流检测功能
float getFastCurrent(void);

// 获取有功功率
float getActivePower(void);

// 获取用电量
float getEnergy(void);

// 线电压频率检测功能
float getFREQ(void);

// 工作状态
uint8_t getSTATUS(void);

//@}
#ifdef __cplusplus
}
#endif

#endif /* __BL0942_H__ */

/******************************************************************************/
/* EOF (not truncated)                                                        */
/******************************************************************************/

8、替代方案

上海贝岭也提供了需要校准的电量计量芯片:BL0937。

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

BL0937 在定义产品时考虑到智能插座类产品厂家不是专业计量器具厂家,没有专业昂贵的校准设备,对电能计量精度要求也相对较低,只是提供用电参考信息,不作计费标准。智能插座只需要读取功率,电压,电流,并根据功率计量累积电量,所以BL0937 与 MCU 间不要复杂的通讯协议去实时的读取计量芯片寄存器,计量精度校准也相对简单,只需在额定功率负载时校准系数,也不需要复杂的校准设备。 

BL0937方案的应用电路如下所示,经过实际测试稳定可靠:

ESP8266 WiFi物联网智能插座—电能计量,ESP8266 WiFi物联网智能插座,物联网,WiFi智能插座,电能计量,BL0942,原力计划

感兴趣的朋友可以研究一下这个方案,由于不是本项目所使用的方案,不再赘述。文章来源地址https://www.toymoban.com/news/detail-740096.html

到了这里,关于ESP8266 WiFi物联网智能插座—电能计量的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 物联网智能网关(ESP8266WIFI模块)

    一、温湿度和光敏数据采集。要求:采集ESP8266平台中温湿度传感器与光敏电阻的数据并传输至网页端显示。 (1)分别对应温湿度传感器及光敏传感器的功能绘制或展示硬件连接原理图并简单说明。   光敏电路:光敏电路,实现感光效果   温湿度(DHT11)电路:测量温湿度

    2023年04月22日
    浏览(51)
  • 【ESP32】BL0942功耗传感器SPI接口驱动

    BL0942功耗模块在物联网设备中的应用比较广泛,本博文完成ESP32基于SPI接口驱动功耗BL0942模块(上海贝岭公司)的寄存器的读写,从而可以完成寄存器模式的配置,以及读取寄存器的值完成电流电压,功率等值的计算。 在通信模式下,先发送 8bit 识别字节(0x58) 或(0xA8), (0x5

    2024年02月14日
    浏览(54)
  • STM32--ESP8266物联网WIFI模块(贝壳物联)--远程无线控制点灯

    本文适用于STM32F103C8T6等MCU,其他MCU可以移植,完整资源见文末链接 一、简介 随着移动物联网的发展,各场景下对于物联控制、数据上传、远程控制的诉求也越来越多,基于此乐鑫科技推出了便宜好用性价比极高的wifi物联模块——ESP8266,话不多少我们先来看看这个神奇的模

    2024年02月08日
    浏览(60)
  • STM32玩转物联网实战篇:2.ESP8266 WIFI模块TCP通信示例详解

    开发板功能区分布图 开发板俯视图     ESP8266 WIFI模块内置TCP/IP网络协议,模块支持三种网络模式,AP、STA和AP+STA模式,AP模式:模块作为WIFI热点,等待其他设备的连接,进行局域网的通信,STA模式:模块作为客户端通过路由器连接外网,和服务器进行通信,AP+STA模式:两

    2024年02月03日
    浏览(57)
  • STM32--ESP8266物联网WIFI模块(贝壳物联)--温湿度数据上传服务器显示

    本文适用于STM32F103C8T6等MCU,其他MCU可以移植,完整资源见文末链接 一、简介 随着移动物联网的发展,各场景下对于物联控制、数据上传、远程控制的诉求也越来越多,基于此乐鑫科技推出了便宜好用性价比极高的wifi物联模块——ESP8266,话不多少我们先来看看这个神奇的模

    2024年02月08日
    浏览(49)
  • 【雕爷学编程】Arduino智能家居之使用ESP8266WiFi库和DHTesp库

    Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来

    2024年01月18日
    浏览(50)
  • STM32 ESP8266 物联网智能温室大棚 (附源码 PCB 原理图 设计文档)_stm32 esp8266 onenet 温室

    系统启动后,单片机控制相关传感器进行环境参数的采集,将数据传回单片机处理后,通过OLED显示屏将相关环境指数实时显示。用户可以在手机端打开APP与本系统进行通信,更加便捷地查看监测数据。结构框图如下所示。 硬件部分包含主控芯片、传感器模块,OLED模块,WIF

    2024年04月23日
    浏览(49)
  • 嵌入式项目分享 单片机(stm32)远程智能宠物喂养系统 - 物联网 esp8266

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月21日
    浏览(141)
  • 单片机项目分享 单片机(stm32)远程智能宠物喂养系统 - 物联网 esp8266

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月19日
    浏览(64)
  • stm32——esp8266物联网开发,连接onenet云平台(http)做智能家居(1)

    此处感谢b站up主——彼岸有光我们有船(我认为讲的和江科大老师一样好,如果习惯江科大老师的讲法的朋友们都可以看看捏) 提供的教程和最初的正点原子的源码,因为我学习的是江科大的stm32,所以进行了部分改编和部分注释,在此把视频内容简化,进行简单的复习。

    2023年04月08日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包