Good day fellow Home Assistant Users,
I am trying to set up a turntable for photogrammetry with the ESP32 and an external stepper driver. There is lots of switches for the cameras and lights ect and all is working as expected.
I want most programming done on the esp/esphome side.
I will explain as best as I can so here goes.
Basic Principle:
- Turn on switch in HassIO
- Delay - Wait for start delay (before turntable starts turning)
- Snap all photos (with shutter delays)
- Delay - for cameras to finish taking photos (all that is enabled at once)
- Turn the turntable a set number of steps or degrees and stop
- Snap all photos - same as 3
- Delay - same as 4
- Check if turntable has reached the final position (Final position in my case is 360 degrees or 47520 steps)
- If not: Repeat from point nr 5 above
If Yes: Stop Turning
My Code is not perfect but does everything except the part where it
-checks if the next/final position has been reached and turn again.
Some (only one or two entries) of the code in here I may not be using anymore.
That is what I need help with and have been trying for a few weeks now but no luck.
substitutions:
room: workshop
upper_room: Workshop
devicename: turntable_esp32
upper_devicename: Turntable ESP32
##################################################
##################################################
###### ESPHome Config
##################################################
##################################################
esphome:
name: $devicename
platform: ESP32
board: esp32doit-devkit-v1
wifi:
use_address: 192.168.1.147
reboot_timeout: 1min
networks:
- ssid: "Wifi1"
password: "wifipassword1"
- ssid: "Wifi2"
password: "wifipassword2"
- ssid: "Wifi3"
password: "wifipassword3"
power_save_mode: none
ap:
ssid: "ESP32 Turntable"
password: "password"
captive_portal:
logger:
api:
services:
- service: control_stepper
variables:
target: int
then:
- stepper.set_target:
id: turntable_stepper
target: !lambda 'return target;'
ota:
##################################################
##################################################
###### Stepper Motor
##################################################
##################################################
stepper:
- platform: a4988
id: turntable_stepper
step_pin:
number: 4
inverted: True
# mode: INPUT_PULLUP
dir_pin:
number: 16
inverted: True
# mode: INPUT_PULLUP
max_speed: 100000 steps/s
# sleep_pin:
# number: 17
# inverted: True
# mode: INPUT_PULLUP
acceleration: 2000
deceleration: 2000
##################################################
##################################################
##### Switches
##################################################
##################################################
switch:
##### ESPHome Switches
##################################################
- platform: restart
name: "Reboot ${upper_devicename}"
id: turntable_esp32_restart
##################################################
##### GPIO Switches
##################################################
##### Lights
- platform: gpio
name: Turntable Lights
id: switch_turntable_lights
pin:
number: 25
inverted: True
##### Stepper Enable
- platform: gpio
name: "Turntable Enable Switch"
id: turntable_enable_switch
pin:
number: 17
inverted: True
##### Power Supply Relay
- platform: gpio
name: Stepper PSU Switch
id: switch_stepper_psu
pin:
number: 15
inverted: True
##### Camera 1 Shutter
- platform: gpio
id: camera_1_shutter_gpio_switch
pin:
number: 5
inverted: True
on_turn_on:
then:
- delay: !lambda return id(camera_1_shutter_delay).state;
- switch.turn_off: camera_1_shutter_gpio_switch
- platform: template
name: Camera 1 Shutter Switch
id: camera_1_shutter_template_switch
# icon: mdi:
turn_on_action:
if:
condition:
binary_sensor.is_on: enable_camera_1
then:
- switch.turn_on: camera_1_shutter_gpio_switch
##### Camera 2 Shutter
- platform: gpio
id: camera_2_shutter_gpio_switch
pin:
number: 18
inverted: True
on_turn_on:
then:
- delay: !lambda return id(camera_2_shutter_delay).state;
- switch.turn_off: camera_2_shutter_gpio_switch
- platform: template
name: Camera 2 Shutter Switch
id: camera_2_shutter_template_switch
# icon: mdi:
turn_on_action:
if:
condition:
binary_sensor.is_on: enable_camera_2
then:
- switch.turn_on: camera_2_shutter_gpio_switch
##### Camera 3 Shutter
- platform: gpio
id: camera_3_shutter_gpio_switch
pin:
number: 19
inverted: True
on_turn_on:
then:
- delay: !lambda return id(camera_3_shutter_delay).state;
- switch.turn_off: camera_3_shutter_gpio_switch
- platform: template
name: Camera 3 Shutter Switch
id: camera_3_shutter_template_switch
# icon: mdi:
turn_on_action:
if:
condition:
binary_sensor.is_on: enable_camera_3
then:
- switch.turn_on: camera_3_shutter_gpio_switch
##### Camera 4 Shutter
- platform: gpio
id: camera_4_shutter_gpio_switch
pin:
number: 21
inverted: True
on_turn_on:
then:
- delay: !lambda return id(camera_4_shutter_delay).state;
- switch.turn_off: camera_4_shutter_gpio_switch
- platform: template
name: Camera 4 Shutter Switch
id: camera_4_shutter_template_switch
# icon: mdi:
turn_on_action:
if:
condition:
binary_sensor.is_on: enable_camera_4
then:
- switch.turn_on: camera_4_shutter_gpio_switch
##### Camera 5 Shutter
- platform: gpio
id: camera_5_shutter_gpio_switch
pin:
number: 23
inverted: True
on_turn_on:
then:
- delay: !lambda return id(camera_5_shutter_delay).state;
- switch.turn_off: camera_5_shutter_gpio_switch
- platform: template
name: Camera 5 Shutter Switch
id: camera_5_shutter_template_switch
# icon: mdi:
turn_on_action:
if:
condition:
binary_sensor.is_on: enable_camera_5
then:
- switch.turn_on: camera_5_shutter_gpio_switch
##### Camera 5 Focus
- platform: gpio
id: camera_5_focus_gpio_switch
pin:
number: 22
inverted: True
on_turn_on:
then:
- delay: !lambda return id(camera_5_shutter_delay).state;
- switch.turn_off: camera_5_focus_gpio_switch
- platform: template
name: Camera 5 Focus Switch
id: camera_5_focus_template_switch
# icon: mdi:
turn_on_action:
if:
condition:
binary_sensor.is_on: enable_camera_5
then:
- switch.turn_on: camera_5_focus_gpio_switch
##################################################
##### Template Switches
##################################################
##### Stop Turntable Switch
- platform: template
name: "Stop Turntable Switch"
id: stop_turntable_template_switch
turn_on_action:
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
- switch.turn_off: switch_stepper_psu
- switch.turn_off: turntable_enable_switch
##### Manual Turntable Control
- platform: template
name: "Manual Turntable Control"
id: manual_turntable_control_template_switch
turn_on_action:
- switch.turn_on: switch_stepper_psu
- switch.turn_on: turntable_enable_switch
- delay: !lambda return id(start_delay_turntable).state * 1000;
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: !lambda return id(degrees_to_turn).state;
- stepper.set_speed:
id: turntable_stepper
speed: !lambda return id(rpm_turntable).state;
turn_off_action:
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
##### Auto Turntable Control
- platform: template
name: "Automatic Turntable Photogrammetry"
id: auto_turntable_photogrammetry_template_switch
turn_on_action:
- delay: !lambda return id(start_delay_turntable).state * 1000;
- script.execute: auto_turntable_photogrammetry_script
turn_off_action:
- script.stop: auto_turntable_photogrammetry_script
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
##### Snap All Photos
- platform: template
name: "Snap All Photos"
id: snap_all_photos_template_switch
turn_on_action:
- switch.turn_on: camera_1_shutter_template_switch
- switch.turn_on: camera_2_shutter_template_switch
- switch.turn_on: camera_3_shutter_template_switch
- switch.turn_on: camera_4_shutter_template_switch
- switch.turn_on: camera_5_shutter_template_switch
- platform: template
name: "Automatic 360 Turntable Photogrammetry"
id: auto_360_turntable_photogrammetry_template_switch
turn_on_action:
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
- stepper.set_speed:
id: turntable_stepper
speed: !lambda return id(rpm_turntable).state;
- delay: !lambda return id(start_delay_turntable).state * 1000;
- switch.turn_on: auto_360_turntable_photogrammetry_continue_template_switch
- lambda: 'id(turntable_current_position) = 0;'
turn_off_action:
# - script.stop: auto_turntable_photogrammetry_script
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
- platform: template
id: auto_360_turntable_photogrammetry_continue_template_switch
turn_on_action:
- switch.turn_on: snap_all_photos_template_switch
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
- delay: !lambda return id(take_photo_delay).state * 1000;
- lambda: 'id(turntable_current_position) = id(turntable_stepper).current_position;'
turn_off_action:
- stepper.report_position:
id: turntable_stepper
position: 0
- stepper.set_target:
id: turntable_stepper
target: 0
##################################################
##################################################
##### Scripts
##################################################
##################################################
script:
##### Auto Turntable Scripts
- id: auto_turntable_photogrammetry_script
then:
- stepper.report_position:
id: turntable_stepper
position: !lambda return id(degrees_to_turn).state;
- stepper.set_target:
id: turntable_stepper
target: !lambda return id(degrees_to_turn).state;
# target: !lambda return id(steps_to_turn_turntable).state * 132;
- stepper.set_speed:
id: turntable_stepper
speed: !lambda return id(rpm_turntable).state;
- lambda: 'id(turntable_current_position) = id(turntable_stepper).current_position;'
# - wait_until:
# lambda: 'return id(turntable_stepper).current_position == id(degrees_to_turn).state;'
# - delay: !lambda return id(delay_turntable).state * 1000;
- switch.turn_on: snap_all_photos_template_switch
- delay: !lambda return id(take_photo_delay).state * 1000;
- switch.turn_off: snap_all_photos_template_switch
- switch.turn_on: auto_turntable_photogrammetry_template_switch
##################################################
##################################################
##### Globals
##################################################
##################################################
globals:
##### ESP32 Sensors
##################################################
- id: stepspersecond_to_rpm_global
type: float
restore_value: no
initial_value: '0'
- id: turntable_current_position
type: float
restore_value: no
initial_value: '0'
- id: turntable_next_target_position
type: float
restore_value: no
initial_value: '0'
- id: turntable_final_position
type: float
restore_value: no
initial_value: '47500'
##################################################
##################################################
##### Sensors
##################################################
##################################################
sensor:
##### ESP32 Sensors
##################################################
##### Voltage
# - platform: adc
# pin: VCC
# name: "Turntable Voltage ESP32"
# update_interval: 30s
##### Wifi Signal
- platform: wifi_signal
name: "Turntable WiFi Signal ESP32"
update_interval: 30s
##### Uptime
- platform: uptime
name: "Turntable Uptime ESP32"
id: turntable_uptime_esp32
update_interval: 30s
##### Hall Effect
- platform: esp32_hall
name: "Turntable Hall Effect Sensor"
update_interval: 1s
##################################################
##### HASSIO Input Numbers
##################################################
#####
- platform: homeassistant
name: "steps_to_turn_turntable"
entity_id: input_number.steps_to_turn_box
id: steps_to_turn_turntable
#####
- platform: homeassistant
name: "delay_turntable"
entity_id: input_number.turntable_delay_box
id: delay_turntable
#####
- platform: homeassistant
name: "start_delay_turntable"
entity_id: input_number.turntable_start_delay_box
id: start_delay_turntable
#####
- platform: homeassistant
name: "rpm_turntable"
entity_id: sensor.turntable_rpm_sensor
id: rpm_turntable
#####
- platform: homeassistant
name: "pulses_per_revolution_stepper"
entity_id: input_number.pulses_per_revolution_stepper_box
id: pulses_per_revolution_stepper
#####
- platform: homeassistant
name: "steps_per_second_stepper"
entity_id: input_number.steps_per_second_stepper_box
id: steps_per_second_stepper
#####
- platform: homeassistant
name: "take_photo_delay"
entity_id: input_number.take_photo_delay_box
id: take_photo_delay
#####
- platform: homeassistant
name: "degrees_to_turn"
entity_id: sensor.turntable_degrees_to_turn
id: degrees_to_turn
##### Current Stepper Position
- platform: template
name: "Current Stepper Position"
id: stepper_position
lambda: return id(turntable_stepper).current_position;
update_interval: 1s
##### Current Stepper Position from global
- platform: template
name: "Current Stepper Position from global"
id: stepper_position_from_global
lambda: return id(turntable_current_position);
update_interval: 1s
##### Next Stepper Position from global
- platform: template
name: "Next Stepper Position from global"
id: next_stepper_position_from_global
lambda: return id(turntable_next_target_position);
update_interval: 1s
##### Camera 1 Shutter Delay
- platform: homeassistant
name: "Camera 1 Shutter Delay"
entity_id: input_number.camera_1_shutter_delay_box
id: camera_1_shutter_delay
##### Camera 2 Shutter Delay
- platform: homeassistant
name: "Camera 2 Shutter Delay"
entity_id: input_number.camera_2_shutter_delay_box
id: camera_2_shutter_delay
##### Camera 3 Shutter Delay
- platform: homeassistant
name: "Camera 3 Shutter Delay"
entity_id: input_number.camera_3_shutter_delay_box
id: camera_3_shutter_delay
##### Camera 4 Shutter Delay
- platform: homeassistant
name: "Camera 4 Shutter Delay"
entity_id: input_number.camera_4_shutter_delay_box
id: camera_4_shutter_delay
##### Camera 5 Shutter Delay
- platform: homeassistant
name: "Camera 5 Shutter Delay"
entity_id: input_number.camera_5_shutter_delay_box
id: camera_5_shutter_delay
##################################################
##################################################
##### Binary Sensors
##################################################
##################################################
binary_sensor:
##################################################
##### Stepper Sensor
##################################################
##### Stepper is moving / Has reached target
# - platform: template
# name: "Stepper reached next target"
# id: stepper_reached_next_target
# lambda: |-
# if (id(turntable_current_position).state < id(turntable_next_target_position)) {
# return true;
# } else {
# return false;
# }
##### Stepper reached final target
# - platform: template
# name: "Stepper reached final target"
# id: stepper_reached_final_target
# lambda: |-
# if (id(turntable_current_position).state < id(turntable_final_position)) {
# return true;
# } else {
# return false;
# }
##################################################
##### HassIO Binary Sensors
##################################################
##### Photogrammetry boolean
- platform: homeassistant
name: "Photogrammetry boolean HassIO"
entity_id: input_boolean.photogrammetry_boolean
##### Enable Caamera 1 boolean
- platform: homeassistant
name: "Enable Camera 1 boolean HassIO"
entity_id: input_boolean.enable_camera_1_boolean
id: enable_camera_1
##### Enable Caamera 2 boolean
- platform: homeassistant
name: "Enable Camera 2 boolean HassIO"
entity_id: input_boolean.enable_camera_2_boolean
id: enable_camera_2
##### Enable Caamera 3 boolean
- platform: homeassistant
name: "Enable Camera 3 boolean HassIO"
entity_id: input_boolean.enable_camera_3_boolean
id: enable_camera_3
##### Enable Caamera 4 boolean
- platform: homeassistant
name: "Enable Camera 4 boolean HassIO"
entity_id: input_boolean.enable_camera_4_boolean
id: enable_camera_4
##### Enable Caamera 5 boolean
- platform: homeassistant
name: "Enable Camera 5 boolean HassIO"
entity_id: input_boolean.enable_camera_5_boolean
id: enable_camera_5
##################################################
##################################################
##### Text Sensors
##################################################
##################################################
text_sensor:
#####
- platform: wifi_info
ip_address:
icon: "mdi:ip"
name: Turntable ESP32 IP Address
ssid:
name: Turntable ESP32 SSID
icon: "mdi:access-point-network"
bssid:
name: Turntable ESP32 BSSID
icon: "mdi:access-point-network"
- platform: version
name: "ESP32 Turntable ESPHome Version"
#####
- platform: template
name: "Turntable Uptime (formatted)"
lambda: |-
uint32_t dur = id(turntable_uptime_esp32).state;
int dys = 0;
int hrs = 0;
int mnts = 0;
if (dur > 86399) {
dys = trunc(dur / 86400);
dur = dur - (dys * 86400);
}
if (dur > 3599) {
hrs = trunc(dur / 3600);
dur = dur - (hrs * 3600);
}
if (dur > 59) {
mnts = trunc(dur / 60);
dur = dur - (mnts * 60);
}
char buffer[17];
sprintf(buffer, "%ud %02uh %02um %02us", dys, hrs, mnts, dur);
return {buffer};
icon: mdi:clock-start
update_interval: 30s
The cameras is phones/DSLR cameras triggered by relays with self made boards with resistors connected to the 3.5mm earphone jacks for shutter.
My Home Assistant code is as follows:
sensor:
########## TURNTABLE ##########
- platform: template
sensors:
turntable_pulses_per_revolution:
value_template: "{{ '%.0f'%(states('input_number.pulses_per_revolution_stepper_box') | float * 4.75) | float }}"
friendly_name: 'Turntable Pulses per Revolution'
# unit_of_measurement: 'Pulse/rev'
turntable_pulses_per_degree:
value_template: "{{ '%.0f'%(states('sensor.turntable_pulses_per_revolution') | float / 360) | float }}"
friendly_name: 'Turntable Pulses per Degree'
turntable_degrees_to_turn:
value_template: "{{ '%.0f'%((states.input_number.turntable_turn_degrees.state | float) *
(states.sensor.turntable_pulses_per_degree.state | float)) | float }}"
friendly_name: 'Turntable Degrees to Turn'
turntable_rpm_sensor:
value_template: "{{ '%.0f'%((states.input_number.turntable_rpm.state | float) / 60 *
(states.sensor.turntable_pulses_per_revolution.state | float)) | float }}"
friendly_name: 'Turntable RPM Sensor'
###############################################################################
########## INPUT BOOLEANS ##########
input_boolean:
photogrammetry_boolean:
name: Snap All Photos Boolean
initial: off
enable_camera_1_boolean:
name: Enable Camera 1 Boolean
initial: off
icon: mdi:camera
enable_camera_2_boolean:
name: Enable Camera 2 Boolean
initial: off
icon: mdi:camera
enable_camera_3_boolean:
name: Enable Camera 3 Boolean
initial: off
icon: mdi:camera
enable_camera_4_boolean:
name: Enable Camera 4 Boolean
initial: off
icon: mdi:camera
enable_camera_5_boolean:
name: Enable Camera 5 Boolean
initial: off
icon: mdi:camera
###############################################################################
#################### INPUT NUMBERS ####################
input_number:
########## TURNTABLE STEPPER INPUT NUMBERS ##########
# turntable_stepper_control_slider:
# name: "Turntable Stepper Control Slider"
# initial: 0
# min: -15224
# max: 15224
# step: 1
# mode: slider
steps_to_turn_box:
name: "Turntable Steps to Turn Box"
initial: 0
min: -9999999
max: 9999999
step: 1
mode: box
turntable_delay_box:
name: "Turntable Delay Box"
initial: 0
min: 0
max: 9999999
step: 1
mode: box
turntable_start_delay_box:
name: "Turntable Start Delay Box"
initial: 0
min: 0
max: 9999999
step: 1
mode: box
turntable_rpm:
name: "Turntable RPM"
initial: 0
min: 0
max: 5000
step: 1
mode: box
pulses_per_revolution_stepper_box:
name: "Stepper Driver Pulses per Revolution Box"
initial: 10000
min: 400
max: 50000
step: 1
mode: box
turntable_turn_degrees:
name: "Turtable turn degrees Box"
initial: 10
min: -720
max: 720
step: 1
mode: box
turntable_nr_of_photos_per_revolution:
name: "Turtable number of photos per revolution Box"
initial: 0
min: 0
max: 360
step: 1
mode: box
steps_per_second_stepper_box:
name: "Turntable Steps per Second Box"
initial: 0
min: 0
max: 30000
step: 1
mode: box
kinect_scan_nr_of_turns_box:
name: "Turntable Number of Turns Box"
initial: 0
min: 0
max: 100
step: 1
mode: box
take_photo_delay_box:
name: "Turntable Take Photo Delay"
initial: 0
min: 0
max: 9999999
step: 1
mode: box
send_photos_every_box:
name: "Send Photos every amount of minutes"
initial: 60
min: 0
max: 9999
step: 1
mode: box
camera_1_shutter_delay_box:
name: "Camera 1 Shutter Delay"
initial: 50
min: 0
max: 9999999
step: 1
mode: box
camera_2_shutter_delay_box:
name: "Camera 2 Shutter Delay"
initial: 50
min: 0
max: 9999999
step: 1
mode: box
camera_3_shutter_delay_box:
name: "Camera 3 Shutter Delay"
initial: 50
min: 0
max: 9999999
step: 1
mode: box
camera_4_shutter_delay_box:
name: "Camera 4 Shutter Delay"
initial: 50
min: 0
max: 9999999
step: 1
mode: box
camera_5_shutter_delay_box:
name: "Camera 5 Shutter Delay"
initial: 50
min: 0
max: 9999999
step: 1
mode: box
Technical Details:
HassOS 2.12 on Virtual Machine
HomeAssistant 0.101.2
ESP32 DevKit V1
Stepper Driver: Wantai DQ860MA Microstepping Driver
8ch Relay board with Octocouplers
220V Led Lights for photogrammetry (1 relay switches on all lights)