Dmitry
Published

Smart Solar Heating with MiniPLC, ESPHome & Home Assistant

Upgrade your solar heating with MiniPLC, ESPHome & Home Assistant—smart control, real-time data, and energy efficiency in one system.

BeginnerFull instructions provided10 hours207
Smart Solar Heating with MiniPLC, ESPHome & Home Assistant

Things used in this project

Hardware components

MiniPLC
HOMEMASTER MiniPLC
×1
pt1000 Sensor
×1
pt100
×1
Adafruit Waterproof DS18B20 Digital temperature sensor
Adafruit Waterproof DS18B20 Digital temperature sensor
×4
water pump
×1

Software apps and online services

Home Assistant
Home Assistant
ESPHome

Story

Read more

Code

ESPHome YAML Configuration for Smart Solar Heating Control

YAML
This file defines the automation logic for controlling the circulation and mixing pumps based on temperature readings from RTD and 1-Wire sensors. It is deployed to the MiniPLC via ESPHome dashboard.
esphome:
  name: miniplc
  friendly_name: "MiniPLC"

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:


captive_portal:




web_server: 
  port: 80
  version: 3


one_wire:
  - platform: gpio
    pin: GPIO05
    id: hub_1
  - platform: gpio
    pin: GPIO04
    id: hub_2

i2c:
  - id: bus_a
    sda: 32
    scl: 33
    frequency: 400kHz
    timeout: 1s
    scan: true
    



time:
  - platform: pcf8563
    id: pcf8563_time
    address: 0x51
    timezone: "Romania/Bucharest"
  - platform: homeassistant
    # instead try to synchronize via network repeatedly ...
    on_time_sync:
      then:
        # ... and update the RTC when the synchronization was successful
        pcf8563.write_time:

    on_time:
      # Every 5 minutes
      - seconds: /10
        then:
          - if:
              condition:
                lambda: 'return id(collector_temperature).state > id(heater_temperature).state + 10;'
              then:
                - switch.turn_on: relay1
              else:
              - if:
                  condition:
                    lambda: 'return id(collector_temperature).state < id(heater_temperature).state + 5;'
                  then:
                    - switch.turn_off: relay1
      - seconds: /30
        then:
          - if:
              condition:
                lambda: 'return id(heater_up_temperature).state > id(heater_temperature).state + 3;'
              then:
                - switch.turn_on: relay2
              else:
              - if:
                  condition:
                    lambda: 'return id(heater_up_temperature).state < id(heater_temperature).state + 2;'
                  then:
                    - switch.turn_off: relay2

pcf8574:
  - id: 'pcf8574_hub_a'
    address: 0x38
    pcf8575: false
  - id: 'pcf8574_hub_b'
    address: 0x39
    pcf8575: false


spi:
  miso_pin: GPIO12
  mosi_pin: GPIO13
  clk_pin: GPIO14

text_sensor:
  - platform: template
    name: "Current time"
    id: current_time
    lambda: |-
      char str[17];
      time_t currTime = id(pcf8563_time).now().timestamp;
      strftime(str, sizeof(str), "%Y-%m-%d %H:%M", localtime(&currTime));
      return  { str };
    update_interval: 60s


font:
  - file: "gfonts://Roboto"
    id: roboto_small
    size: 8

  - file: "gfonts://Roboto"
    id: roboto_big
    size: 48

  - file: "gfonts://Roboto"
    id: roboto
    size: 14

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C 
    rotation: 180
    contrast: 100%
    id: oled_display
#    update_interval: 1s
#    lambda: |-
#       // Print "Mitt Smarta Hus" in top center.
#       it.printf(64, 0, id(font1), TextAlign::TOP_CENTER, "HOMEMASTER");

