Skip to content

peca2345/ESPHome-electric-smoke-house

Repository files navigation

ESPHome - electric smoke house and smokebox

This is a tutorial on automating a smokehouse with a smoke generator.

Description:

Features:

  • PID thermal regulation
  • measurement of smoke, smokehouse and internal meat temperature
  • fan automation - speed control according to smoke temperature
  • vibrator automation - when the smoke drops, it vibrates with the wood chips for better combustion
  • WIFI/cloud control (via Home Assistant server) + android or google home notification
  • writing sensor data to grafana
  • wattmeter
  • LCD display
  • manual control buttons
  • fuel: wood chips

Button function:

  • TEMP UP: target temp. +1°C (long press +5°C and very long press set thermostat to 65°C)
  • TEMP DOWN: target temp. -1°C (long press -5°C and very long press set thermostat to 0°C)
  • THERMOSTAT: ON/OFF thermostat
  • LIGHT IN: ON/OFF indoor light
  • LIGHT OUT: ON/OFF outdoor light
  • AUT. VIB: ON/OFF vibrator automation (vibrates with the chip at low smoke temperature)
  • AUT. FAN: ON/OFF fan automation (speed control according to smoke temperature)
  • FAN UP: +10% speed (long press max. speed)
  • FAN DOWN: -10% speed (long press OFF)

Required knowledge:

Used components:

  • ESP12F 4CH 1pcs: ALI

  • ESB/TTL programmer: ALI

  • MCP23017 1pcs: ALI

  • SSR DIN 25A 1pcs: ALI

  • PWM driver 2pcs: ALI

  • Buttons 9pcs: ALI

  • LCD 20x4 5V 1pcs: ALI

  • AC-DC 12V 3.3A MD-40-12 DIN 1pcs: ALI

  • Switch AC 250V 16A 2pcs: ALI

  • Dallas temp. Sensor 4pcs: ALI

  • FAN 5025 12V 6200rpm 1pcs: ALI

  • Vibrator DC 1.5-6V 22400RPM 1pcs: ALI

  • Wattmeter PZEM-004T 100A 1pcs: ALI

  • Heater 2600W 230V 1pcs: ALI

  • LED diode set 1pcs: ALI

  • Resistors set 1pcs: ALI

  • LED light outdoor 20W 230V 1pcs: ALI

  • Oven light 25W 230V 1pcs: ALI

  • Oven E14 holder/socket 1pcs: ALI

  • DCIN jack panel 5.5x2.1 5pcs set: ALI

  • DCIN jack cable 5.5x2.1 5pcs set 1pcs: ALI

Schema:

Schema

Step by Step.. (prototype)

StepbyStep

LCD:

LCD

Home Assistant: (web browser)

HA

Grafana:

Grafana

Android notification:

android

Gallery:

https://photos.app.goo.gl/iQ432f7vACJFKvrUA

ESPHome code

esphome:
  name: iudirna
  platform: esp8266
  board: esp12e
  on_boot:
    then:
      - switch.turn_off: fan_auto
      - switch.turn_off: vibrator_auto
      - delay: 5s
      - climate.control:
          id: pid_climate
          mode: 'OFF'
          
logger:
  level: NONE # log must be NONE to release the wattmeter
  hardware_uart: UART1
  
api:
ota:
  password: "a025f35ef14fd7ed30fba24567e45e60"
             # USE YOUR KEY GENERATED BY ESPHOME
wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password 

########################################################### 
    
uart: 
  rx_pin: GPIO3
  tx_pin: GPIO1
  baud_rate: 9600
  # for wattmeter pzem004t (the logger must be "NONE" to release the uart)
  
i2c: # for LCD, mcp23017
  sda: GPIO4
  scl: GPIO5
  scan: false
  # if you don't know the addresses of i2c devices, enable scan (true) and read the ID from the log
  
mcp23017:
  - id: 'mcp23017_hub'
    address: 0x20 
    # adress detected from log with i2c scan enabled
    
dallas: 
  - pin: GPIO12
    update_interval: 5s
    
########################################################### LCD DISPLAY

