『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 2165|回复: 22

[经验分享] 终于跟着教程装上了培正电表!交作业了!

[复制链接]

5

主题

79

帖子

876

积分

高级会员

Rank: 4

积分
876
金钱
797
HASS币
0
发表于 2024-7-21 22:04:47 | 显示全部楼层 |阅读模式
一直苦于国网的不稳定性,又想对家里电量电费进行一个统计,于是终于在上个月跟着论坛教程装上了培正!
装了之后问题又来了,由于湖南电价方案与论坛之前的都不一样,没有峰谷的阶梯电价,而且只是根据春夏季节简单地调整了阶梯,所以要对esphome代码进行调整!
参考了jjcs和hzcoolwind两位前辈的方案,感谢两位大佬的付出!
【终极版】培正Esphome电量统计,谷峰计算,阶梯电价
https://bbs.hassbian.com/thread-24441-1-1.html
带实时年度阶梯电价和峰谷电统计的培正ESPHOME

https://bbs.hassbian.com/thread-24535-1-1.html

同时借助chatgpt,对论坛之前的代码进行了一些微调,最终形成了湖南电价版本!
由于湖南电价阶梯是按月电量计算的,所以在原来基础上增加了月度电量重置,同时增加了年度电费和月度电费重置,以便中途修正数据!
Snipaste_2024-07-21_22-03-59.jpg
目前用下来发现电量与国网数据差0.2~0.3的样子,感觉还可以!
但是也存在一个问题,就是每隔一段时间设备会变成不再可用,然后又自动恢复,由于没有影响到统计我也就没管它了,希望有知道的大佬指点一下应该怎么调整,感谢!
substitutions:
  name: power_meter
  friendly_name: Power Meter

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  name_add_mac_suffix: false
  project:
    name: hzcoolwind.power-meter
    version: "1.1.0"

esp32:
  board: esp32dev
  framework:
    type: esp-idf

api:

ota:
  password: "12345678"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Bluetoothproxy Fallback Hotspot"
    password: !secret ap_password

web_server:
  port: 80
  
logger:

improv_serial:

uart:
  - id: main_uart
    rx_pin: 
      number: GPIO16
      inverted: false
      mode:
        input: true
        pullup: true
    tx_pin: 
      number: GPIO17
      inverted: false
      mode:
        output: true
    baud_rate: 9600
    debug:
      direction: BOTH

modbus:
  - id: mod_bus_pzemac
    send_wait_time: 5ms
    uart_id: main_uart
   
button:
  - platform: template
    name: Meter Reset
    id: reset_button
    icon: "mdi:emoticon-outline"
    on_press:
      - pzemac.reset_energy: pzemac_main

  - platform: template
    name: Reset Memory
    id: reset_memory
    entity_category: diagnostic
    on_press:
      - lambda: |-
            id(global_today_usage) = 0.000f;
            id(global_today_bill) = 0.000f;
            id(global_yesterday_usage) = 0.000f;
            id(global_yesterday_bill) = 0.000f;
            id(global_month_usage) = 0.000f;
            id(global_month_bill) = 0.000f;
            id(global_annual_usage) = 0.000f;
            id(global_annual_bill) = 0.000f;
            id(global_yesterday_energy) = 0.000f;
            
  - platform: safe_mode
    name: Safe Mode Boot
    entity_category: diagnostic

  - platform: restart
    name: Restart
    entity_category: diagnostic


globals:
  # flash保存昨日抄表数(每天0点更新保存)
  - id: global_yesterday_energy
    type: float
    restore_value: yes
    initial_value: '0.000'

  # flash保存今日电量电费
  - id: global_today_usage
    type: float
    restore_value: yes
    initial_value: '0.000'
  - id: global_today_bill
    type: float
    restore_value: yes
    initial_value: '0.000'

  # flash昨日用电量电费(每天0点更新保存)
  - id: global_yesterday_usage
    type: float
    restore_value: yes
    initial_value: '0.000'
  - id: global_yesterday_bill
    type: float
    restore_value: yes
    initial_value: '0.000'

  # flash保存本月电量电费(不含当天)
  - id: global_month_usage
    type: float
    restore_value: yes
    initial_value: '0.000'
  - id: global_month_bill
    type: float
    restore_value: yes
    initial_value: '0.000'

  # flash保存年度用电量电费(不含当月)
  - id: global_annual_usage
    type: float
    restore_value: yes
    initial_value: '0.000'
  - id: global_annual_bill
    type: float
    restore_value: yes
    initial_value: '0.000'

  # flash保存上月电量电费(1号0点更新保存)
  - id: global_last_month_usage
    type: float
    restore_value: yes
    initial_value: '0.000'
  - id: global_last_month_bill
    type: float
    restore_value: yes
    initial_value: '0.000'

  # 全局变量:当前阶梯档位(0,1,2)flash不保存,计算所得 
  - id: global_step_id
    type: int
    restore_value: false
    initial_value: '0'

