Baco
Published © LGPL

Control sit/stand Desk height with a touch screen

Control IKEA Bekant Desk sit/stand height with M5Stack Core2 using two Relay units and a ToF (time-of-flight sensor VL53L0x) unit.

IntermediateWork in progress4 hours4,576
Control sit/stand Desk height with a touch screen

Things used in this project

Hardware components

M5Stack Core2 ESP32 IoT Development Kit
M5Stack Core2 ESP32 IoT Development Kit
×1
Mini 3A Relay Unit
M5Stack Mini 3A Relay Unit
×2
Time-of-Flight (ToF) VL53L0X Laser Ranging Unit (MCP4725/)
M5Stack Time-of-Flight (ToF) VL53L0X Laser Ranging Unit (MCP4725/)
×1
IKEA BEKANT Desk sit/stand
https://www.ikea.com/ch/en/cat/bekant-desk-underframes-18965/ 902.552.52 (Underframe sit/stand f table tp, el, white120x80 cm) https://www.ikea.com/ch/en/assembly_instructions/bekant-underframe-sit-stand-f-table-tp-el-white__AA-1006070-9_pub.pdf 302.552.50 (Underframe sit/stand f table tp, el120x80 cm) https://www.ikea.com/ch/en/assembly_instructions/bekant-underframe-sit-stand-f-table-tp-el__AA-1006070-9_pub.pdf
×1
IKEA BEKANT Table top
×1
3M Double Sided Foam Adhesive Pads
To attach Time-of-Flight Distance Ranging Sensor under the desk
×1
Jumper wires (generic)
Jumper wires (generic)
Make <=> Make (to attach to relays), Male <=> Female (to extend)
×1
Test Probe Connector, Hook
Test Probe Connector, Hook
Test Clamp Wire Hook Test Clip (usually for Logic Analyzer) but used to hook to original two button backplane circuit
×3
M5GO/FIRE Battery Bottom
M5Stack M5GO/FIRE Battery Bottom
N.B. You need the Bottom2 M5GO Battery Bottom2 for Core2 to add port B and C for Relay https://docs.m5stack.com/#/en/base/m5go_bottom2
×1

Software apps and online services

M5Stack UIFlow

Hand tools and fabrication machines

Multitool, Screwdriver
Multitool, Screwdriver
Used to break into the ABS enclosure of the original IKEA control (138684) also used for the 3.96 socket part of Relay M5Unit (Mini 3A Relay Unit) Part of iFixit's Pro Tech Toolkit
Metal Spudger
Used to break into the ABS enclosure of the original IKEA control (138684) Part of iFixit's Pro Tech Toolkit
Halberd Spudger
Used to break into the ABS enclosure of the original IKEA control (138684) Part of iFixit's Pro Tech Toolkit
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Schematics

M5Stack UiFlow Blocky

Using M5Stack UiFlow v1.7.4 for M5stack Core2 connected to two Relay M5Units (ports B + C) and one ToF M5Units (port A)

M5Stack UiFlow Blocky Code

Using M5Stack UiFlow v1.7.4 for M5stack- Core2 connected to two Relay M5Units (ports B + C) and one ToF M5Units (port A)

Code

M5Stack Python Code

Python
Using M5Stack UiFlow v1.7.4 for M5stack- Core2 connected to two Relay M5Units (ports B + C) and one ToF M5Units (port A)
from m5stack import *
from m5stack_ui import *
from uiflow import *
import time
import unit

screen = M5Screen()
screen.clean_screen()
screen.set_screen_bg_color(0x000000)
relay0 = unit.get(unit.RELAY, unit.PORTB)
relay1 = unit.get(unit.RELAY, unit.PORTC)
tof0 = unit.get(unit.TOF, unit.PORTA)


m = None
height = None
m1 = None
target = None
m2 = None
m3 = None
m4 = None
m5 = None
m6 = None
offset = None