display: 
  - platform: lcd_pcf8574
    dimensions: 20x4
    update_interval: 2s # LCD 2004A may have problem with <2s - wifi not working
    address: # detected from log with i2c scan enabled
    lambda: |-
      it.printf(0, 0, "Udirna: %.0f", id(iudirna_teplota1).state);
      it.printf(12, 0, "T=%.0f", id(pid_climate).target_temperature_low);
      it.printf(17, 0, "%s", id(pid_mode).state ? "ON" : "OFF");
      it.printf(0, 1, "Maso 1: %.0f", id(iudirna_teplota2).state);
      it.printf(11, 1, " F=%.0f", id(fan_speed).state);
      it.printf(17, 1, "%s", id(fan_auto).state ? "AUT" : "MAN");
      it.printf(0, 2, "Maso 2: %.0f", id(iudirna_teplota3).state);
      it.printf(11, 2, " V=%.0f", id(vibrator_speed).state);
      it.printf(17, 2, "%s", id(vibrator_auto).state ? "AUT" : "MAN"); 
      it.printf(0, 3, "Dymbox: %.0f", id(iudirna_teplota4).state);
      it.printf(11, 3, " H=%.0f", id(iudirna_up_time).state); 


########################################################### THERMOSTAT PID

climate: 

  # PID TERMOSTAT
  - platform: pid 
    id: pid_climate
    name: "iUdirna PID Climate Controller"
    sensor: iudirna_teplota1
    default_target_temperature: 65°C
    visual:
      min_temperature: 0
      max_temperature: 99
      temperature_step: 1
    heat_output: heater
    control_parameters:
      kp: 0.22224  
      ki: 0.00067  
      kd: 18.41252 
      # for functional autotune set kp,ki,kd: 0 
      # overwrite with log values after autotune is complete
      

sensor:
########################################################### WATTMETER

  # WATTMETER PZEM004T - UART   
  - platform: pzemac
    update_interval: 10s
    current:
      name: "iudirna_pzem_proud"
    voltage:
      name: "iudirna_pzem_napeti"
    energy:
      name: "iudirna_pzem_spotreba"
    power:
      name: "iudirna_pzem_prikon"
      id: pzem_energy
    frequency:
      name: "iudirna_pzem_frekvence"
    power_factor:
      name: "iudirna_pzem_ucinik"

########################################################### PID AUTOTUNE

  # PID HEAT SENSOR (SENSOR FOR GRAFANA)
  - platform: pid #sensor 
    name: "iUdirna PID Climate HEAT"
    type: HEAT
# ENABLE PID SENSORS BELOW ONLY DURING AUTOTUNE #
#  - platform: pid #sensor
#    name: "iUdirna PID Climate Result"
#    type: RESULT
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate PROPORTIONAL"
#    type: PROPORTIONAL 
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate INTEGRAL"
#    type: INTEGRAL
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate DERIVATIVE"
#    type: DERIVATIVE
#    climate_id: pid_climate
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate COOL"
#    type: COOL
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate KP"
#    type: KP
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate KI"
#    type: KI
#    climate_id: pid_climate
#  - platform: pid #sensor
#    name: "iUdirna PID Climate KD"
#    type: KD
#    climate_id: pid_climate
# ENABLE THE PID SENSORS ABOVE ONLY DURING AUTOTUNE #

########################################################### TEMP. SENSOR

  # UDIRNA
  - platform: dallas #sensor 
    name: "iudirna_dallas_teplota1"
    address: 0xC106219415E16428 
    id: iudirna_teplota1
    unit_of_measurement: "°C"  
    # address detected from the log
    
  # MASO1
  - platform: dallas #sensor
    name: "iudirna_dallas_teplota2"
    address: 0xBE06219419160728 
    id: iudirna_teplota2
    unit_of_measurement: "°C" 
    # address detected from the log
    
  # MASO2
  - platform: dallas #sensor
    name: "iudirna_dallas_teplota3"
    address: 0xB101215744DA0B28 
    id: iudirna_teplota3
    unit_of_measurement: "°C"  
    # address detected from the log
    
  # DYMBOX
  - platform: dallas #sensor
    name: "iudirna_dallas_teplota4"
    address: 0xB9012157542A0228 
    id: iudirna_teplota4
    unit_of_measurement: "°C"  
    # address detected from the log

