Here it is a short teaser to show the concept of the project.
Roadmap, step by step
- starting from very low level electronics: TRIACs, SSRs and dimmers
- going up to the micro-controller firmware to handle real-time smoothing of the mains waveform
- going to up to a simple RESTful embedded web-server on Linux/Android
- going up to a modern and nice looking HTML UI based on Polymer
Overall architecture
The lightning controller consists of the following:
- A PIC16F88 micro-controller, which handles the low-level light dimming / main switching operations and drives the lights (AC bulbs).
Link to the sources and schematics - An embedded web server, running on a UDOO Quad board. The server exposes REST endpoint to control the lights and communicates with the PIC through one of the UDOO's UART ports.
Link to the sources - A HTML5 web-app, based on Polymer, to handle the user-interface.
Link to the sources
Safety warning and disclaimer
Part of this project involved a DIY board meant to be connected to the mains supply.
Never ever put your hands, try to fix, program or debug a board while it is connected to the mains, especiallyif you think you know what you are doing. Even if your board is supposed to be opto-isolated, you might have mis-connected the opto-isolators or created accidental short-circuits which invalidated the AC / DC galvanic isolation. In all these cases, take some extra patience and always physically unplug the board from the mains before doing any maintenance.
No religion has confirmed yet whether there are good compilers for micro-controllers in heaven. Likewise, micro-controllers might be difficult to operate in hell, due to the extreme temperature range (XTALs might drift a lot there causing PLLs to never lock).
Furthermore, the schematic here should be considered as a prototypical concept. Therefore I decline any responsibility for any damages / fires / earthquakes caused by that.
Light dimmers: theory of operation
Let's start from ground zero and cover the electronic principles behind AC light dimmers. How does a light dimmer work?
The principle is extremely easy to understand but a bit hard to turn into practice (we'll see later why). The figure below should give a very good idea about the theory: imagine a switch (a very fast one) which gates the connection between the AC mains and the lamp. The higher proportion of the sine-wave will reach the lamp, the brighter the light will be.
The first problem is: how do we actually switch the mains in a timely fashion? In most countries, the mains sine-wave has a frequency of 50 Hz, which means that each half cycle (0 V, +/- peak, 0 V) happens at a frequency of 100 Hz, hence with a period of 10 ms.
A mechanical relay won't be able to keep up with such timings (without wearing out in few hours). Thebuilding block used in these cases is the TRIAC. In the very essence, a TRIAC is similar to a transistor, but is able to drive alternate current loads.
Fantastic! So, all we need to do is to connect a TRIAC to a micro-controller? NO. It is not that simple. TRIACs have a couple of gotchas.
TRIACs are not isolatedand you should never have any galvanic path between AC and DC logic. TRIAC should be always driven with a opto-isolated driver (the MOC3021 is a popular choice). TRIAC drivers, however, require a number of extra components to work properly, which add extra complexity and points of failure to the circuit.
Solid State Relays (SSRs) are more DIY-friendly alternatives to TRIACsIn the very essence a SSR is an integrated circuit which embeds a TRIAC, an opto-coupled driver and the annex analog driving circuitry.
TRIACs and SSRs turn off only at zero crossThis is the detail that makes the driving logic a bit complicated. A TRIAC cannot be turned off at any random point (better: it can but it won't have the desired effect). The reason lies in its silicon design. See the wikipedia page for more details. A dimmer, therefore, needs to keep track with the mains sine-wave with pretty strict timing margins, within the sub millisecond range. Which is the perfect job for a micro-controller.
There are three important factors to remember when choosing a SSR:
- The driving voltage (typ. 5v or 12v): this should be chosen accordingly to the DC logic of the board. Usually SSRs cannot be driven directly from a PIC and require a buffer chip.
- Maximum Output Load (typ 1-2 A): this determines the maximum power that the SSR will be able to drive. Remember to oversize the SSR to avoid heat dissipation issues. For instance a 1 AMP SSR is theoretically able to drive a load of 1 A x 220 V = ~220 W. in practice it should not be used with loads higher than 100-150 W.
- The trigger type: zero-cross or random fire. Zero-cross SSRs are essentially on/off switches, which are able to turn on and off only on a zero-cross point. Their main application is driving very large loads (typically ovens / thermostats). Random-fire SSRs behave like standard TRIACs. They can be turned on at any point of the sine-wave but turn off only upon zero-crossing points.
Use only random-fire SSRs for light dimmersIt is obvious at this point that random-fire SSRs are what we are looking for here. Look carefully to the data-sheet before buying them, in order to avoid sad surprises and end up with a dimmer which just doesn't work.
Why not just PWMYou might wonder why we can't just use pulse-width modulation (PWM) like we do for dimming LEDs and other DC loads, and use something better than a TRIAC.
Technically speaking it is doable, but it has a number of disadvantages:
- It requires a IC which is able to switch at arbitary points, like an IGBT. IGBTs are more expensive and much harder to operate (require a high gate voltage).
- Even excluding the technical difficulties, high frequency switching of large AC loads will end up creating a lot of electromagnetic interference. In concrete words, a PWM-based AC dimmer is very likely to drop down significantly the quality of your WiFi (and cause many other problem).
Schematic of the dimmer
Having explained the theory underneath, the schematic follows straightforwardly:
Micro-controllerThe choice has fallen on the super-popular Microchip's PIC16F88. If you know PICs you will know why. If you don't know PICs, just trust me :) The 16F88 is super cheap (few EURs), can be found in virtually any electronics / DIY shop and has all the peripherals required for the job (ADC, timer, internal oscillator).
Why not an Arduino?Absolutely reasonable objection. There is no reason why you should not use an Arduino here if you are familiar with them. Personally, I have used PICs since I have memory, and these days there are more PICs than pairs of socks in my bedroom.
UART inputThe communication between the UDOO board and the PIC is handled via UART (read: serial port). UART is easy to use. Both the PIC16F88 and the UDOO board have UARTs and their voltage level is compatible (at least in the UDOO -> PIC dir.).
Mains tracking input stageThe mains AC waveform gets through a SFH620A opto-coupler to the analog-to-digital input RA1 (AN1) of the PIC. Note that:
- The opto-isolator has a Math.abs() effect. The micro-controller will see only a train of positive half-sinusoids (as from the output of a rectifier bridge).
- The pull up configuration has the further effect of inverting the phase of the wave. In other words, the PIC will read a value close to digital 0 when the mains are at the maximum peak point (either positive or negative) and a value close to
0xff
on the zero-crossing points.
SSR output buffersThe PIC output drivers cannot source enough current to directly drive a SSR. For this reason the four SSR outputs are buffered using a ULN2003. The ULN2003 is a very popular darlington array chip consisting in 7 buffers, able to drive up to 500 mA loads.
SSR chipsMy choice for the SSRs has fallen on the Panasonic AQG22212. It's reasonably cheap (~4 EUR each) and can drive loads up to 2 A (~440 W).
Firmware for the PIC16F88
The source code for the firmware is written in C and is available here: github.com/primiano/light-dimmer
I am not going to comment the code for the firmware, as most of it is PIC-specific. If you have used PICs before, you will find the source code very easy to follow. Otherwise, it will look as a nonsense assignment of registers without a meaning.
What can be more useful, instead, is a flow-chart which explains the overall logic. This should make it easier to rewrite the firmware on any other micro-controller.
I am adding just few guidelines, which apply generally when writing embedded C software and are vital for a dimmer. With a cycle time of 10ms and a desired dimming resolution of 64 steps, the computation budget is about 156 uS. With a clock frequency of 1 MHz, it gets down to ~156 (assembly) instructions.
Embedded REST web server on
UDOO
Let's now switch to the UDOO side. The UART can be accessed in hardware using the pin TX0 (refer to thePinout Diagram ) which corresponds to the PIN 1 of standard Arduino shields. From the software side, the UART is visible as a standard TTY,
/dev/ttymxc3
I choose to develop the web-service in C. It makes it possible to reuse the same code whether you are running either Android or Linux (the UDOO board supports both).
The web-service should be run as part of initrc on Android or daemontools on Linux. See this CL as an example. Try not to run it as root: there is no need for that and is frightening from a security viewpoint. Just chown the serial TTY to an unpriviledged user using udev rules).
Accessing the /dev/ttymxc3 serial port
The way to go to access the serial, in C / Linux, is using libtermios
:
What we are going to do now, is writing a web-service which raises the abstraction level and encapsulates the UART wire protocol with the PIC, exposing that through a RESTful web service. The API is going to be super simple:
Get the current state of a dimmer
Set the brightness of a dimmer
(The actual web-service I wrote has two extra endpoints for some digital I/O lines. I am not going to comment them in this post as they are absolutely trivial and similar to the dimmer ones).
To implement the web service I used mongoose. It is an open-source, lightweight and very easy to use (one .c file) web-server.
Essentially mongoose allows to register a custom callback function to handle HTTP requests. What we need to do is just match the request path in the callback and invoke the right REST handler. I created a minimal layer of abstraction to make it more readable as follows (see the home_automation.c for the full code):
Web based UI in Polymer
In this project the UI has been realized as a HTML web app based on polymer.
Why? Why not a native app? Mainly for three reasons:
- I want to control the lights of my flat using both my smartphone and my laptop. I am a lazy engineer and I don't want to write the same code twice.
- It is 2015 and the concept of installing an app is so démodé. It sounds like loading tapes into a drive (or should we download that using z-modem?).
- I am a browser engineer, I spend way too much time writing native code and I like to switch on the other side and enjoy the beauty of the things I contribute to in my spare time.
Ok, HTML/JS cool. But what the heck is this polymer?If you don't know the answer you should definitely check-out polymer-project.org.
Essentially Polymer is the way to go to create web-apps based on actual reusable components. Besides the architectural encapsulation itself, the nice thing about Polymer is that components act as actual boundaries for JS and CSS scopes.
In other words, Polymer is the fantastic world where you can add a new piece of UI without fearing that the style of the entire page will be screwed up.
Essentially it's the way to go for civilised modularity and forget about awkward hacks (i.e. get back to the state where !important is a word that you use only with the people you care about, not a CSS annotation to make an element actually coloured).
Furthermore, it has a lot of other nice properties (dynamic bindings similar to Angular JS, native browser support in Chrome).
The other nice thing about Polymer is that, beyond the framework itself, the project has recently made available the Paper Elements: a toolkit of material design UI components. This allows to quickly make a first-class UI which looks like any other native mobile app.
Last but not least, Polymer comes with a layout editor, Polymer Designer which allows to design the UI and take advantage of Paper Elements in a graphical environment, without having to know too much about polymer's syntax.
The architecture of the HTML UI for this project is decoupled in two levels:
The <home-automation-dimmer>
componentThe responsibility of this component is to handle the interaction with one channel of the dimmer. The component exposes three property to its clients, which are:
- value: the actual brightness of the dimmer (read/write).
- channel: the channel ID of the dimmer (0, 1, 2 or 3).
- color: the color of the UI element.
<polymer-element name="home-automation-dimmer" attributes="value channel color">
Concretely this component consists of a <paper-slider>
UI element (see image below) and two <core-ajax>
components, one for the read (GET), the other for writes (POST).
The three components are bound together by the value
property. When the component is loaded, the first AJAX component will issue a request to the dimmer/{{channel}}
enpoint, binding its reponse to value
. When the response is ready, the property is changed. The change of value
causes an automatic update of the <paper-slider>
, which will reflect the value read from the web-service.
Similarly, when the paper slider is changed, tapping on that, the value
property will be propagated all the way through the second AJAX component, which will issue a HTTP POST request, setting the dimmer to the desired value.
The <home-automation>
UIThe responsibility of the <home-automation>
is to simply instantiate and group together the four <home-automation-dimmer>
elements, one for each channel of the dimmer. Furthermore, it will define the CSS style-sheet to give a proper shape and colour to the elements, as follows:
Sources of the User Interface
Primiano Tucci
Comments