完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
ESP8266+BL0937电能计量芯片
1. BL0937计量芯片的介绍 BL0937的应用威廉希尔官方网站 图 BL0937的外围威廉希尔官方网站 图 2. ESP8266与BL0937芯片的引脚连接 [tr]ESP引脚BL0937引脚[/tr]GPIO3SEL GPIO4CF GPIO5CF1 3. 程序设计思路 采用系统时间实现单周期测量 假设GPIO外部中断类型为下降沿触发,设下降沿数量为num=0,则测量逻辑如下所示: [tr]下降沿个数周期数[/tr]10 21 故在第一个下降沿到来和第二个下降沿到来时获取系统时间,此为单周期时间,然后清零重新计数。多个外部中断时需要注意不同外部中断的下降沿时间间隔,防止持续进入某个外部中断。 2. 采用定时器实现平均测量 定时器测量时需要注意应该采用硬件定时器,时钟源为NMI时钟源,此时钟源优先级高于外部中断,可保证定时的准确性。 4. 需要注意的问题 打开中断之后,下降沿可能不会立即触发中断,一种是加延时,具体时间要根据负载而定;一种方法是执行while循环,判断计时时间是否到达。总的来说,整个过程对于周期的测量并不准确,误差在2以内。 5. 功率电能完整代码 #include “user_main.h” #include “osapi.h”#include “os_type.h” #include “driver/uart.h” #include “user_interface.h” #include “spi_flash.h” #include “espconn.h” #include “user_config.h” #include “hal_key.h” #include “tosee_common.h” #include “tosee_led.h” #include “config.h” #include “power.h” #include “test.h” #include “ets_sys.h” #include “ip_addr.h” #include “mem.h” #include “user_main.h” #include “hw_timer.h”int num1; //功率脉冲int num2; //电能脉冲float Fcf; //功率float P; //W,kWHfloat W; //定义电压电流转换系数int Kp = 15; int Kw = 10; int flag=0; int flag1=0; void ICACHE_FLASH_ATTR bl_interrupt() { unsigned int gpio_status = 0; gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); //获取中断状态 ETS_GPIO_INTR_DISABLE(); //关中断 //GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); //清中断标志位 if(gpio_status & BIT(4)) { num1=num1+1; //PW 脉冲个数 num2=num2+1; } GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); if(flag==0) { ETS_GPIO_INTR_ENABLE(); } else{ ETS_GPIO_INTR_DISABLE(); } } void ICACHE_FLASH_ATTR PW_handler() { if (Fcf 《 6780) { P = Fcf * Kp; //W W = num2 * Kw; //kWh flag1=1; } else { P = 0; //P=0标志过流 W = num2 * Kw; //kWh flag1=1; } } void hw_test_timer_cb(void) { flag=1; } void ICACHE_FLASH_ATTR hz_handler() { Fcf=num1/5.0; //Hz}void ICACHE_FLASH_ATTR pw_init() { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); GPIO_DIS_OUTPUT(4); //GPIO4和GPIO5使能上拉 PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO4_U); //GPIO4中断配置 ETS_GPIO_INTR_DISABLE(); ETS_GPIO_INTR_ATTACH(&bl_interrupt, NULL); gpio_pin_intr_state_set(GPIO_ID_PIN(4), GPIO_PIN_INTR_NEGEDGE); //硬件定时器 hw_timer_init(1,0); hw_timer_set_func(hw_test_timer_cb); hw_timer_arm(2000000); //us,2s ETS_GPIO_INTR_ENABLE(); //开中断 while(1) { if(flag==1) { ETS_GPIO_INTR_DISABLE(); hz_handler(); PW_handler(); os_printf(“P=%d,W=%d,num1=%d,num2=%d------n”,P,W,num1,num2); if(flag1==1){num1=0; } } } } 7.电压电流测量完整代码 #include “ets_sys.h” #include “osapi.h” #include “ip_addr.h” #include “espconn.h” #include “mem.h” #include “user_interface.h” #include “smartconfig.h” #include “airkiss.h” #include “driver/uart.h” #include “hw_timer.h”int num0 = 0; //电流电压脉冲float Fcf1 = 0; //电流电压Hzint U=0;int I=0; //V,mA//定义电压电流转换系数int Ku = 220; float Ki = 0.18; int flag=0; int flag1=0; /* * 脉冲中断计数函数 */ void ICACHE_FLASH_ATTR bl_interrupt() { unsigned int gpio_status = 0; gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); //获取中断状态 ETS_GPIO_INTR_DISABLE(); //关中断 //GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); //清中断标志位 if(gpio_status & BIT(5)) { num0 = num0 + 1; } GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); if(flag==0) { ETS_GPIO_INTR_ENABLE(); } else { ETS_GPIO_INTR_DISABLE(); } } void ICACHE_FLASH_ATTR bl_select() { if(GPIO_ID_PIN(3)==0) { I = Fcf1 * Ki; //mA GPIO_OUTPUT_SET(GPIO_ID_PIN(3), 1); } else { GPIO_OUTPUT_SET(GPIO_ID_PIN(3), 0); U = Fcf1 * Ku; //mA } flag1=1;} void hw_test_timer_cb(void) { flag=1; } void ICACHE_FLASH_ATTR hz_handler() { Fcf1=num0/1.0; //Hz} void ICACHE_FLASH_ATTR Time_UI_init() { PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5); GPIO_DIS_OUTPUT(5); GPIO_OUTPUT_SET(GPIO_ID_PIN(3), 0); //GPIO3=0 //GPIO4和GPIO5使能上拉 PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO5_U); //GPIO5中断配置 ETS_GPIO_INTR_DISABLE(); ETS_GPIO_INTR_ATTACH(&bl_interrupt, NULL); gpio_pin_intr_state_set(GPIO_ID_PIN(5), GPIO_PIN_INTR_NEGEDGE); //硬件定时器 hw_timer_init(1,0); hw_timer_set_func(hw_test_timer_cb); hw_timer_arm(2000000); //us,2s ETS_GPIO_INTR_ENABLE(); //开中断 while(1) { if(flag==1) { ETS_GPIO_INTR_DISABLE(); hz_handler(); bl_select(); if(flag1==1){num0=0; } } } } 8. 需要解决的问题 计算问题 ESP8266的基础计算没有了解过,但是在整个程序中发现计算有误。(1)中断执行函数中{num1=num1+1; num2=num2+1;},这两句程序只会执行第一个,不明白什么原因;(2)主程序中最后判断是否对num1清零。这条程序会先于hz_handler()和PW_handler()函数执行。虽然执行条件未达到。这个也不明白;(3)貌似ESP8266会优先执行赋值语句;同一个函数下两条计算语句会只执行第一条。 参数类型问题 默认P=x.x(W),W=x.xx(kWh)。那么设置计算函数的时候要注意各个参数的类型。 |
|
|
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-14 16:09 , Processed in 0.512213 second(s), Total 43, Slave 37 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号