number:
  # 复位年度电量电费,因为国网只能查询上月以前的数据,加上表上读数为实际当年使用度数
  - platform: template
    id: set_reset_annual_usage
    name: Set Reset Annual Usage
    mode: box
    min_value: 0
    max_value: 9999
    initial_value: 0
    optimistic: true
    step: 0.01
    restore_value: false
    unit_of_measurement: kwh
    on_value:
      then:
        - lambda: |-
            id(global_annual_usage) = x;
            id(annual_usage).publish_state( id(global_annual_usage) + id(month_usage).state);
  - platform: template
    id: set_reset_annual_bill
    name: Set Reset Annual bill
    mode: box
    min_value: 0
    max_value: 9999
    initial_value: 0
    optimistic: true
    step: 0.01
    restore_value: false
    unit_of_measurement: CNY
    on_value:
      then:
        - lambda: |-
            id(global_annual_bill) = x;
            id(annual_bill).publish_state( id(global_annual_bill) + id(month_bill).state);

  # 复位当月电量电费,因为国网只能查询昨天以前的数据,加上昨天以及今天的数据才是当月当前的数据
  - platform: template
    id: set_reset_month_usage
    name: Set Reset Month Usage
    mode: box
    min_value: 0
    max_value: 9999
    initial_value: 0
    optimistic: true
    step: 0.01
    restore_value: false
    unit_of_measurement: kwh
    on_value:
      then:
        - lambda: |-
            id(global_month_usage) = x ;
            id(month_usage).publish_state( id(global_month_usage) + id(global_today_usage) );
            id(current_price).update();
  - platform: template
    id: set_reset_month_bill
    name: Set Reset Month bill
    mode: box
    min_value: 0
    max_value: 9999
    initial_value: 0
    optimistic: true
    step: 0.01
    restore_value: false
    unit_of_measurement: CNY
    on_value:
      then:
        - lambda: |-
            id(global_month_bill) = x ;
            id(month_bill).publish_state( id(global_month_bill) + id(global_today_bill) );

