Close
0%
0%

Heating Controller

Tempted to call this FrankenHeatController or something, but this time round doing it a little bit better.

Similar projects worth following
Don't want to hack inside my Single Channel Boiler TimeSwitch, so I'm doing it the horrible way and using a Raspi Zero W to drive a Servo to physically push the 'Boost' button on my heating controller when needed.
That way I can forego all the functions of the TimeSwitch and pass all time duties on to the Pi, or manual on-off, for control over the Web or via Alexa.

For a while now I've wanted to be able to control my heating from the web, or even control it with Amazon Alexa. This is my attempt at it.

Hardware overview- 

  • Raspberry Pi Zero W
  • 5v Hobby Servo motor
  • Breakout board for MOSFET

Whilst the pi may be considered a bit overkill, I do want it to be 'smart' controlled, so can't make do with a PIC or Arduino. I do have a Pi Pico, but this doesn't have a network stack or supporting peripherals.

The Pi will be a normal LAMP stack device, running a small script that can be triggered to move the servo motor. 

The idea being that my heating timeswitch has a BOOST button. This button works regardless of the scheduling mode the unit is in, be it on OFF mode, or on come on once, or come on twice. Boost gives you 1hr of heating, then turns off the boiler, you can press it 3 times to get 3 hours. 

So I don't want to mash up and tear apart my relatively new timeswitch controller, as is usual we want to be as non-invasive as possible, and I'm definitely not up to the challenge of hooking directly into the boiler relay to turn it on - I want this timeswitch available for all other functions, eg having the heating come on on a schedule if required.

At the moment (autumn) it's that time of year I'm always turning the heating on and off (house-wide thermostats are pointless) as the outside temperature fluctuates wildly, so being able to do it without going into the boiler cupboard and fumbling around, this seems a far better proposition.

To achieve this, we'll be driving a servo motor from the Pi. The servo is positioned to be able to press the button with the swing of a servo arm. To soften any impact and prevent any switch damage occurring, I'll spring-load the end of the actuator arm.

Also I noted during experimentation that even if you tell the servo to unpower the servo arm, it still drains upwards of 50-100mA so to prevent wasted energy we'll use an N channel MOSFET to switch servo power on and off. The Pi is surprisingly low-powered, with 0.1 watt measured.

So the servo stays unpowered in it's 'home' position. When instructed, the arm will rapidly move to hover over the boost button, then slowly move down to actuate the button, immediately release, then rapid-move to the home position again. This keeps the arm well out of the way and allows me to press the buttons when I want to manually.