########################################################### UPTIME SENSOR

  # UPTIME - doba uzeni
  - platform: uptime #sensor
    id: iudirna_up_time
    name: "iudirna_up_time2"
    update_interval: 60s
    filters:
      - lambda: return x / 3600;
    unit_of_measurement: "h"

########################################################### FAN + VIB + PID SENSOR

  # PID MODE LAMBDA FOR LCD (gets thermostat status - heat/off)
  - platform: template #sensor
    id: "pid_mode"
    name: iudirna_pid_mode
    update_interval: 1s
    accuracy_decimals: 0
    lambda: |-
      return id(pid_climate).mode;
      
  # FAN SPEED LAMBDA FOR LCD (gets a speed value)
  - platform: template #sensor
    id: "fan_speed"
    name: iudirna_fan_speed
    update_interval: 1s
    accuracy_decimals: 0
    lambda: |-
      return id(fan_pwm).speed;
      
  # VIB SPEED LAMBDA FOR LCD (gets a speed value)
  - platform: template #sensor
    id: "vibrator_speed"
    name: "iudirna_vibrator_speed"
    update_interval: 1s
    accuracy_decimals: 0
    lambda: |-
      return id(vibrator_pwm).speed;
  
########################################################### WIFI SIGNAL  

  # WIFI SIGNAL SENSOR
  - platform: wifi_signal #sensor
    name: "iudirna_signal_wifi2"
    update_interval: 10s     
    
interval: 

  # WIFI - CHECKING THE CONNECTION AND CONTROLLING THE LED INDICATOR LIGHT
  - interval: 1s
    then:
      if:
        condition:
          wifi.connected:
        then:
          - switch.turn_on: iudirna_led3_wifi_status
        else:
          - switch.turn_off: iudirna_led3_wifi_status
          
########################################################### TERMOSTAT - LED interval

  # LED DIODE - THERMOSTAT
  - interval: 100ms
    then:
      if:
        condition: 
          - sensor.in_range:
              id: pid_mode
              above: 1
              below: 5
        then:
          - switch.turn_on: iudirna_led0_termostat
        else:
          - switch.turn_off: iudirna_led0_termostat

########################################################### FAN AUTO 

  # FAN AUTO - change temperature and speed at will
  - interval: 10min
    id: interval_fan_auto
    then:
      if:
        condition:
          and:
            - switch.is_on: fan_auto
            - sensor.in_range:
                 id: iudirna_teplota4
                 above: -20 # vyse
                 below: 30  # nize
        then:
          - fan.turn_on:
              id: fan_pwm
              speed: !lambda return (id(fan_pwm).speed = 7.0); # SPEED
        else:               
          if:
            condition:
              and:
                - switch.is_on: fan_auto
                - sensor.in_range:
                     id: iudirna_teplota4
                     above: 30 # vyse
                     below: 50 # nize
            then:
              - fan.turn_on:
                  id: fan_pwm
                  speed: !lambda return (id(fan_pwm).speed = 5.0); # SPEED           
            else:
              if:
                condition:
                  and:
                    - switch.is_on: fan_auto
                    - sensor.in_range:
                        id: iudirna_teplota4
                        above: 55 # vyse
                        below: 80 # nize
                then:
                  - fan.turn_on:
                      id: fan_pwm
                      speed: !lambda return (id(fan_pwm).speed = 3.0); # SPEED   
                      
