电流
直播中

乐骞添

7年用户 933经验值
私信 关注
[问答]

怎样去设计一种ESP8266+BL0937电能计量芯片电路

怎样去设计一种ESP8266+BL0937电能计量芯片电路?在设计过程中需要注意哪些问题?

回帖(1)

杨涛

2021-9-9 18:20:02
  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)。那么设置计算函数的时候要注意各个参数的类型。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分