As a first project into micro controllers, I looked at converting a manual sit stand desk into one powered by a motor, controlled over WiFi MQTT commands.
The original desk had no electronics and could only manually be “wound” up and down with a handle. Looking for a first project into micro controllers and coding I thought this might be perfect. Searching online for some inspiration, others either hacked the Ikea motorised desk or added motors with a manual push button. I wanted focus more on the software side and the ability to control it through multiple methods because, why not?
The basic idea I started with was a motor controller, connected to a dc motor that would be controlled through an Arduino. What I ended up with is an ESP32 controlling a 2006 BMW electric window motor through a touch screen panel running home automation software. Its been a fun first project to say the least.
Physics not being my strong point, I initially thought I could get away with using a small worm geared motor I found on Aliexpress. I quickly realised the part was severely under powered.
After ordering a LM298 motor driver and the original under powered motor, I realised I needed to find a way of connecting the motor and the hollow shaft of the desk. I had recently ordered an Ender 3 3D printer and thought this would be a good opportunity to learn how to do some basic CAD work.
The final parts i ended up with are as follows, you can jump to the code or read on for the whys.
- End stops
- Boost Buck Converter XL6009
- DC12V 10A 120W Switching Power Supply
- 5A DC Motor Driver Board
- ESP32 Development Board
- Sit Stand Desk
Non suitable Hardware
My initial designs incorporated printing the hex shaft to replace the original handle of the desk. But I quickly realised 3d printing isn’t strong enough for the angles and forces required. The shaft design would fail upon testing. Back to the drawing board.
Looking online i came across several mentions of car window and car wiper motors having high torque. So I made my way down to the local wreckers. Most electric window motors had either a 7 tooth or 30+ tooth configuration. After having trouble designing for the 7 tooth configuration, I ended up with a 32 tooth 2006 BMW electric window. Part # 676283620660.
Using the FCGEAR plugin on Freecad, I designed a suitable connector that would sit on the cog of the motor and a hex shaft. I found designing it over 2 parts enabled me to strengthen parts internally, then using Cura I merged the 2 parts into 1 and printed them that way.
To fix the shaft snapping problem, I reversed the thought process and rather than printing the shaft, went to the local hardware store and purchased a 5.5mm hex key, cut the bending handle end off and designed the connector to have the 32 teeth on one end and the 5.5mm hex female shaft on the other. Put it all together with a 12v laptop charger for testing and the desk went up! To hold it all together I designed a case to hold the power supply and electronics that could be screwed to the desk.
To see what kind of motor controller i needed I measured the amps pulled by the motor under load. Pushing the weight of 2 24″ monitors a laptop, speakers and other stuff on the desk, the motor peaked around 4.5 Amps. Having all the information i needed for the hardware, I went to Aliexpress, ordered a 5Amp motor controller, 12V power supply, Buck converter and an ESP32.
When it came to the software, the initial idea was to have an up down button. That became how can i add useless IOT to this? Which resulted in a wifi connected, MQTT, home automation controlled, motorised desk.
The software was built using the Pubsub client library for MQTT integration. Initially it was coded around receiving a payload in the form of “x, yyyy”. Where x is a number between 1 and 4 giving a direction (up, down, top, bottom) yyyy was equal to milliseconds. So 1,2000 would make the desk go up for 2 seconds. 3, 0000 would send the desk to the “top” position.
Adding a switch in Home Assistant would send a payload to the inTopic for sending the desk to the “Top” or “Bottom” position. But there was no feedback for in between. To remedy this I wanted to add visual feedback on Home Assistant in the form of a slider, this would show in real time what percentage the desk was currently at. As feature creep kept piling up, I now looked at adding percentage input via MQTT too. As a result, in addition to accepting the payload format of <1, 1000> , it also accepted the format of <6, 78> . 6 notifying that it is a percentage payload and the 78 requesting the desk be moved to 78% of the total height. This meant a change of logic and a rewrite of the code. It introduced a bug in which every millisecond as the code looped going up or down, it resulted in thousands of MQTT messages being sent. The server could handle it but it was pointless spam. So fixed this by only updating every second, 15 seconds of motor time now equals 15 messages rather than 15 000.
Another problem to solve was timing top and bottom with 0, 1 or 2 end stops. The premise for “Top” and “Bottom” was initially going to be manually timed. Physically timing the motor cycling through bottom to top, then hard code that time in. But I had recently pulled an end stop off of the 3d printer to add auto bed leveling and decided to try adding in end stops to the project. I placed one at the bottom and designed an end stop holder of sorts in Freecad. I couldn’t place one at the top of the desk due to the desks design, but have left a variable in the code so it can be added in if your desk allows it.
Currently a maximum cycle time is still put in as a backup but at boot the desk cycles from bottom end stop to top, unless maxMotorTime is hit. It then stores this as cycleTime in EEPROM memory. This allows it to restore from power loss in non volatile memory of the ESP32. As part of the boot cycle, the desk sends out its last position through MQTT .
All in all its been a great first project and im already looking at the next project which will be a Nest style heating\ cooling controller.
- Add an LCD screen to display percentage
- Add 4 buttons similar to IKEA desk, up, down, memory 1 memory 2
- Change from Pubsubclient to another library to add in https\TLS for MQTT
- Add MySQL or SQlite integration for set hour reminders to stand