########################################################### VIBRATOR AUTO

  # VIBRATOR AUTO                    
  - interval: 10min
    id: interval_vibrator_auto
    then:
      if:
        condition:
          and: # a condition that is triggered manually by a button
            - switch.is_on: vibrator_auto 
            - sensor.in_range:
                id: iudirna_teplota4
                above: 0  # vyse
                below: 30 # nize
        then:
          - fan.turn_on:
              id: vibrator_pwm
              speed: !lambda return (id(vibrator_pwm).speed = 10.0);  # MAX SPEED
          - delay: 3s # ceka 3s
          - fan.turn_on:
              id: vibrator_pwm
              speed: !lambda return (id(vibrator_pwm).speed = 1.0); # SET 1 (1=OFF)
          - fan.turn_off: # OFF vibrator
              id: vibrator_pwm
        else:
          if:
            condition:
              and:
                - switch.is_on: vibrator_wait_temp # pcondition that is enabled only after the temperature is reached from the start
                - sensor.in_range:
                    id: iudirna_teplota4
                    above: 0  
                    below: 30 
            then:
              - fan.turn_on:
                  id: vibrator_pwm
                  speed: !lambda return (id(vibrator_pwm).speed = 10.0); # MAX SPEED
              - delay: 3s # ceka 3s
              - fan.turn_on:
                  id: vibrator_pwm
                  speed: !lambda return (id(vibrator_pwm).speed = 1.0); # SET 1 (1=OFF)
              - fan.turn_off: # OFF VIBRATOR
                  id: vibrator_pwm 
                  
binary_sensor:              

########################################################### BUTTONS

  # BUTTON THERMOSTAT 
  - platform: gpio #binary_sensor
    id: "iudirna_button5_termostat"
    pin:
      mcp23xxx: mcp23017_hub
      number: 5
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
        - delayed_on: 20ms
    on_press:
      - switch.toggle: pid_switch
              
  # BUTTON LIGHT IN
  - platform: gpio #binary_sensor
    id: "iudirna_button8_svetlo_vnitrni"
    pin:
      mcp23xxx: mcp23017_hub
      number: 9
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
        - delayed_on: 20ms
    on_press:
    - switch.toggle: iudirna_svetlo_in
    
  # BUTTON LIGHT OUT    
  - platform: gpio #binary_sensor 
    id: "iudirna_button9_svetlo_venkovni"
    pin:
      mcp23xxx: mcp23017_hub
      number: 8 
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
        - delayed_on: 20ms
    on_press:
    - switch.toggle: iudirna_svetlo_out
    
  # BUTTON THERMOSTAT TARGET TEMP +1°C   
  - platform: gpio #binary_sensor
    id: "iudirna_button10_set_temp_up"
    pin:
      mcp23xxx: mcp23017_hub
      number: 10
      mode:
        input: true
        pullup: true
      inverted: true
    on_click:
    - min_length: 20ms
      max_length: 500ms
      then:
        - climate.control:
            id: pid_climate
            target_temperature: !lambda return (id(pid_climate).target_temperature + 1.0);
    - min_length: 500ms
      max_length: 2000ms
      then:
        - climate.control:
            id: pid_climate
            target_temperature: !lambda return (id(pid_climate).target_temperature + 5.0);    
    - min_length: 2000ms
      max_length: 6000ms
      then:
        - climate.control:
            id: pid_climate
            target_temperature: !lambda return (id(pid_climate).target_temperature = 65.0);   
            
  # BUTTON THERMOSTAT TARGET TEMP -1°C 
  - platform: gpio #binary_sensor
    id: "iudirna_button11_set_temp_down"
    pin:
      mcp23xxx: mcp23017_hub
      number: 11
      mode:
        input: true
        pullup: true
      inverted: true
    on_click:
    - min_length: 20ms
      max_length: 500ms
      then:
        - climate.control:
            id: pid_climate
            target_temperature: !lambda return (id(pid_climate).target_temperature - 1.0);
    - min_length: 500ms
      max_length: 2000ms
      then:
        - climate.control:
            id: pid_climate
            target_temperature: !lambda return (id(pid_climate).target_temperature - 5.0);
    - min_length: 2000ms
      max_length: 6000ms
      then:
        - climate.control:
            id: pid_climate
            target_temperature: !lambda return (id(pid_climate).target_temperature = 0.0);
            
  # BUTTON FAN SPEED +1
  - platform: gpio #binary_sensor
    id: iudirna_button12_set_fan_up
    pin:
      mcp23xxx: mcp23017_hub
      number: 12
      mode:
        input: true
        pullup: true
      inverted: true
    on_click:
    - min_length: 20ms
      max_length: 500ms
      then:
        - fan.turn_on:
            id: fan_pwm
            speed: !lambda return (id(fan_pwm).speed + 1.0);
    - min_length: 500ms
      max_length: 3s
      then:
        - fan.turn_on:
            id: fan_pwm
            speed: !lambda return (id(fan_pwm).speed = 10.0);
            
  # BUTTON FAN SPEED -1
  - platform: gpio #binary_sensor
    id: iudirna_button13_set_fan_down
    pin:
      mcp23xxx: mcp23017_hub
      number: 13
      mode:
        input: true
        pullup: true
      inverted: true
    on_click:
    - min_length: 20ms
      max_length: 500ms
      then:
      - if:
          condition:
            or:
              - lambda: 'return id(fan_pwm).speed == 1.0;'
              - lambda: 'return id(fan_pwm).speed == 2.0;'
          then:
            - fan.turn_on:
                id: fan_pwm
                speed: !lambda return (id(fan_pwm).speed - 1.0);
            - fan.turn_off:
                id: fan_pwm
          else:
            - fan.turn_on:
                id: fan_pwm
                speed: !lambda return (id(fan_pwm).speed - 1.0);  
    - min_length: 500ms
      max_length: 3s
      then:
        - fan.turn_on:
            id: fan_pwm
            speed: !lambda return (id(fan_pwm).speed = 1.0);
        - fan.turn_off:
            id: fan_pwm
            
  # BUTTON FAN AUTO 
  - platform: gpio #binary_sensor
    id: iudirna_button14_fan_auto
    pin:
      mcp23xxx: mcp23017_hub
      number: 14 # B6
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
        - delayed_on: 20ms
    on_press:
      then:
        - switch.toggle: fan_auto
        
  # BUTTON VIBRATOR AUTO 
  - platform: gpio #binary_sensor
    id: iudirna_button15_vibrator_auto
    pin:
      mcp23xxx: mcp23017_hub
      number: 15 # B7
      mode:
        input: true
        pullup: true
      inverted: true
    on_click:
    - min_length: 20ms
      max_length: 500ms
      then:
        - switch.toggle: vibrator_auto
    - min_length: 500ms
      max_length: 5s
      then:
        - fan.turn_on:
            id: vibrator_pwm
            speed: !lambda return (id(vibrator_pwm).speed = 10.0);
        - delay: 3s
        - fan.turn_on:
            id: vibrator_pwm
            speed: !lambda return (id(vibrator_pwm).speed = 1.0);
        - fan.turn_off:
            id: vibrator_pwm
            