height_lbl = M5Label('0', x=151, y=153, color=0x00ff00, font=FONT_MONT_26, parent=None)
bar0 = M5Bar(x=10, y=189, w=300, h=12, min=65, max=115, bg_c=0x707070, color=0x00ff00, parent=None)
label1 = M5Label('-', x=63, y=208, color=0x00ff00, font=FONT_MONT_32, parent=None)
label2 = M5Label('+', x=239, y=208, color=0x00f000, font=FONT_MONT_32, parent=None)
label3 = M5Label('M', x=152, y=210, color=0x00ff00, font=FONT_MONT_20, parent=None)
m1_btn = M5Btn(text='M1', x=35, y=27, w=70, h=30, bg_c=0x000000, text_c=0x00ff00, font=FONT_MONT_24, parent=None)
m2_btn = M5Btn(text='M2', x=125, y=27, w=70, h=30, bg_c=0x000000, text_c=0x00ff00, font=FONT_MONT_24, parent=None)
m3_btn = M5Btn(text='M3', x=214, y=27, w=70, h=30, bg_c=0x000000, text_c=0x00ff00, font=FONT_MONT_24, parent=None)
m4_btn = M5Btn(text='M4', x=35, y=98, w=70, h=30, bg_c=0x000000, text_c=0x00ff00, font=FONT_MONT_24, parent=None)
m5_btn = M5Btn(text='M5', x=125, y=98, w=70, h=30, bg_c=0x000000, text_c=0x00ff00, font=FONT_MONT_24, parent=None)
m6_btn = M5Btn(text='M6', x=214, y=98, w=70, h=30, bg_c=0x000000, text_c=0x00ff00, font=FONT_MONT_24, parent=None)

from numbers import Number


# Describe this function...
def up():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  relay0.on()
  relay1.off()

# Describe this function...
def down():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  relay0.on()
  relay1.on()

# Describe this function...
def stop():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  relay0.off()
  relay1.off()

# Describe this function...
def init():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  m = 0
  m1 = 65
  m2 = 75
  m3 = 85
  m4 = 95
  m5 = 105
  m6 = 115
  target = 0
  offset = 2

# Describe this function...
def refresh():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  height = int(((tof0.distance) / 10))
  height = (height if isinstance(height, Number) else 0) + offset
  bar0.set_value(height)
  height_lbl.set_text(str(height))
  m1_btn.set_btn_text(str(m1))
  m2_btn.set_btn_text(str(m2))
  m3_btn.set_btn_text(str(m3))
  m4_btn.set_btn_text(str(m4))
  m5_btn.set_btn_text(str(m5))
  m6_btn.set_btn_text(str(m6))


def m1_btn_pressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  if m != 0:
    m1 = m
    m = 0
  else:
    target = m1
  pass
m1_btn.pressed(m1_btn_pressed)

def m2_btn_pressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  if m != 0:
    m2 = m
    m = 0
  else:
    target = m2
  pass
m2_btn.pressed(m2_btn_pressed)

def m3_btn_pressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  if m != 0:
    m3 = m
    m = 0
  else:
    target = m3
  pass
m3_btn.pressed(m3_btn_pressed)

def m4_btn_pressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  if m != 0:
    m4 = m
    m = 0
  else:
    target = m4
  pass
m4_btn.pressed(m4_btn_pressed)

def m5_btn_pressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  if m != 0:
    m5 = m
    m = 0
  else:
    target = m5
  pass
m5_btn.pressed(m5_btn_pressed)

def m6_btn_pressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  if m != 0:
    m6 = m
    m = 0
  else:
    target = m6
  pass
m6_btn.pressed(m6_btn_pressed)

def buttonA_wasPressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  down()
  pass
btnA.wasPressed(buttonA_wasPressed)

def buttonC_wasPressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  up()
  pass
btnC.wasPressed(buttonC_wasPressed)

def buttonB_wasPressed():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  m = height
  pass
btnB.wasPressed(buttonB_wasPressed)

def buttonA_wasReleased():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  stop()
  target = 0
  pass
btnA.wasReleased(buttonA_wasReleased)

def buttonC_wasReleased():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  stop()
  target = 0
  pass
btnC.wasReleased(buttonC_wasReleased)

def buttonB_wasReleased():
  global m, height, m1, target, m2, m3, m4, m5, m6, offset
  stop()
  target = 0
  pass
btnB.wasReleased(buttonB_wasReleased)


init()
while True:
  refresh()
  if target == 0:
    pass
  elif height < target:
    up()
  elif height > target:
    down()
  else:
    stop()
    target = 0
  wait_ms(100)
  wait_ms(2)

Credits

Baco

Baco

2 projects • 3 followers

Comments