Skip to content

Instantly share code, notes, and snippets.

@tlinnet
Created August 16, 2025 19:22
Show Gist options
  • Save tlinnet/9970489fdd287ca79734c3002f5cba1e to your computer and use it in GitHub Desktop.
Save tlinnet/9970489fdd287ca79734c3002f5cba1e to your computer and use it in GitHub Desktop.
ESPHome YAML code for ESP32 Keyestudio Smart Farm KS0567
# Conversion from Arduino code to ESPHone YAML
# https://wiki.keyestudio.com/KS0567_Keyestudio_ESP32_IoT_Control_Smart_Farm_Starter_Kit_for_Arduino_Scratch_3.0_Graphical_Programming
# Arduino code: https://fs.keyestudio.com/KS0567
esphome:
name: esphome-web-0d8384
friendly_name: ESP32 Keyestudio Smart Farm KS0567
min_version: 2025.5.0
name_add_mac_suffix: false
on_boot:
priority: -100 # Do as last action
then:
- lambda: !lambda id(servoSlider).make_call().set_value(90).perform();
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
level: DEBUG
api:
encryption:
key: "REPLACE ME"
ota:
- platform: esphome
wifi:
ssid: REPLACE-ME
password: REPLACE-ME
#
servo:
- id: my_servo
output: servo_output
auto_detach_time: 3s # Stop feeding power
transition_length: 1s # How fast
rtttl:
output: rtttl_out
on_finished_playback:
- logger.log: 'Song ended!'
# Servo Motor and Fan Motor
output:
- platform: ledc # On ESP32, use ledc output. Else esp8266_pwm
id: servo_output
pin: GPIO26
frequency: 50 Hz
- platform: ledc
id: fan_forward
pin: GPIO19
frequency: 50 Hz # Needs same frequency
- platform: ledc
id: fan_reverse
pin: GPIO18
frequency: 50 Hz # Needs same frequency
- platform: ledc
id: rtttl_out
pin: GPIO16
frequency: 50 Hz # Needs same frequency
switch:
- platform: gpio
name: "LED"
id: led_switch
pin: GPIO27
- platform: template
name: "Fan"
id: fan_switch
optimistic: true
turn_on_action:
- output.set_level:
id: fan_forward
level: 0.25
- output.set_level:
id: fan_reverse
level: 0.0
turn_off_action:
- output.set_level:
id: fan_forward
level: 0.0
- output.set_level:
id: fan_reverse
level: 0.0
- platform: template
name: "Play Buzzer"
id: rtttl_switch
optimistic: true
on_turn_on:
then:
# - rtttl.play: ‘StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6’
# - rtttl.play: ‘star_wars:d=16,o=5,b=100:4e,4e,4e,8c,p,g,4e,8c,p,g,4e,4p,4b,4b,4b,8c6,p,g,4d#,8c,p,g,4e,8p’
# - rtttl.play: ‘mission_imp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d’
- rtttl.play: ‘mario:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6’
on_turn_off:
then:
- rtttl.stop
number:
- platform: template
id: servoSlider
name: Servo Control
icon: mdi:sync
optimistic: true
min_value: -10 # Servo rotates to -10deg to open the box
max_value: 90
initial_value: 90
step: 5
on_value:
then:
- lambda: !lambda id(my_servo).write(x/90);
sensor:
- platform: ultrasonic
name: "Ultrasonic Distance"
id: ultrasonic_sensor
trigger_pin: GPIO12
echo_pin: GPIO13
update_interval: 1s
filters:
- multiply: 50 # Convert to cm. This is distance back and forth. Half
- filter_out: nan
- median:
window_size: 3
send_every: 2
send_first_at: 2
accuracy_decimals: 1
unit_of_measurement: "cm"
on_value_range:
- above: 2
below: 4
then:
- number.set:
id: servoSlider
value: -10
- above: 4
then:
- number.set:
id: servoSlider
value: 90
- platform: adc
name: "Photocell Light Level"
id: photo_sensor
pin: GPIO34
update_interval: 1s
attenuation: auto
unit_of_measurement: "lux"
accuracy_decimals: 1
on_value_range:
- below: 1.5
then:
- switch.turn_on: led_switch
- above: 1.5
then:
- switch.turn_off: led_switch
- platform: adc
name: "Steam Sensor Level"
id: steam_sensor
pin: GPIO35
update_interval: 1s
attenuation: auto
unit_of_measurement: "ppm"
accuracy_decimals: 1
on_value_range:
- below: 2
then:
- switch.turn_off: rtttl_switch
- above: 2
then:
- switch.turn_on: rtttl_switch
binary_sensor:
- platform: gpio
pin: GPIO5
name: "Fan Button"
id: button_fan
device_class: running
filters:
- invert:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
- logger.log: "Button was pressed"
- switch.turn_on: fan_switch
on_release:
then:
- logger.log: "Button was released"
- switch.turn_off: fan_switch
@tlinnet
Copy link
Author

tlinnet commented Aug 16, 2025

Added LCD

esphome:
  name: esphome-web-0d8384
  friendly_name: ESP32 Keyestudio Smart Farm KS0567
  min_version: 2025.5.0
  name_add_mac_suffix: false
  on_boot: 
    priority: -100 # Do as last action
    then:
      - lambda: !lambda id(servoSlider).make_call().set_value(90).perform();

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