fan:
########################################################### FAN PWM OUTPUT

  # FAN PWM SPEED
  - platform: speed #fan
    output: fan_output
    id: fan_pwm
    name: "iudirna_fan_pwm_switch"
    speed_count: 10
    restore_mode: ALWAYS_OFF
    
  # VIBRATOR PWM SPEED
  - platform: speed
    output: vibrator_output
    id: vibrator_pwm
    name: "iudirna_vibrator_pwm_switch"
    speed_count: 10
    restore_mode: ALWAYS_OFF
    
output: 

  # FAN PWM OUTPUT
  - platform: esp8266_pwm #output
    pin: GPIO13
    frequency: 80 Hz # 12V FAN 5015
    id: fan_output
    min_power: 0
    max_power: 0.7


    
  # VIBRATOR PWM OUTPUT
  - platform: esp8266_pwm
    pin: GPIO14
    frequency: 600 Hz # 1.5-6V vibrator
    id: vibrator_output
    max_power: 0.5 # 1=12V 0.5=6V
   
########################################################### PID AUTOTUNE

  # PID - PWM output     
  - platform: slow_pwm #output
    pin: GPIO16
    id: heater
    period: 30s
    
switch: 

  # PID - autotune    
  - platform: template #switch
    name: "iUdirna PID Climate Autotune"
    turn_on_action:
      - climate.pid.autotune: pid_climate