#       // Print time in HH:MM format
#       it.strftime(0, 60, id(font2), TextAlign::BASELINE_LEFT, "%H:%M", id(pcf8563_time).now());
    pages:
      - id: page1
        lambda: |-
          it.printf(64, 0, id(roboto_small), TextAlign::TOP_CENTER, "HOMEMASTER");
          it.strftime(0, 60, id(roboto_big), TextAlign::BASELINE_LEFT, "%H:%M", id(pcf8563_time).now());
      - id: page2
        lambda: |-
          char str[17];
          time_t currTime = id(pcf8563_time).now().timestamp;
          strftime(str, sizeof(str), "Time: %H:%M", localtime(&currTime)); // Nur Uhrzeit anzeigen
          it.printf(0, 0, id(roboto), "%s", str); // Anzeige der Uhrzeit
          it.printf(0, 20, id(roboto), "Collector: %.1f°C", id(collector_temperature).state); // Display temperature
          it.printf(0, 40, id(roboto), "Heater: %.1f °C", id(heater_temperature).state); // Display humidity
      - id: page3
        lambda: |-
          char str[17];
          time_t currTime = id(pcf8563_time).now().timestamp;
          strftime(str, sizeof(str), "Time: %H:%M", localtime(&currTime)); // Nur Uhrzeit anzeigen
          it.printf(0, 0, id(roboto), "%s", str); // Anzeige der Uhrzeit
          it.printf(0, 20, id(roboto), "Heater up: %.1f°C", id(heater_up_temperature).state); // Display temperature
          it.printf(0, 40, id(roboto), "Heater down: %.1f °C", id(heater_down_temperature).state); // Display humidity
      - id: page4
        lambda: |-
          char str[17];
          time_t currTime = id(pcf8563_time).now().timestamp;
          strftime(str, sizeof(str), "Time: %H:%M", localtime(&currTime)); // Nur Uhrzeit anzeigen
          it.printf(0, 0, id(roboto), "%s", str); // Anzeige der Uhrzeit
          it.printf(0, 20, id(roboto), "Feed water: %.1f°C", id(feed_water_to_collector_T).state); // Display temperature
          it.printf(0, 40, id(roboto), "Return water: %.1f °C", id(return_water_from_collector_T).state); // Display humidity
      - id: page5
        lambda: |-
          char str[17];
          time_t currTime = id(pcf8563_time).now().timestamp;
          strftime(str, sizeof(str), "Time: %H:%M", localtime(&currTime));
          it.printf(0, 0, id(roboto), "%s", str);
          if (id(relay1).state) {
            it.print(0, 20, id(roboto), "Water pump: ON");
          } else {
            it.print(0, 20, id(roboto), "Water pump: OFF");
          }
          if (id(relay2).state) {
            it.print(0, 40, id(roboto), "Mixing pump: ON");
          } else {
            it.print(0, 40, id(roboto), "Mixing pump: OFF");
          }



binary_sensor:
  - platform: gpio
    pin:
      number: GPIO36
    name: "DI #1"
  - platform: gpio
    pin:
      number: GPIO39
    name: "DI #2"
  - platform: gpio
    pin:
      number: GPIO34
    name: "DI #3"
  - platform: gpio
    pin:
      number: GPIO35
    name: "DI #4"
  - platform: gpio
    name: "Button #1"
    pin:
      pcf8574: pcf8574_hub_a
      number: 0
      inverted: true
    filters:
      - delayed_on: 30ms
      - delayed_off: 30ms
    on_press:
    - display.page.show_next: oled_display
  - platform: gpio
    name: "Button #2"
    pin:
      pcf8574: pcf8574_hub_a
      number: 1
      inverted: true
    filters:
      - delayed_on: 30ms
      - delayed_off: 30ms
    on_press:
    - display.page.show_previous: oled_display
  - platform: gpio
    name: "Button #3"
    pin:
      pcf8574: pcf8574_hub_a
      number: 2
      inverted: true
  - platform: gpio
    name: "Button #4"
    pin:
      pcf8574: pcf8574_hub_a
      number: 3
      inverted: true



