Yoghurt maker project

After searching lots and finding little, I figured that there is value in sharing my project here for others to use and hopefully, help develop.

The driver for this project is that I wanted a yoghurt / yogurt maker that met the criteria for making some large batches of probiotic yoghurt. For those interested in the health and science, read the book ‘Super Gut’ by Dr. William Davis.

  • Must be able to run continuously, unattended, for up to 48 hours,
  • Must be able to heat as low as 95F
  • Must be able to handle a single batch of 2 quarts
  • Must not be expensive

I found zero products that were available and fit the requirements so I figured I’d set about building one as a prototype. I looked at what was available and as with most first-cut prototypes, I wanted it as cheap as possible. I bought the Euro Cuisine YM80 yoghurt maker from Amazon along with the additional tier to raise capacity. It comes with tiny jars for making different flavours of ‘normal’ yoghurt but they are no use to me. The additional tier has a moulded holder for more jars that I may need to cut out. I will be just using a single Ziplock tub or maybe mason jars in there.

The device has what I needed but couldn’t easily make; a housing and a heater. The device as received has a switch, a power light and a heater plate. There is no temperature control or timer control so I needed to add those.

I pulled off the rubber feet and used an S2 T20 security Torx bit to remove the 4 screws. The inner plastic pan then comes off to reveal the heat plate and wiring. Now for the interesting stuff…

I used a Wemos D1 esp8266 as the controller, a Dallas DS18B20 temperature sensor, a dual 5v relay board and an SH1106 128x64 (ssd1306_i2c) OLED screen I had in my parts bin.

I added a generic thermostat component to my Home Assistant configuration.yaml and also added an automation helper timer entity. The timer is used in an automation routine to trigger the timer relay as that was the first way that I figured out how to get it to work. The thermostat function works to read the Dallas temperature, set the desired temperature for the unit and control the units heater relay depending on the difference between the two.

Challenges I had:
Screen and display code:-
The first issue I has was that I hadn’t used an OLED before so I needed to figure that out. I determined that it was an ssd1306 driver and i2c as it only had vcc, gnd, slk and sda pins. I just got noise on the screen until I figured out that I needed to set the model, which in my case was sh1106. Once I set that, the screen noise was gone and I could play with the text and font stuff. Again, I couldn’t work out how to make the fonts work and a lot of the forum posts seem to assume knowledge of this. In short, I learned by grabbing a simple font like Arial.ttf, getting the .ttf download and putting it in /config/esphome. Once there, the code will reference it and it is then just about playing with screen position and font size to make it look right for you. I posted here and got some solid help that allowed me to make progress. I was struggling to format the code to get the HA set temperature value to display on the screen.

Power:-
There isn’t a practical way to convert 110v to 5v in a small form factor that will fit inside the YM80. The heat plate is 110v (or 240v for the EU models) so I chose to just run a microUSB cable from the Wemos. At first, I was going to use a power cable but instead went with a microUSB to USB-A cable so that I could reflash the Wemos in the event that it wouldn’t OTA flash. I have Unifi wifi hardware and there seems to be a bug in later ESPhome firmware that causes issues with connecting.

Display mounting:-
Its a prototype so it can look clunky but, there isn’t a flat surface that the screen can be mounted on to look nice. I just hot-glued the screen to the outside to cover over the power switch hole.

Issues and work still remaining:
I noticed that the temperature swing is a lot wider than I can accept. Ideally, I want the internal temperature of the unit to remain within 1F. The climate code handles this and I need to look further into why I am getting the deep cooling swings.

Any suggestions welcome.

I also think that the code can be cleaned up. I’m not a natural dev so my code ends up being what works from the snippets I can find when I search for solutions to problems that I’m having. In particular, I appreciate that there may be several ways to achieve the same goal and I’m not certain that I’m using the most efficient solution.

The timer function isn’t as stylish as I want it to be. It works but in the same way that red tuck tape works for that broken back light on your truck.

ESP Code:

esphome:
  name: esp8266-yoghurtmaker
  comment: ESPhome comment here

esp8266:
  board: d1_mini
  framework:
    version: recommended

logger:

wifi:
  manual_ip:
    static_ip: 192.168.10.XXX
    gateway: 192.168.10.1
    subnet: 255.255.255.0
    dns1: 192.168.10.1
    dns2: 0.0.0.0
  ap:
    ssid: "Fallback-yoghurtmaker"
    password: ""
    ap_timeout: 1min
  domain: .local
  reboot_timeout: 15min
  power_save_mode: NONE
  fast_connect: false
  output_power: 20.0
  networks:
  - ssid: !secret wifi_iot_ssid
    password: !secret wifi_iot_password
    priority: 0.0
  use_address: 192.168.10.XXX

captive_portal:

api:
  password: !secret api_password
  port: 6053
  reboot_timeout: 15min
ota:
  password: !secret ota_password
  safe_mode: true
  port: 8266

font:
  - file: 'arlrdbd.ttf'
    id: font1
    size: 30  

dallas:
  - pin: D5 #GPIO14
    update_interval: 15s