########################################################### RELAY

  # FAN AUTO - enables the automatic control interval condition
  - platform: template
    name: "iudirna_fan_auto"
    id: fan_auto
    optimistic: true
    
  # VIBRATOR AUTO - enables the interval condition of the automatic button control
  - platform: template
    name: "iudirna_vibrator_auto"
    id: vibrator_auto
    optimistic: true
    turn_off_action: 
        # when manually switching off with the button it also switches off the wait_temp condition
      - switch.turn_off: vibrator_wait_temp 
      - fan.turn_on: # nastavi rychlost na minimum (1= vypnuto)
          id: vibrator_pwm
          speed: !lambda return (id(vibrator_pwm).speed = 1.0);
      - fan.turn_off: # a vypne vibrator
          id: vibrator_pwm 
          
  # VIBRATOR AUTO WAIT FOR TEMP             
  - platform: template                      
    name: "iudirna_vibrator_wait_temp"                                            
    id: vibrator_wait_temp                  
    optimistic: true
    # automatic control interval condition 
    # only after reaching a given temperature from the start does the thermometer switch it on
    # this will ensure that it will not vibrate from the beginning when melting but only 
    # after reaching the specified temperature
    
  # RELAY2 - INDOOR LIGHT
  - platform: gpio #switch
    id: iudirna_svetlo_in
    name: "iudirna_rele2_svetlo_vnitrni"
    restore_mode: ALWAYS_OFF
    pin:
      mcp23xxx: mcp23017_hub
      inverted: false
      number: 6
      mode:
        output: true
        pullup: false
    on_turn_on:
        - switch.turn_on: iudirna_led1_vnitrni_svetlo
    on_turn_off:
        - switch.turn_off: iudirna_led1_vnitrni_svetlo
        
  # RELAY3 - OUTDOOR LIGHT  
  - platform: gpio #switch
    id: iudirna_svetlo_out
    name: "iudirna_rele3_svetlo_venkovni"
    restore_mode: ALWAYS_OFF
    pin:
      mcp23xxx: mcp23017_hub
      inverted: false
      number: 7
      mode:
        output: true
        pullup: false
    on_turn_on:
        - switch.turn_on: iudirna_led2_venkovni_svetlo
    on_turn_off:
        - switch.turn_off: iudirna_led2_venkovni_svetlo 

########################################################### LED DIODE OUTPUT

  # LED1 - THERMOSTAT STATUS (RED)
  - platform: gpio #switch     
    id: "iudirna_led0_termostat"
    restore_mode: ALWAYS_OFF
    pin:
      mcp23xxx: mcp23017_hub
      number: 0 # A0
      mode:
        output: true
        pullup: false
      inverted: false 
      
  # LED2 - OUTDOOR LIGHT (YELLOW)
  - platform: gpio #switch     
    id: "iudirna_led1_vnitrni_svetlo"
    restore_mode: ALWAYS_OFF
    pin:
      mcp23xxx: mcp23017_hub
      number: 2 # A2
      mode:
        output: true
        pullup: false
      inverted: false 
      
  # LED3 - OUTDOOR LIGHT (YELLOW)
  - platform: gpio #switch     
    id: "iudirna_led2_venkovni_svetlo"
    restore_mode: ALWAYS_OFF
    pin:
      mcp23xxx: mcp23017_hub
      number: 1 # A1
      mode:
        output: true
        pullup: false
      inverted: false 
      
  # LED3 - WIFI status (BLUE)
  - platform: gpio #switch     
    id: "iudirna_led3_wifi_status"
    restore_mode: ALWAYS_OFF
    pin:
      mcp23xxx: mcp23017_hub
      number: 3 # A3
      mode:
        output: true
        pullup: false
      inverted: false 

  # PID THERMOSTAT REMOTE
  - platform: template                   
    id: pid_switch
    turn_on_action:
      if:
        condition:
          - sensor.in_range:
              id: pid_mode # 0=OFF 3=HEAT
              above: 1 # => ON
              below: 5 # => ON
        then:
          - climate.control:
              id: pid_climate
              mode: 'OFF'
        else:
          - climate.control:
              id: pid_climate
              mode: 'HEAT'
      

About

Home Assistant

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published