switch:
 - platform: gpio
   name: "RELAY #1"
   id: relay1
   pin:
      pcf8574: pcf8574_hub_b
      number: 2
      mode:
        output: true
      inverted: false
 - platform: gpio
   name: "RELAY #2"
   id: relay2
   pin:
      pcf8574: pcf8574_hub_b
      number: 1
      mode:
        output: true
      inverted: false
 - platform: gpio
   name: "RELAY #3"
   pin:
      pcf8574: pcf8574_hub_b
      number: 0
      mode:
        output: true
      inverted: true

 - platform: gpio
   name: "RELAY #4"
   pin:
      pcf8574: pcf8574_hub_a
      number: 6
      mode:
        output: true
      inverted: true
 - platform: gpio
   name: "RELAY #5"
   pin:
      pcf8574: pcf8574_hub_a
      number: 5
      mode:
        output: true
      inverted: true
 - platform: gpio
   name: "RELAY #6"
   pin:
      pcf8574: pcf8574_hub_a
      number: 4
      mode:
        output: true
      inverted: true
 - platform: gpio
   name: "LED #2"
   pin:
      pcf8574: pcf8574_hub_b
      number: 3
      mode:
        output: true
      inverted: true
 - platform: gpio
   name: "LED #3"
   pin:
      pcf8574: pcf8574_hub_b
      number: 4
      mode:
        output: true
      inverted: true
 - platform: template
   name: "Switch buzzer"
   optimistic: true
   turn_on_action:
     - output.turn_on: buzzer_output
     - output.ledc.set_frequency:
         id: buzzer_output
         frequency: "2441Hz"
     - output.set_level:
         id: buzzer_output
         level: "75%"
   turn_off_action:
     - output.turn_off: buzzer_output

sensor:
 # WiFi Signal Strength
  - platform: wifi_signal
    name: "MiniPLC Wifi Signal Strength"
    update_interval: 60s
  - platform: uptime
    name: "MiniPLC Uptime"
# Dallas temperature
  - platform: dallas_temp
    one_wire_id: hub_1
    address: 0x973c99e3819c3528
    name: "Heat exchanger down Temp."
    id: heater_down_temperature
    update_interval: 5s
  - platform: dallas_temp
    one_wire_id: hub_1
    address: 0x333c56f649b88328
    name: "Heat exchanger up Temp."
    id: heater_up_temperature
    update_interval: 5s
  - platform: dallas_temp
    one_wire_id: hub_2
    address: 0x0e0000006ac79328
    name: "Feed water from collector"
    id: feed_water_to_collector_T
    update_interval: 5s
  - platform: dallas_temp
    one_wire_id: hub_2
    address: 0x07030d9794011328
    name: "Return water to collector"
    id: return_water_from_collector_T
    update_interval: 5s
    filters:
    - timeout:
        timeout: 10s
        value: 0
 #MAX 31865 RTD 
  - platform: max31865
    name: "MAX 31856 Temperature 1"
    id: collector_temperature
    cs_pin: GPIO1
    reference_resistance: 400 Ω
    rtd_nominal_resistance: 100 Ω
    update_interval: 5s
  - platform: max31865
    name: "MAX 31856 Temperature 2"
    id: heater_temperature
    cs_pin: GPIO3
    reference_resistance: 4000 Ω
    rtd_nominal_resistance: 1000 Ω
    update_interval: 5s
  - platform: ads1115
    multiplexer: 'A0_GND'
    gain: 6.144
    name: "ADC AI4"
    update_interval: 60s
    filters:
      - multiply: 3
  - platform: ads1115
    multiplexer: 'A1_GND'
    gain: 6.144
    name: "ADC AI3"
    update_interval: 60s
    filters:
      - multiply: 3
  - platform: ads1115
    multiplexer: 'A2_GND'
    gain: 6.144
    name: "ADC AI2"
    update_interval: 60s
    filters:
      - multiply: 3
  - platform: ads1115
    multiplexer: 'A3_GND'
    gain: 6.144
    name: "ADC AI1"
    update_interval: 60s
    filters:
      - multiply: 3
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    name: "Modbus Sensor"
    register_type: holding
    address: 0x0001    ## address of the register inside the Modbus slave device
    unit_of_measurement: "C"
    value_type: U_WORD


output:
 - platform: ledc
   pin: GPIO02
   id: buzzer_output  
 - platform: mcp4725
   id: dac_output
status_led:
  pin:
     pcf8574: pcf8574_hub_a
     number: 7
     mode:
       output: true
     inverted: false

Credits

Dmitry
2 projects • 1 follower

Comments