sensor:
  # 培正电表,每月重置
  - platform: pzemac
    id: pzemac_main
    update_interval: 10s
    address: 0x01
    modbus_id: mod_bus_pzemac
    current:
      name: "Main Current"
    voltage:
      name: "Main Voltage"
    power:
      name: "Main Power"
      id: main_power
    frequency:
      name: "Main Frequency"
    power_factor:
      name: "Main Factor"
    energy:
      name: "Main Energy"
      id: main_energy
      unit_of_measurement: kWh
      device_class: energy
      state_class: total_increasing
      accuracy_decimals: 3
      filters:
        - multiply: 0.001
 
  # 昨日抄表数
  - platform: template
    name: Yesterday Energy
    id: yesterday_energy
    accuracy_decimals: 3
    device_class: "energy"
    state_class: "total_increasing"
    icon: mdi:lightning-bolt
    unit_of_measurement: kWh
    update_interval: 15s
    lambda: 
      return id(global_yesterday_energy);

  # 今日用电量、电费
  - platform: template
    name: Today Usage 
    id: today_usage
    accuracy_decimals: 3
    device_class: "energy"
    state_class: "total_increasing"
    icon: mdi:lightning-bolt
    unit_of_measurement: kWh
    update_interval: 10s
    lambda: 
      return id(global_today_usage);
  - platform: template
    name: Today_bill
    id: today_bill
    accuracy_decimals: 3
    unit_of_measurement: CNY
    update_interval: 10s
    lambda: 
      return id(global_today_bill); 

  # 昨日用电量、电费
  - platform: template
    name: Yesterday Usage
    id: yesterday_usage
    accuracy_decimals: 3
    device_class: "energy"
    state_class: "total_increasing"
    icon: mdi:lightning-bolt
    unit_of_measurement: kWh
    update_interval: 60s
    lambda: 
      return id(global_yesterday_usage);
  - platform: template
    name: Yesterday_bill
    id: yesterday_bill
    accuracy_decimals: 3
    unit_of_measurement: CNY
    update_interval: 60s
    lambda: 
      return id(global_yesterday_bill);

  # 当月用电量、电费
  - platform: template
    name: Month Usage
    id: month_usage
    accuracy_decimals: 3
    device_class: "energy"
    state_class: "total_increasing"
    icon: mdi:lightning-bolt
    unit_of_measurement: kWh
    update_interval: 15s
    lambda: 
      return id(global_month_usage) + id(today_usage).state;
  - platform: template
    name: Month_bill
    id: month_bill
    accuracy_decimals: 3
    unit_of_measurement: CNY
    update_interval: 15s
    lambda: 
      return id(global_month_bill) + id(today_bill).state; 

  # 上月用电量、电费
  - platform: template
    name: Last Month Usage 
    id: last_month_usage
    accuracy_decimals: 3
    device_class: "energy"
    state_class: "total_increasing"
    icon: mdi:lightning-bolt
    unit_of_measurement: kWh
    update_interval: 60s
    lambda: 
      return id(global_last_month_usage);
  - platform: template
    name: Last Month bill
    id: last_month_bill
    accuracy_decimals: 3
    unit_of_measurement: CNY
    update_interval: 60s
    lambda: 
      return id(global_last_month_bill); 

  # 年度用电量、电费
  - platform: template
    name: Annual Usage
    id: annual_usage
    accuracy_decimals: 3
    device_class: "energy"
    state_class: "total_increasing"
    icon: mdi:lightning-bolt
    unit_of_measurement: kWh
    update_interval: 15s
    lambda: 
      return id(global_annual_usage) + id(month_usage).state;
  - platform: template
    name: Annual Bill
    id: annual_bill
    accuracy_decimals: 3
    unit_of_measurement: CNY
    update_interval: 15s
    lambda: 
      return id(global_annual_bill) + id(month_bill).state;
      
  # 当前电价
  - platform: template
    name: Current Price
    id: current_price
    accuracy_decimals: 3
    icon: mdi:home-lightning-bolt
    unit_of_measurement: 'CNY/kWh'
    update_interval: 10s
    lambda: |-       
      int step_id = 0;
      float current_price = 0.000f;
      float all_prices[] = {0.588, 0.638, 0.888};
      
      int total_usage = id(month_usage).state;
      
      int current_month = 1;
      current_month = parse_number<int>(id(time_sntp).now().strftime("%m")).value();
      
      if (total_usage <= 200) {
        step_id = 0;
      } else {
        if ((current_month >= 3 && current_month <= 5) || (current_month >= 9 && current_month <= 11)) {
          if (total_usage <= 350) {
            step_id = 1;
          } else {
            step_id = 2;
          }
        } else {
          if (total_usage <= 450) {
            step_id = 1;
          } else {
            step_id = 2;
          }
        }
      }

      id(global_step_id) = step_id;
      current_price = all_prices[step_id];

      return current_price;
 
  - platform: wifi_signal
    name: "WiFi Signal Sensor"
    update_interval: 60s

text_sensor:
  - platform: wifi_info
    ip_address:
      name: IP Address
      icon: "mdi:ip-network"

time:
  - platform: homeassistant
    timezone: UTC-8
    id: time_ha

  - platform: sntp
    id: time_sntp
    servers: ntp.aliyun.com 
    timezone: UTC-8

    on_time:
      # 每隔1分钟更新保存今日电量电费
      - seconds: 59
        then:
          - if:
              condition:
                time.has_time: 
              then:
                - lambda: |-
                    id(current_price).update();
                    float price = id(current_price).state;

                    id(global_today_bill) = id(global_today_bill) + (id(main_energy).state - id(global_yesterday_energy)-id(global_today_usage)) * price;
                    id(global_today_usage) = id(main_energy).state - id(global_yesterday_energy);

      # 每天0点更新保存当月电量电费、昨日电量电费以及昨日抄表数
      - seconds: 0
        minutes: 0
        hours: 0 
        then:
          - if:
              condition:
                time.has_time: 
              then:
                - lambda: |-
                    id(global_month_usage) = id(global_month_usage) + id(global_today_usage);
                    id(global_month_bill) = id(global_month_bill) + id(global_today_bill);

                    id(global_yesterday_usage) = id(global_today_usage);
                    id(global_today_usage) = 0.000f;

                    id(global_yesterday_bill) = id(global_today_bill);
                    id(global_today_bill) = 0.000f;

                    id(global_yesterday_energy) = id(main_energy).state;

      # 每月1日0点更新保存年度电量电费、上月电量电费, 并重置电表电量
      - seconds: 00
        minutes: 00
        hours: 00
        days_of_month: 1  
        then:
          - lambda: |-   
              id(global_annual_usage) = id(global_annual_usage) + id(global_month_usage);
              id(global_annual_bill) = id(global_annual_bill) + id(global_month_bill);

              id(global_last_month_usage) = id(global_month_usage); 
              id(global_month_usage) = 0.000f;
              id(global_last_month_bill) = id(global_month_bill); 
              id(global_month_bill) = 0.000f;

              id(global_yesterday_energy) = 0.000f;
          - if:
              condition:
                time.has_time: 
              then:  
                - logger.log: "-->publish last month electricity."          
                - pzemac.reset_energy: pzemac_main      
                - delay: 1s
                - pzemac.reset_energy: pzemac_main