That's the overview covered.

  • Software and code

    h3liosphan11/22/2021 at 01:17 0 comments

    So it's just a straight forward Pi OS Lite deploy onto a 16GB uSD card, configured totally headless, so ssh and WiFi configs put on the boot partition, apt upgraded, then the pi user removed, and my own substituted with sudo access.

    Lighttpd and Python 2.7.16, plus web CGI tie-ins were installed.

    I had already PoC'd the code in Python using a pi, so it was a case of moving this to the 'production' pi and adapting it for 'the web',

    Here's the web page - 

    Some may recognise the 'theme', this is a dark Bootstrap theme, which goes a very long way towards making it look semi-professional and not all web 1.0. This also goes a long way towards making it useable across a wide variety of devices and screen sizes - this appears perfectly sized on my Android Phone, Windows PC, Surface Tablet and Android Tablets.

    This is in stark contrast to the web 1.0 pages I made for my LED Hat project, which were a pain to use on a phone.

    The menus don't work, the search bar is there but not implemented at all, not needed, but left there to make it cooool.

    The 4 buttons are pretty self explanatory - 

    • TEST will move the servo fast, then slow, but will not press down on the heating button.
    • As mentioned you can boost up to 3 times for a 3 hour heating 'boost', then it turns off the heating, so each one of the buttons just executes the same bit of servo movement code as many times as you choose. 

    Each button is hard coded into index.html - 

    <main class="container">
      <div class="bg-dark p-5 rounded">
        <h1 class="text-light bg-dark">Boost</h1>
        <a class="btn btn-lg btn-primary" href="cgi-bin/servo-once.py" role="button"
    >once</a>
        <a class="btn btn-lg btn-primary" href="cgi-bin/servo-twice.py" role="button
    ">twice</a>
        <a class="btn btn-lg btn-primary" href="cgi-bin/servo-thrice.py" role="butto
    n">thrice</a>
        <a class="btn btn-lg btn-primary" href="cgi-bin/servo-test.py" role="button"
    >TEST</a>
      </div>
    </main>
    

    And here's the servo-once.py file (Apologies, the code highlighting for Python doesn't seem to work, not even if I remove the HTML at the bottom, or the #! declaration at the top) -

    #!/usr/bin/python
    from gpiozero import Servo, LED
    from time import sleep
    
    from gpiozero.pins.pigpio import PiGPIOFactory
    
    import cgi
    
    factory = PiGPIOFactory()
    
    servo = Servo(14, min_pulse_width=0.50/1000, max_pulse_width=2.5/1000, pin_facto
    ry=factory)
    mosfet = LED(15, active_high=True, initial_value=False, pin_factory=factory)
    
    homepos = -0.05
    hoverover = -0.9
    press = -0.98
    
    servo.value = homepos
    mosfet.on()
    sleep(0.3)
    
    servo.value = homepos
    
    x = hoverover
    
    while x >= press:
            servo.value = x
            sleep(0.01)
            x -= 0.001
    
    while x < hoverover:
            servo.value = x
            sleep(0.01)
            x += 0.001
    
    servo.value = homepos
    sleep(1)
    
    mosfet.off()
    #servo.value = None
    
    print("Content-Type: text/html\n\n")  # html markup follows
    print("<html><head></head><body><script>window.history.back();</script></body></
    html>")
    

    So as you can see the code uses the PiGPIOFactory component to activate the MOSFET to power the servo and actually move the servo. The pigpio daemon is running to allow the lighttpd user to access the gpio ports without running as root / su. The code therefore runs as www-data (or whatever user the sub-component activates from cgi-bin).

    There are two phases to the motion, it rapidly moves down to a 'hover' point, then slowly moves the arm down further to press the button, doing this in a while loop, it then reverses this back to the hover point, then back home. It then powers the Servo down again. Delays are inserted to give the servo time to move to that position, and to control the speed of the slow movement.

    Trial and error is all that determined the homepos, hoverover and press values hard-coded above.

    At the end is a small HTTP injection to return to the previous page so browsers don't freeze and get all confused! As you can see, it's just some javascript to go back a page.

    You may notice the #servo.value = None...

    Read more »

  • Finishing off the major design

    h3liosphan11/22/2021 at 00:36 0 comments

    The 4 finalisation steps have been completed - 

    • Actuator arm, see photo, this is now attached, and allows full articulation of the arm down to the button - it's lined up spot on, thereby justifying the use of CAD drawings and roughing out existing kit inside the CAD software. I didn't bother putting a spring loaded pusher element on the end, rather settling on a softly rounded touch point - I thought about applying some rubber for grip but this is completely unnecessary - I don't think there's any real benefit using a spring, as the Servo was finely controlled not to crush the switch down too hard.
    • Develop software stack - talk about this later in another build log.
    • As for securely attaching it to the heating controller - this is where I fouled up a little and excluded some quite important details from the CAD drawings and design stage (further design discipline needed!) - it all needed to be secured from behind so the arm can press against the button and isn't just lifting itself off the button. I ended up roughing out some clear acrylic stolen from an old computer monitor, the diffusion screen I think (not pictured because it's a travesty of a mount). It was very (badly) roughly cut to the size of both the timeswitch and heating controller, width wise, and the full height. I only then realised that all the wires from the timeswitch need to come out the back to the boiler. So I hacked a hole in the acrylic. This worked out okay because it also gives the timeswitch a nice base, a gap for the wires to protrude, and the wires (being secured to a plastic back plate that's supposed to be screwed to the wall)  hold the timer in position nicely, at least stopping the unit from sliding downwards. I also screwed the heating controller box to the Acrylic, thereby preventing any movement of the black box, allowing the arm to press without moving.
    • Fine tuning was done by hand by tweaking the Servo reach in the python code. 

    So it has been in operation now for a few weeks, has so far worked flawlessly. I'm actually really happy with it, it's amazing having the ability to wake up to a cold house and turn the heating on via a tablet or a phone whilst still in bed, then waiting a bit for the house to warm up - a real boon - likewise when returning home and I don't have the timer schedule on, I can turn the heating on without having to go all the way to my boiler cabinet. Nice!

    For whatever reason my WiFi isn't all that stable, sometimes dying after many weeks / months of normal operation, requiring a reset of the broadband router. There has been one or two instances of this happening during the testing phase, and the Pi Zero has successfully reconnected when I've needed to reset the router, and it has done so without intervention, which is great. I've also not needed to reset the Pi for any reason.

    All in all, very rewarding in build and in practicality!

    .

    .

    .

    I have expansion plans. Scope creep if you will. I realised it'd be great to know if the boiler was on or off - I can't hear that the heating is on most of the time so I won't know if the house will begin to cool down after the boost mode expires. I could get the Pi to count up 1, 2 or 3 hours but this is the 21st century, lazy!

    See that white LED on the timeswitch above, that is only on when the heating is on. I have plans to implement a simple light sensor using an LDR and a capacitor (no ADC necessary). This is for the next log as it's not done yet, meanwhile here's a sneak peek inside Fusion360 for the design of this element - 

    And here's the (already tested on another Pi) circuit diagram - 

    The astute reader will realise this is an RC (divider?) circuit that the Pi uses to charge up, then measures the discharge time of the cap - due to the varying resistance (light levels), the discharge time will change, and is detectable in software.

    I'm getting ahead of myself.....

  • Physical design and print

    h3liosphan10/25/2021 at 21:48 0 comments

    So basically I'm terrible at designing housings for my electronic creations - things change mid project, the housing ends up being sub-optimal to outright disruptive - check out my FrankenFlight controller to see an example.

    So this time round I decided to go the whole hog with Fusion 360 and mock it up in its virtual entirety. The 1st pic in the gallery is an indication of this. Leave NO stone unturned in your pursuit of modelling everything to reveal any fitment issues prior to 3d printing - and I think it paid off this time!

    This is the heating controller body, bits of importance only - the black oblong is the boost button as measured - this is all from actual measurements.

    This is the servo positioned accordingly to line up with the boost button - 

    Now the other bits are put in place, while positioning them I thought about wall clearance distances too.

    This is the Raspberry Pi, as lifted from their own specs PDF sheet, really handy!

    The board on the top left is the MOSFET breakout board (see future project log for details on this). This is to scale, but I've only boxed out the areas, the big block in the middle is just the protruding MOSFET package, very roughly scaled up to help avoid any interference.

    I use different design files for each component, then create a main design project drawing and bring them in by just dragging them in from the project drawer on the left. This has the advantage that you can open the original drawing again, make changes, then update them on the main design drawing.

    I position them roughly as required and adjust to fit.

    After that I just box up the whole case around these components, also putting mounting points in place for the bits. For this I see zero reason to make it a design masterpiece, even a black oblong can be suitable and pretty attractive for something like this - didn't even use the bevel / fillet tool once!

    And here's the lid - 

    Here you can see the slot for the USB cable to power the Pi, servo and everything - leave no stone unturned!

    And this is everything in place -

    It really helps to have done a lot of 3D printing as I have, and learned the various challenges printing such a model. Things to consider - 

    • Can the printer print overhangs effectively, how long an overhang can it manage? 3D printers do not (successfully) print in mid-air!
    • Post and hole dimensioning so they come out correctly the right size (holes tend to shrink due to plastic shrinkage and posts are really awkward, can easily be done too wide, with lots of stringing with the wrong temps and retraction settings. Aim to model gaps of 0.3mm to 0.5mm to your objects. 
    • At all stages think about the model orientation as it'll be printed - that way you'll know about all the overhangs, and obviously the case lid / siding without violating the laws of gravity. I've printed the case base down as normal, have modelled the lid to be printed upside down, with lips guiding the lid into perfect position.

    I think I've come on leaps and bounds at project housing design - here's a sneak peak at the end result (sans actuator arm, because I've not made it yet).

    Yes I've left the lid on for now - saving the 'reveal' for later! I'm not exactly done yet tho - still need to - 

    • Build an actuator arm with spring loaded tip - currently just shown with a servo horn.
    • Develop the software stack to make it work (currently SSHing into it to make it move)
    • Find a way to securely attach this to the side of the heating timeswitch - this means figuring out a way to stop it 'flexing' when pressing the button, ensuring it doesn't just push itself away having not enough 'heft' to press the button fully - yes this is something I missed out in the design stages, but it's a different challenge. I might just attach it with a strapping or something, just some thick string or some strong tape.
    • fine tune the motion of the arm to prevent long-term button...
    Read more »

  • MOSFET time

    h3liosphan10/25/2021 at 21:19 0 comments

    IRLZ44N's have arrived, I've successfully built a test circuit to prove the MOSFET is doing it's job.

    I told a small lie last log entry - I had dealt with MOSFETs before, trying to trigger a bright LED, but it was totally unsuccessful! Didn't even consider at the time putting in a pull down resistor to tie the gate to ground!

    This time round I had read a lot about it, so I had a basic mock-up circuit on a breadboard. Interesting to read that the GPIO to Gate resistor isn't there to limit voltage into a MOSFET, it's only there to delay the 'charging' of the FET - still, the advice I read is to put one in at rough

    After a lot of trial and error I achieved success turning the MOSFET on and off, thereby shutting down the Servo motor completely - as previously mentioned, some servos will make your life difficult if they demand too much current in a short period of time, especially with something as 'delicate' as an RPi.

    So the standard advice for inductive loads such as a motor, is to put a flyback diode in to catch voltage spikes during start / stop of the motor, and save your MOSFET and/or GPIO pins on the Pi from being fried. Call me risky but so far I've not needed one, so is not on my list to add one - does a Servo motor come with one to protect RC radio gear perhaps?

    I'm using a 10k resistor from Gate to ground to pin it low.

    I'm also using a ~250ohm resistor from GPIO pin to Gate to slow the activation of the MOSFET by a tiny amount - my thinking at least is to ramp up the MOSFET activation, hence energy usage, slower than if it were on instantly, saving brownouts - is this good!?

    Aside from that, it's all just standard connections - the Servo is high, MOSFET under it, servo negative terminal connected to Drain, then Source goes straight to ground.

    Toying with the idea of putting some decoupling caps in, but nobody else has mentioned needing them for a MOSFET, and my circuit works without.

    Now on to planning the physical form, and building a small MOSFET breakout board from proto-stuff.

  • Proof of Concept and basic planning

    h3liosphan10/25/2021 at 21:01 0 comments

    I've undergone some basic proofing of concept, started building a simple servo control using this chap's YT video - youtu.be/_fdwE4EznYo

    This is a great explanation, because the net is swarmed with articles talking about how a Pi (especially the Zero) cannot drive a Servo without even a little bit of jitter - this was a misconception based on how Linux is timeshared, and hence can't drive a steady PWM signal without missing the timing - it can be done instead using the various hardware peripherals, hardware PWM on any GPIO pin is the solution.

    I built a brand new RPi SD Card image with the latest Pi OS Lite on it (don't need the GUI), booted it up and fully configured it. After following the instructions to plug in a servo, power it, and drive it with a GPIO pin, all was good. This worked fine.

    Obviously you'll run into issues attempting to drive powerful servos, powering the mini-servos is usually preferred without augmenting the power supply to the servo (i.e. not powering it through the 5v pin on the pi). Fortunately, with extensive testing I've managed to get a normal hobby sized servo - Hitec HS645 MG working just fine without any hiccups off of the 5v pin on the Pi - this is with a 3.4A charger from Ikea (however it's only 2.4A per USB socket, it's a 3 way). 

    I have a cheapo HobbyKing servo (H-KING) that does not like working from it - the servo twitches when asked to move, then the pi immediately resets, suggesting there was a nasty brown-out.

    I've experimented with an IRF540A, never having previously worked with MOSFETs before, I had to do extensive reading before figuring out it requires too high a voltage before activating. I have no experience either building a correct circuit to drive it thru a transistor, so I instead ordered some logic level MOSFETs.

    I've placed an order for 10x IRLZ44N's, as I predict at least two will get blown during my experimentation!

View all 5 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates