116 lines
6.6 KiB
ReStructuredText
116 lines
6.6 KiB
ReStructuredText
|
Neighbor's Water Heater Automation (part 1)
|
||
|
###########################################
|
||
|
:author: tyrel
|
||
|
:category: Automation
|
||
|
:tags: automation, c++, esp8266, servo, stepper
|
||
|
:status: published
|
||
|
|
||
|
The Setting
|
||
|
~~~~~~~~~~~
|
||
|
|
||
|
My neighbor has a Bosch tankless water heater he put in last year.
|
||
|
This water heater has one slight problem that when the power even blips a single second, it gets set back to its lowest temperature of 95°F.
|
||
|
My neighbor (we'll call him Frank for this post because Frank Tank is funny) Frank wants to set his heater to 120°F in his house.
|
||
|
The problem arises in that his water heater is under the house in his crawl space.
|
||
|
|
||
|
Without an easy way to set his temperature, he needs to crawl under his crawl space and turn a dial *EVERY. SINGLE. TIME.*
|
||
|
|
||
|
He asked me if I knew of anything off the shelf that would help.
|
||
|
I did not.
|
||
|
So I said the only logical thing someone `like me <https://tyrel.website/wiki/HomeAssistant>`_ would have done.
|
||
|
"I can totally automate that!"
|
||
|
|
||
|
The Lay Of The Land
|
||
|
~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
He has a `Bosch Tronic 6000C <https://www.prowaterheatersupply.com/PDFS/Bosch_Tronic_6000C_Pro_WH27_WH17_Installation_Manual.pdf>`_, with what appears to be a rotary encoder knob to set the temperature.
|
||
|
I only spent a few minutes under his house while planning this and didn't think to any measuring of how many detents to rotate, or how long the dial took to rotate to 120°F, so my first pass of this project is done with estimations.
|
||
|
|
||
|
.. figure:: {static}/images/2022/11/04_heater.png
|
||
|
:alt: bosch heater with a temperature 7 segment LED set to 120F
|
||
|
:width: 920px
|
||
|
|
||
|
|
||
|
Project Time - Round 1!
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
I have a few random servos laying around, and an NodeMCU ESP8266 module.
|
||
|
I figure these would be the perfect solution! ... note: was half right...
|
||
|
|
||
|
I found some code online by `Kumar Aditya <https://github.com/kumaraditya303>`_ that is for the `two items in my current parts list <https://github.com/kumaraditya303/ESP8266_SERVO_CONTROLLER>`_ (ESP8266 and SG90)
|
||
|
|
||
|
The Original code runs a web server on port 80, and runs a web page with some jQuery (wow it's been a while) to change the angle of the servo.
|
||
|
I realized this wasn't what I needed because my servos could only go 180° and I might need to go multiple rotations.
|
||
|
I found a youtube video on how to make a `SG90 run infinite in either direction <https://www.youtube.com/watch?v=zZGkkzMBL28>`_, so I did those modifications.
|
||
|
I then modified the front end code a little bit.
|
||
|
|
||
|
The new code on the back end was actually exactly the same, even though the effect was slightly different.
|
||
|
It would run on port 80, listen at ``/`` and ``/angle``, but the angle here was more of direction and speed (a vector?).
|
||
|
The way the servo was built, 160° was "Stop", higher than that was rotate clockwise, lower was rotate counter clockwise.
|
||
|
|
||
|
I put three buttons on my page that would be "Lower" (150), "STOP" (160), and "Higher" (170).
|
||
|
I then did some standard debouncing and disabling of buttons using setTimeout and such.
|
||
|
|
||
|
For a final touch I added in a range slider for "Time".
|
||
|
This held how many seconds after pressing Higher or Lower, that I would send the STOP command again.
|
||
|
|
||
|
This seemed to work relatively well, but I figure I should just use a stepper motor if I was attempting to emulate one this way.
|
||
|
I dug around in my closet and was able to find some parts.
|
||
|
|
||
|
.. figure:: {static}/images/2022/11/04_servo.png
|
||
|
:alt: blue case servo with a white arm, cables running off screen. sitting on a desk.
|
||
|
|
||
|
Project Time - Round 2!
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
I was able to rummage up a `28BYJ-48 <https://components101.com/motors/28byj-48-stepper-motor>`_ stepper with control board, and a `HW-131 power module <https://www.cafago.com/en/p-e8575.html>`_.
|
||
|
|
||
|
With these I needed a new library so I stripped the c++ code down to its basics, just getting me a server with the index page for the first pass.
|
||
|
|
||
|
On the Javascript side of things, I then decided I would add a temperature slider, from 90° to 120° (which writing this realize it should be from 95°... git commit...) with a confirmation button, and a small button to initialize down to 95°.
|
||
|
|
||
|
The initialize button would need to trigger an initialization where I rotate counter clockwise an appropriate amount of time (Length TBD) in order to force the rotary encoder dial to always start at a known state of 95.
|
||
|
The green submit button sends the new desired temperature as a post.
|
||
|
|
||
|
Server side, I was using a library called `AccelStepper <https://www.airspayce.com/mikem/arduino/AccelStepper/>`_.
|
||
|
This I set some made up max speeds and steps per rotation, actual values TBD.
|
||
|
|
||
|
I added an endpoint called ``/setTemperature`` that takes in a temperature and sets a local temperature variable.
|
||
|
From there, I calculate the temperature less 95, to find out how many degrees I need to increase by, for now I'm considering this rotations.
|
||
|
|
||
|
I then apply a multiplier (TBD also... there's a lot of these as you can see!) and call ``stepper.moveTo()`` and it actually feels like it's pretty accurate.
|
||
|
|
||
|
The endpoint ``/initialize`` runs ``stepper.moveTo`` with ten rotations CCW, and then resets the "known location" back to zero (this also runs on power on for now).
|
||
|
|
||
|
|
||
|
.. figure:: {static}/images/2022/11/04_webpage.png
|
||
|
:alt: webpage controls, title "Water Heater Control", a blue slider with a green button saying "Set Temperature: 90", and red "Initialize to 90" button
|
||
|
:width: 920px
|
||
|
|
||
|
|
||
|
.. figure:: {static}/images/2022/11/04_stepper.png
|
||
|
:alt: blue case servo with a white arm, cables running off screen. sitting on a desk.
|
||
|
:width: 920px
|
||
|
|
||
|
In Action
|
||
|
~~~~~~~~~
|
||
|
|
||
|
The result of this second round of coding is a lot more that I expect to happen once I can finally get down beneath his house.
|
||
|
Frank will lose power, his water heater will reset to 95°F, the NodeMCU will reboot, and reinitialize itself.
|
||
|
Frank will then open his browser to the NodeMCU's server, set the desired temperature, and take warm showers.
|
||
|
|
||
|
Version 2 will come once I actually test EVERYTHING.
|
||
|
My first quesiton is if a rubber band on a lego tire with a servo wheel adaptor (`which I 3d modeled and printed... <https://www.thingiverse.com/thing:5594405>`_) will work sufficiently.
|
||
|
Programming wise, I need to figure out how many steps is one degree. Is the rotary encoder one degree per detent? Is it a constant speed? Is it like an alarm clock where you can sometimes jump by 10?
|
||
|
|
||
|
Stay tuned to find out the exciting conclusion once I can go down below Frank's house.
|
||
|
|
||
|
.. figure:: {static}/images/2022/11/04_stepper_wheel.png
|
||
|
:alt: blue case servo with a white arm, cables running off screen. sitting on a desk.
|
||
|
:width: 920px
|
||
|
|
||
|
Code
|
||
|
~~~~
|
||
|
|
||
|
The code is currently at https://gitea.tyrel.dev/tyrel/frank_tank.git
|