HNpower.zip (2.82 KB, 下载次数: 15)




评分

参与人数 2金钱 +24 收起 理由
隔壁的王叔叔 + 12 论坛有你更精彩!
jjcs + 12 在下对你的景仰犹如滔滔长江之水,连绵不绝.

查看全部评分

回复

使用道具 举报

146

主题

2267

帖子

7002

积分

元老级技术达人

积分
7002
金钱
4730
HASS币
30
发表于 2024-7-21 22:32:10 | 显示全部楼层
本帖最后由 bugensui 于 2024-7-22 00:32 编辑

计算全部在flash里完成的?牛逼的, 是不是计算量太大,esp内存不够,所以,经常不可用, id(global_today_usage) = 0.000f;  这句代码是直接把今日电量设置为0对吧,为什么不直接写等于0
回复

使用道具 举报

1

主题

88

帖子

779

积分

高级会员

Rank: 4

积分
779
金钱
691
HASS币
0
发表于 2024-7-22 00:35:48 | 显示全部楼层
同湖南 这个是只能测试一路吧?
回复

使用道具 举报

46

主题

1654

帖子

6676

积分

论坛元老

Rank: 8Rank: 8

积分
6676
金钱
5012
HASS币
40
发表于 2024-7-22 02:15:23 | 显示全部楼层
bugensui 发表于 2024-7-21 22:32
计算全部在flash里完成的?牛逼的, 是不是计算量太大,esp内存不够,所以,经常不可用, id(global_today_u ...

变量和默认数据类型是0.000这样格式,所以最好统一
折腾精神永存,感恩感谢论坛每一位愿意分享和帮助过我的大佬,论坛有你更精彩
回复

使用道具 举报

46

主题

1654

帖子

6676

积分

论坛元老

Rank: 8Rank: 8

积分
6676
金钱
5012
HASS币
40
发表于 2024-7-22 02:20:20 | 显示全部楼层
bugensui 发表于 2024-7-21 22:32
计算全部在flash里完成的?牛逼的, 是不是计算量太大,esp内存不够,所以,经常不可用, id(global_today_u ...

esp32足以胜任,重启原因很复杂,想要解决,想要逐步排除分析,只能靠自己,我看代码esp32使用到是idf框架,换成adruino框架试试看
折腾精神永存,感恩感谢论坛每一位愿意分享和帮助过我的大佬,论坛有你更精彩
回复

使用道具 举报

46

主题

1654

帖子

6676

积分

论坛元老

Rank: 8Rank: 8

积分
6676
金钱
5012
HASS币
40
发表于 2024-7-22 02:22:53 | 显示全部楼层
还有楼主最好贴上自己的esphome版本号,方便其他人复现教程,最新的esphome部分写法改了
折腾精神永存,感恩感谢论坛每一位愿意分享和帮助过我的大佬,论坛有你更精彩
回复

使用道具 举报

46

主题

1654

帖子

6676

积分

论坛元老

Rank: 8Rank: 8

积分
6676
金钱
5012
HASS币
40
发表于 2024-7-22 02:25:53 | 显示全部楼层
修改的代码需要充分考虑,代码是否稳定,健壮性,
折腾精神永存,感恩感谢论坛每一位愿意分享和帮助过我的大佬,论坛有你更精彩
回复

使用道具 举报

8

主题

2073

帖子

6053

积分

论坛元老

流水无味

Rank: 8Rank: 8

积分
6053
金钱
3980
HASS币
145

灌水之王

发表于 2024-7-22 08:04:28 | 显示全部楼层
18年还是19年买的培正模块 至今未拆封
回复

使用道具 举报

40

主题

2176

帖子

8286

积分

元老级技术达人

积分
8286
金钱
6095
HASS币
110
发表于 2024-7-22 08:37:59 | 显示全部楼层
我现在用的透传模块DT06
回复

使用道具 举报

146

主题

2267

帖子

7002

积分

元老级技术达人

积分
7002
金钱
4730
HASS币
30
发表于 2024-7-22 11:50:40 | 显示全部楼层
jjcs 发表于 2024-7-22 02:20
esp32足以胜任,重启原因很复杂,想要解决,想要逐步排除分析,只能靠自己,我看代码esp32使用到是idf框 ...

那我就放心的修改代码尝试了。我已经知道思路了,这种代码存储globals,如果断电后,储存在globals会丢失不,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-23 23:14 , Processed in 0.574061 second(s), 36 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表