i2c:
  sda: D2
  scl: D1

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    reset_pin: D0 #GPIO16
    address: 0x3C
    lambda: |-
      it.printf(0, 0, id(font1), "T: %.1f F", id(yoghurt_maker_temperature).state);
      it.printf(0, 30, id(font1), "S: %.0f F", id(ym_settemp).state);
      
switch:
  - platform: restart
    name: Yoghurt Maker Restart  

  - platform: gpio
    pin:
      number: D6 #GPIO12
      inverted: yes
    restore_mode: Restore_Default_Off
    name: "Yoghurt Maker Heater"
    id: yoghurt_maker_heater

  - platform: gpio
    pin:
      number: D7 #GPIO13
      inverted: yes
    restore_mode: Restore_Default_Off
    name: "Yoghurt Maker Timer"
    id: yoghurt_maker_timer

sensor:
  - platform: dallas
    address: 0x773c01b5567fxxxx
    name: "Yoghurt Maker Temperature"
    id: yoghurt_maker_temperature
    device_class: "temperature"
    state_class: "measurement"
    unit_of_measurement: "ºF"
    accuracy_decimals: 1
    filters:
      - filter_out: nan
      - lambda: return x * (9.0/5.0) + 32.0;
      
  - platform: homeassistant
    id: ym_settemp
    entity_id: climate.ha_ym_interface
    attribute: temperature

binary_sensor:
  - platform: status
    name: "Yoghurt Maker Status"

HA configuration.yaml code:

climate:
  - platform: generic_thermostat
    name: "HA YM Interface"
    unique_id: ha_ym_interface
    heater: switch.yoghurt_maker_heater
    target_sensor: sensor.yoghurt_maker_temperature
    min_temp: 50
    max_temp: 150
    hot_tolerance: 1
    min_cycle_duration:
      seconds: 5
    keep_alive:
      seconds: 30
    initial_hvac_mode: "off"
    precision: 1.0

Dashboard code:

type: vertical-stack
cards:
  - type: thermostat
    entity: climate.ha_ym_interface
    name: Yoghurt Maker
  - type: entities
    entities:
      - entity: sensor.ym_settemp
        name: Set Temp
        icon: mdi:thermometer-lines
      - entity: sensor.yoghurt_maker_temperature
        name: Internal Temp
      - entity: timer.ym_timer
        name: Timer Status
      - entity: switch.yoghurt_maker_heater
        name: Heater Switch
        icon: mdi:radiator
      - entity: switch.yoghurt_maker_timer
        name: Timer Switch
        icon: mdi:timer-sand-complete
      - entity: binary_sensor.yoghurt_maker_status
        name: Status
    state_color: true

I might post some pics of the unit later once I clear up my workspace. If anyone has improvement suggestions for the device or the code, let 'er rip!

1 Like

Digging a bit into the temp swings, I realised that I hat a hot_tolerance but not a cold_tolerance. I added that in and changed both to minimum values of 0.3 and that now cycles as expected.

climate:
  - platform: generic_thermostat
    name: "HA YM Interface"
    unique_id: ha_ym_interface
    heater: switch.yoghurt_maker_heater
    target_sensor: sensor.yoghurt_maker_temperature
    min_temp: 50
    max_temp: 150
    hot_tolerance: 0.3
    cold_tolerance: 0.3
    min_cycle_duration:
      seconds: 5
    keep_alive:
      seconds: 30
    initial_hvac_mode: "off"
    precision: 1.0

The new issue is what I’ll call ‘overshoot’; heater runs and switches off at 100.3 (100F set temp plus 0.3 tolerance) but the residual heat after switch off climbs to 101.5F. Conversely, low switch on occurs at 99.7F (100 - 0.3 tolerance) but heat lag means the temperature keeps falling to 98.6F so give or take there is a 1.2F overshoot in both directions.

I figure the answer to this will involve code to cycle the relay while the thermostat is calling for heat but I don’t even know where to start. The secret may lie in the min_cycle_duration but I’m guessing there. Anyone have any ideas?

1 Like

I wonder if a PID controller setup may help PID Climate — ESPHome

Some photos of your setup would be nice :slight_smile:

1 Like

I thought of that but deleted my post when I realised the PID climate controller requires a float output (PWM as opposed to a binary switch).

The PID controller would also need to be 110v. It’s a solid idea, I’ll look into it. Thanks.

Yeah but it does say you can use slow_pwm which would pulse the heater on and off with a long duty cycle.

And @TripitakaBC the 110v I presume is switched via a relay which is switched via a GPIO.

1 Like

PID tuning is also a bit of an art. Though there are plenty of tutorials.

Yes, currently (pun intended) the 110v is switched via a pair or relays run off GIO. 110v power comes to the first relay which is controlled by the timer entity. If the timer is running, 110v flows to the second relay which is controlled by the thermostat.

Thinking ahead, having that setup controlled by a PID would cause the relay to ‘chatter’ or even vibrate so a solid state relay would be necessary.

I’ll try a couple of batches as it is. These probiotics can be very sensitive to temperatures but as long as they don’t go above their kill temp, we are all good.

2 Likes