logger:
  level: DEBUG

api:
  encryption:
    key: !secret api_encryption_key

ota:
  - platform: esphome

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

substitutions:
  text_line_1: !secret text_line_1
  text_line_2: !secret text_line_2

#
servo:
  - id: my_servo
    output: servo_output
    auto_detach_time: 3s # Stop feeding power
    transition_length: 1s # How fast

rtttl:
  output: rtttl_out
  on_finished_playback:
    - logger.log: 'Song ended!'
    - switch.turn_off: rtttl_switch

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true
  frequency: 200kHz

# Servo Motor and Fan Motor
output:
  - platform: ledc # On ESP32, use ledc output. Else esp8266_pwm
    id: servo_output
    pin: GPIO26
    frequency: 50 Hz
  - platform: ledc
    id: fan_forward
    pin: GPIO19
    frequency: 50 Hz # Needs same frequency
  - platform: ledc
    id: fan_reverse
    pin: GPIO18
    frequency: 50 Hz # Needs same frequency
  - platform: ledc
    id: rtttl_out
    pin: GPIO16
    frequency: 50 Hz # Needs same frequency

switch:
  - platform: gpio
    name: "LED"
    id: led_switch
    pin: GPIO27
  - platform: template
    name: "Fan"
    id: fan_switch
    optimistic: true
    turn_on_action:
      - output.set_level:
          id: fan_forward
          level: 0.25
      - output.set_level:
          id: fan_reverse
          level: 0.0
    turn_off_action:
      - output.set_level:
          id: fan_forward
          level: 0.0
      - output.set_level:
          id: fan_reverse
          level: 0.0
  - platform: template
    name: "Play Buzzer"
    id: rtttl_switch
    optimistic: true
    on_turn_on:
      then:
#        - rtttl.play: 'StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6'
#        - rtttl.play: 'star_wars:d=16,o=5,b=100:4e,4e,4e,8c,p,g,4e,8c,p,g,4e,4p,4b,4b,4b,8c6,p,g,4d#,8c,p,g,4e,8p'
#        - rtttl.play: 'mission_imp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d'
        - rtttl.play: 'mario:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6'
    on_turn_off:
      then:
        - rtttl.stop

number:
  - platform: template
    id: servoSlider
    name: Servo Control
    icon: mdi:sync
    optimistic: true
    min_value: -10 # Servo rotates to -10deg to open the box
    max_value: 90
    initial_value: 90
    step: 5
    on_value: 
      then:
        - lambda: !lambda id(my_servo).write(x/90);

sensor:
  - platform: ultrasonic
    name: "Ultrasonic Distance"
    id: ultrasonic_sensor
    trigger_pin: GPIO12
    echo_pin: GPIO13
    update_interval: 1s
    filters:
      - multiply: 50 # Convert to cm. This is distance back and forth. Half
      - filter_out: nan
      - median:
          window_size: 3
          send_every: 2
          send_first_at: 2
    accuracy_decimals: 1
    unit_of_measurement: "cm"
    on_value_range:
      - above: 2
        below: 4
        then:
          - number.set:
              id: servoSlider
              value: -10
      - above: 4
        then:
          - number.set:
              id: servoSlider
              value: 90
  - platform: adc
    name: "Photocell Light Level"
    id: photo_sensor
    pin: GPIO34
    update_interval: 1s
    attenuation: auto
    unit_of_measurement: "lux"
    accuracy_decimals: 1
    on_value_range:
      - below: 1.5
        then:
          - switch.turn_on: led_switch
      - above: 1.5
        then:
          - switch.turn_off: led_switch
  - platform: adc
    name: "Steam Sensor Level"
    id: steam_sensor
    pin: GPIO35
    update_interval: 1s
    attenuation: auto
    unit_of_measurement: "ppm"
    accuracy_decimals: 1
    on_value_range:
      - below: 2
        then:
          - switch.turn_off: rtttl_switch
      - above: 2
        then:
          - switch.turn_on: rtttl_switch

binary_sensor:
  - platform: gpio
    pin: GPIO5
    name: "Fan Button"
    id: button_fan
    device_class: running
    filters:
      - invert:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_press:
      then:
        - logger.log: "Button was pressed"
        - switch.turn_on: fan_switch
    on_release:
      then:
        - logger.log: "Button was released"
        - switch.turn_off: fan_switch

globals:
  - id: display_mode
    type: int
    initial_value: '0'

display:
  - platform: lcd_pcf8574
    dimensions: 16x2
    address: 0x27
    id: my_lcd
    lambda: |-
      if (id(display_mode) == 0) {
        it.printf(0, 0, "%s", "${text_line_1}");
        it.printf(0, 1, "%s", "${text_line_2}");
      } else {
        it.printf(0, 0, "Dist.: %.1f cm", id(ultrasonic_sensor).state);
        it.printf(0, 1, "Light: %.1f lux", id(photo_sensor).state);
      }

interval:
  - interval: 5s
    then:
      - lambda: |-
          id(display_mode) = (id(display_mode) + 1) % 2;
      - lambda: |-
          id(my_lcd).update();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment