Ceiling Fan controller


I have some ceiling fans at home, and when it’s not too hot they perform very well in giving some relief. But I don’t like very much standing-up when some control is needed, that’s why I decided that a remote was needed. Buy one ? Hmm, they sell for low price, but they are too simple. So I decided to design and build my own fan-control in a way that some simple automation was possible. For simple automation I mean that the fan will automatically switch off after a predetermined amount of time, and when switched on the behaviour depends on temperature (see below for further details).

I ended adding ESP8266s to all of the ceiling fans at home.

Each ESP handles both the light and the fan; control is via IR remote or WiFi (through an html page).

Yes I know, a simple sOnOff with 2 outputs does nearly the same and is cheaper, but I love to build things … and I don’t like to be Internet dependent for a simple on/off switch (a TCP packet sent over a server to ‘who knows where’). I want the system to be fully functional even without any kind of connection. In this project WiFi is welcomed but an IR remote can be enough. Implementing an MQTT server is not a straightforward operation, that’s why I opted for http.

A web server and an http interface built into the Esp allows for full configuration.

WiFi and or IR can be disabled if not required.

The controller has an on-board temperature sensor, allowing a simple (IF THEN ELSE) automatic behaviour change; example: in winter time the fan is not required and switching the controller on, has only effect on the light. This is particularly handy if a single switch gives power to the whole light and fan unit.
I mean that the fan (and controller) is normally powered off. When it is switched on (by the light switch on the wall) the temperature is read-in and based on how it has been configured the light and / or the fan switches on or not..

Another possible application (allowed by the firmware) is that in winter the fan will be switched on for only 10 minutes, this is useful when cleaning the floor with water and a rag, to get a shorter evaporation time.

The main http control page is reponsive by making use of AJAX, and the IR configuration page too makes use of AJAX for an easy IR remote configuration (you press the button on the Remote and see the corresponding code directly on the configuration http page), so you can set the code immediately WITHOUT the need for a second Arduino test unit connected to a PC serial port.

Schematic and full source code is provided at my Github repository:



I made 2 versions, one where the outputs drive relays, the other drives ACSs.

Even if there is an insulation power transformer, the ACS version is directly tied to the mains !

Principle is really simple, the relay or the ACS is switched on or off when the relative command is received via WiFi or IR.


The ESP8266 has enough space for running the inputs, outputs, timers, a web server, soft-AP, firmware update via the web, NTP client, IR receiver and decoder. All glued together by the Arduino libraries.

Software has been split in different sources to ease reuse (in this project I re-used most of the software from my rice-cooking machine).

The first time it is run it starts as WiFi AP, and by connecting to it everything can be configured. Details, including the AP ssid, username and password are exactly the same as my cooking machine (, default password 12345678, firmware update at, …).


The IR remote option is critical: the transmitter should be directly visible to receiver, at a distance of a few meters and fan blades (if turning) are an obstacle. Finally buying a cheap remote (there are kits for Arduino) is not a good option: reliable covered distance is 2-3 meters but only if perfectly aligned. In other words dont make my same mistake: ir receiver you see in photos has too many obstacles.

For practical reasons (and for learning something new), I made some of the html pages web responsive by using AJAX. The reason is that the ESP8266 is not a powerful CPU with a lot of memory: continuously calling the web server (every 10″) is not the best thing that can be done.

As an example, the non-responsive version of the main page had html, css and ajax all embedded in the same page; this was meaning that approximatively 3 KByte where moved from the ESP to the web browser every few seconds. The micro was not very happy of this, considering it has to handle other tasks too. Luckily in the last few months guys at the ESP Arduino libraries have added an option where the sketch can now be compiled with “lwIP variant: higher bandwidth” and this solved most of the problems. Anyway by making the web pages responsive reduced the amount for data from 3 KByte every 10″ to 51 bytes every 10″ :-).

Another good reason for using Ajax is in the IR remote configurator: every single code coming from the remote is transformed to a unique 64 bit number by the decoding libraries.

This means that I can press the button on the remote and instantly (after 0-10″) see its code. So I can copy the code and paste it in the field that will perform the action (on or off or toggle).

The old way is to prepare an arduino, IR receiver, connect to the PC and look at the serial port to get the 64 bit code, the copy it to the fan configurator.

Why AJAX instead of jQuery ? Well the ESP8266 is a small micro, jQuery add approximatively 400 KByte of overload and even if the libreries can be referred to another server (CDN), I wanted this project be able to work stand-alone: without the internet it starts as an AP and can be configured by connecting to it. The approach is the same as for the rice-cooking machine, so can go there for details.

If using an ESP32 jQuery would have been the best choice.

Led Balancer

I have a lot of different leds in my drawer, some are new high efficiency devices, other are pretty old and despite a high amount of current (say 10 mA) are less brighter than the new ones (at 1 mA). I still have some leds from the 80-90s but their max brightness is incredibly low: practically unusable.
I sometimes need to put together leds having different colors and to get uniform brightness I need to test the leds together and experimentally find acceptable R values.
Similar problems with analog (4 pins) RGB leds.


The easier way to have the work done is to get 1 potentiometer x led, a multimeter, and a calculator.

I then decided to build a ‘Led Balancer’ device using materials I already have.

That’s why I went to this project, giving Arduino the task of reading current, voltage and proposing the correct E12 standard R value depending on supply voltage.
Too easy: that’s why I ended up adding pwm to set the brightness by up/down buttons.

The pcb hosts an arduino nano, a 20×4 characters lcd display (HD44780 compatible), some buttons, a connector for the leds and a few other components (including a voltage reference).

Leds can both be powered by DC (and current limited by multi-turn trimmers) or by arduino pwm generated signal.
AtMega ADC takes care of reading both voltage and current.
With pwm enabled, the adc reading requires some sw work, because U and I can only be read-in during the ‘active’ (led on) phase. The I value is then sw scaled by the pwm ratio.
This required tweaking the AtMega registers (details in source code pwmadc1ch.cpp).
The pwm out pin from arduino is buffered and inverted (BC327). The pwm pins have been chosen to leave Timer0 free (it is required for millis() and other time-keeping functions). Interrupts have been enabled, and at the correct transition (high to low) adc is started.
Adc sampling rate has been increased, minimum pwm duty cycle has been limited to 5%, that means a few more than 100 us, required by the Adc to have the sample done.
Adc alternatively reads voltage and current, and stores readings in 2 buffers.
See the oscilloscope sampled timings.
The pwm code is not directly portable to other Arduinos, it is AtMega328 specific, all the rest is standard architecture-independent C++.

Schematic diagram pdf

Sources (github)

* When driving leds with pwm, the voltage across the led is different from when the led is powered by static dc voltage.
* The pwm ratio (number passed to AnalogWrite()) is not exactly proportional to the effective duty cycle. But the difference is really small, see https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM

* I added a Precision Voltage Reference because I had one. This, along with 1% resistors, simplifies the project (no settings required). The overall error is small for the task of giving a 10% tolerance value for the resistor.

I have written 2 Arduino libraries:
ManyButtons: a single static class (thus a single instance) to handle any number of buttons; debounce and events (button pressed, released and long-pressed) handled.
IEC60003: computes the nearest E-series standard value. Can return both the standard value as a C float or a string in the form “12K”, “22u”, “R33”, “31K6”, … Can be used for R, L and C components.


Pcb has been printed by AllPcb, they do manufacture their pcbs and this means really short production times. As an example, time from file upload to pcbs on my desk has been 5 days. At the moment of writing the total cost (10x10cm, 5 pcs, dhl) is comparable to other services that ship with standard Post.

(rice) Cooking Machine

Esp8266 (rice) Cooking Machine


Adding an ESP8266 to a rice cooking machine enables it to become an IoT, and enables me to have rice cooked exactly at the desired time.

Schematic and full source code is provided at my Github repository:


In the (hope near) future will add a pump to automatically pour water and a programmable ‘taste curve’. See below in ‘Future enhancements’.



  • This post describes a circuit that has some parts directly connected to mains voltage. This means risk of injury or even death (electrocution) if not correctly handled. In case you make one, pay attention and avoid touching any live contact with any part of the body. In case of doubt avoid building it.
  • Some other parts reach high temperatures (up to 200 °C / 400 °F) thus again attention must be paid: temperature may cause injuries.
  • This machine can connect to the internet; like other IOT devices it can not be considered safe, from an intruder point of view, even if some precautions have been taken (see below in the sw section). For this reason it is strongly recommended, as a minimum precaution, to protect it using a good firewall.


Thanks to ESP8266, and its very low price, the machine exposes a web server, can be remotely programmed (firmware update) and configured via some web pages. Configuration does NOT require firmware compilation and update. All parameters are stored in EEPROM and configured by web pages.
The same chip controls both the machine cooking cycle and the web interface. Html pages make (a simple) use of Javascript.
As there is enough flash & eeprom space, the machine gets the time from internet (ntp), manages timezone and DST (daylight savings time).

Rice Cooker

A rice cooking machine costs no more than 30 € and is a quite simple electric device: 2 heating elements (power cooking resistor and ‘keep-warm’ resistor), a main switch, 1 safe/cooking thermal switch, 1 fuse and a couple of lights).
The safe/cooking switch must be manually reset by user and toggles when rice is cooked; a safety thermal fuse protects the whole machine in case something goes wrong and temperature inside the machine rises above a safe limit (194 °C = 391°F).
The key of this machine is the safe/cooking thermal switch that stops heating when temperature rises above 100 °C (212 °F) i.e. when all water evaporated.

A fundamental point is that here, any kind of temperature control is not only useless but detrimental. A constant power level must be applied: water itself guarantees the temperature to be at the constant boiling water value (100 °C), and a small temperature rise (100 to abt 104 °C) is detected by the safe/cooking switch to stop cycle.


Cooking cycle and schematic

Although simple, the rice cooking machine needs to get rice to a completely dry status, thus a layer of rice always sticks to the pot (and it’s not really easy to be removed).

I like rice but not totally dried, so the best solution would be, once cooked, to enter the time machine and go back in time for just a couple of minutes. Not really simple :-), unfortunately I don’t own a Time Machine. That’s why I started this ‘adventure’ some months ago.

How can it be determined when rice is cooked and ready to be served ?

The best solution I found is to check for steam. After an initial warming-up time, steam starts exiting by the lid. When steam flux is nearly over, rice is nearly cooked, approximately 3-5 minutes later the cooking/safe switch will toggle-off cooking. Unfortunately detecting the steam flux is not easy to be implemented and not reliable; along with steam some starch is emitted, detection must deal with temperature, must be easily removable, must be washed after each use.

That’s why I ended up by simply measuring the cooking time.

Here are the requirements for my cooking cycle:

  • the safe/cooking switch status must be detected (all the machine safeties must be retained) and all of its original functionalities must be retained
  • must be able to work with both relays and SSRs (initially I only had relays, SSRs allow wider programming capabilities)
  • must be easily programmed from the web
  • must retain the possibility to be manually operated ‘by hand’ (start and stop cooking); a minimal interface has 1 button and one LED.
  • temperature monitoring is not a big concern but may be useful

I initially provided (later removed) a temperature sensor and for the above explained reason it is here only for pleasure.

It uses the ESP8266 built-in ADC and a glass type 100K-3950-NTC (cheap 3D printer replacement part). Voltage is reduced by a simple R partition. For several different reasons (resistive partitor configured differently from standard, NTC and R tolerances) I decided to use a set-point table with linear-interpolated measures. This gives the possibility to change NTC type or express temperature in any desired measuring unit without the need to make any further computation. Unfortunately, as the NTC wire is directly (mechanically) coupled to the machine inside, I found it to be a big antenna, bringing all of the AC spurious noise directly to the ESP. The result was instability. Tried a filter, but did not solved all the problems. Only after removing the wire, all the issues have been solved and the machine now works like a charm. I did not deleted the temperature handling from the sw. Maybe in the future will be using a different approach (PT100 or thermocouple).

The safe/cooking switch is important so I decided not to hack it in any way. The down side of this is that one must remember to manually reset it or the rice won’t be cooked. This is the main concern because I always load rice + water but (near) always forget to reset it. This means no rice cooked, no food 🙁 and there’s nothing to be done from remote about this.

So when the machine is programmed or manually started, it checks for the safe/cooking switch and an alarm (red status on the web page and machine beeps) is sent if not reset. This check involves turning-on heating for a minimum amount of time (0.1 seconds) from time to time.

To read status I tried both an AC current sensor and an AC voltage sensor (behind the safe switch contacts). The first does not require ‘tampering’ the machine, the second involves bringing out some wires (using silicon heat resistant wires) from it. So I went for the second solution because I like to open, study and hack devices. Please note I decided not to alter the safe/cooking switch in any way, and as it works at high temperatures it is not safe to insert any kind of mechanical/optical switch in parallel to it.

Circuit uses 2 power outputs: 1 main on/off relay, 1 hot/warm relay, and 1 input: the safe/cooking switch detector. A further output is for water pouring (reserved for future uses, see below).

Raw working is easy:

  • cooking: both relays on
  • keep-warm: main relay ON, hot/warm relay OFF
  • off: both relays OFF

safe/cooking switch status detection requires relays to be in the keep-warm status for at least 0.1”.

If for any reason the switch was not reset, cooking will not take place and the machine is ‘electrically’ forced to the keep-warm status (hot/warm relay is series connected to the switch).

Making use or SSRs instead or relays gives a wider range of possibilities like regulating the power, a useful feature with bigger machines when under rice-loaded. Will be handled in a future release.

Schematic has been designed with Kicad and a PCB has been printed via EasyEda of which I’m very satisfied. The PCB is not available because I really made a lot of mistakes in design and I don’t plan to make a new one in a short time.


The whole circuit can be easily assembled using readily available components and breakout boards. The only part to be assembled is the safe switch sensor and the front panel.


Components connected to AC are for 230 V 50 Hz mains. Converting to 110V 60 Hz require some changes, I may report a note to the schematic if needed, but wont be able to test.


I used a self designed breakout board for ESP8266. It is smaller than the Chinese ones (leaves more space on the breadboard) the top is reserved to ESP12x module and the bottom has all the boot required pull-up and pull-down resistors, a power supply filtering capacitor, a reset circuit and the possibility to directly connect GPIO16 to reset, for deep-sleep mode. Maybe will make a post about it.


The software


Has been built under Arduino (ESP8266 board), currently 1.8.2, but most of the code is reusable under any hw architecture by changing only a few routines; software is organized by layers and libraries.

Portions can be easily reused for other purpopses (example: esp8266 startup and login).

This project has become a reality only thanks to the community and software already written (Arduino Esp8266, …). A special thanks to esp8266.com site for the Arduino port and all the guys that share precious libraries.

A brief description:

  • There’s an hw layer (machine_io class) that has to deal with the micro and i/os (example: to get temperature just call the function; it will be retrieved whaterver sensor is used), it has no awareness of what ios are used for.
  • An interface layer (machine_if class) where i/os are managed adding some general functionalities, propedeutic for the machine.
  • the machine cycle class
  • the web-server interface
  • libraries for time handling, serialization, sort
  • the only exception to this layer oriented approach is related to interrupts: when needed, the implementation tries to reduce the code overhead.

Software could have been written differently and better, but I tried to write code in order to get the highest number of reusable independent blocks.

Some refactoring is needed but unfortunately now haven’t the time for doing that.

Some classes manage time operations (add / subtract / print time and date), time zone and DST.

I don’t like how C standard libraries handle time/date, furthermore ESP8266 has some (linking) problems about this, Arduino does not (nearly) handle this at all. I needed a simple but more flexible way to manage time and date, that’s why I created those DateTimeManipulation classes and functions.

The web interface application allows configuring time zone, DST criteria, how time and date are printed. Settings are serialized (saved) in EEPROM and retrieved at boot time.

This project requires the following Arduino libraries:

Sort Sort an array of objects (any type), by providing the proper sorting function.
serializeEeprom Read from /write to eeprom any struct/class
DateTimeManipulation Input and output time and date. Add subtract time …

About safety against sw hacks, there’s little to be sayed. Like other IOT exposed to the web this machine is not safe. I used some precautions (password protected login, some features like firmware update and configuration are only locally available) but it must be strongly noted that it cannot be considered safe, so using a Proxy is really strongly recommended before exposing the rice cooker to the internet.

Future enhancements

  • Remote water loading: this will allow for a real free programming and free cereal usage. Leaving rice (or spelt or any other cereal) in water for some hours is only recommended for some (integral) types. I reserved a specific output to be connected to a SSR for a water pump. Currently experimenting with it, found that a mechanical relay is the best option instead of SSR due to the pure-inductive nature of the load. Pump is from an old espresso machine:
  • Add a simple taste curve’, required to have quality rice. Example:
    1. 15 minutes in cold water
    2. 10 minutes pre-heat (low power) [warm]
    3. 15 minutes cooking (boiling water) [hot]
    4. 5 minutes cooling [warm]
  • Power partialization (50% or 100% is enough) by pwm, useful when cooking a single small rice portion with big (700 W) machines, requires SSRs.
  • Use of SPIFFS file system for data logging (useful for debug).
  • Use of SPIFFS file system for blackout recovery (periodical save of current machine state and attempt to recover operation).
  • Use of EEPROM (SPIFFS file system) for web interface messages translation.
  • Temperature sensor type change. °F/°C web configurable option (temperature is read-in by NTC and setting the measuring unit is simply done by writing the correct set-points).
  • A display. With low priority. I made some tests with a small SH1106 SPI OLED display and found that this kind of interface requires a lot of resources and what can be displayed is not really very useful: when behind the machine the cycle status can be instantly checked by a simple look inside the (transparent glass) lid. Temperature is non relevant (steam gives by far the best indication about the cooking status).
  • Encoder with button for user input as a complement for the display.
  • Upgrade to ESP32. Already got one Expressif Esp32-DEVKITC Core Board V2 (with ESP-WROOM-32).

Not to be implemented

  • WS2812. As a minimal display I’m currently using an RGB LED (common-Anode, 4 pins), it’s by far easier to be handled. Made some tests with WS2812, but discarded because it requires a good 3 to 5V line converter and uses a lot of CPU resources. Now I’m happy with just 1 led and 3 resistors; a state change is a single output to a register without timing constraints.

A look at it

At boot time the machine tries connecting to the WiFi network (if configured and available). If this fails (or if the user switches-on the unit while keeping the button pressed) it creates an Access Point (default IP, default password 12345678, everything can be later configured).

In order to access the machine web interface, username (default: admin) and password (default: esp8266) are required.

So the very first time addresses are as follows: goes to the configuration page. goes to the firmware update page. In order to maintain a consistent safety level I needed to use a trick and generate a dynamic URL [*] goes to the normal operation interface. This is the only page allowed by a remote user (source IP address different from 192…).

If configured to receive a dynamic IP by DHCP, the new IP can be retrieved by the serial port monitor. Not really handy, I suggest configuring a static IP.

The 3-colors LED works as follows:

blue-blinking (50% duty cycle) connection attempt to the WiFi network in progress

blue-blinking (1/3 duty cycle) connected to the WiFi network

blue-blinking (2/3 duty cycle) available as a WiFi Access Point

blue-blinking (any duty cycle) good health state indicator

green: cooking completed

red: cooking in progress or programmed.


[*] the ESP8266 firmware update library (ESP8266HTTPUpdateServer class) does not allow for URL filtering, thus any user connecting to the correct page (/update) may be able to upgrade firmware.

I solved this issue by generating a random page URL. The local user connecting to /update page will be redirected to the ‘random’ update page. The internet user will need to guess the correct URL (may require 2^32 attempts) the /update page is not allowed to him. A ‘random’ URL is generated at boot time immediately after firmware update, so when the browser attempts to reconnect to the old ‘random’ page will receive a “404 Not found“ error. The response from the machine web server indicates the machine is again on-line, but simply the url has changed since then. Just type “/update” or “/” or any other valid page.




Pcb printed via EasyEda; the on line check and pcb preview is really very handy.

Images processed by Facepixelizer

A.C. Soft Start -or- ‘Long Life and Prosper’ to any A.C. load


Sometimes, in my home, the general power switch turns off at the exact moment I turn the Pc on.

The reason is the DeskTop Pc power supply (600W) draining a big peak current at power-up.
Monitor, computer, printers and all Pc peripherals are not directly connected to the mains, I use a switch to turn the loads on and off. This is useful, when not in use, to zero power load and to save electronics against sudden power bursts.

I tried to connect a UPS but nothing changed; the UPS on-off relay becomes damaged after say 200 (a couple of years) switch-on operations.

Thats why 5 years ago I decided to build a soft start and see what’s going on … happily working since then.

A soft start avoids to directly apply the full mains voltage to the the protected power target; in modern SMPS (switching regulators) the mains directly loads electrolitic capacitors (via a bridge rectifier) and until capacitors are fully charged a hig current is drained. Well there is always a standard protection that avoids excessive current: a resistors and/or NTCs.

The higher is the power, the higher is the current peak at power-on. In case of auto-ranging SMPS (Switch Mode Power Supplies) 100-240 V this is particularly true specially if ac mains is 230V 50 Hz (as in my country).

I believe this soft start will lead to a longer life (and prosper 🙂) of the power supply.


The 160 W halogen lamp is series-connected to the load. A simple n.o. relay is parallel connected to the output.

At power on transient, the output is seen as a short circuit, the bulb lights-up; when the output voltage (i.e. the load) reaches the relay toggle voltage (near 170 V in my case), the bulb is shorted, thus giving full power to the output.

The device has 2 protections: a standard fuse and a thermal circuit breaker: should the load or the power present an unpredictable behaviour, the circuit opens up avoiding fire hazards. Thermal breaker is thermally coupled with the bulb. It switches off at 60°C (140 °F) and back on again at 50°C (120 °F).

A really simple pure-electric solution, but with a side effect: the relay itself, when on, drains 1…2 W.

Components are designed for 230 V 600 W SMPS load but can be easlily changed for other voltages and powers.

The box for this device better not to be metallic as the full circuit is exposed to mains and cannot be plastic too couse the bulb may easily reach high temperatures (should not but one can never know); so I went for a pcb case: optimal electrical and thermal insulation. Four surfaces of the parallelepiped are soldered together leaving the pcb (soldered) inside; top and bottom lids are simply duct taped.

Here schematic, pcb & pcb-case.

IMPORTANT SAFETY NOTES: should you decide to make your own protector, please remember:

(1) the circuit is directly connected to AC mains, so do not touch any part of it when disassembled and input-powered.

(2) do test the protection by creating a short circuit to the output: the bulb must stay on until the thermal protection does its job by toggling off-on-off-on indefinitely. Themperature must remain safe (around approximately 60 °C)

Soft Start animation

Dirty Board PCBs

[2014/08/20] UPDATED: unboxing

Experimenting on a new project (a VA meter):

InstrumentationAmp VAmeter

I tried the Dirty Board PCBs service:
Dirty Board PCBs
I chose Express shipping because in my country standard shipping means waiting 1++ months due to ‘standard‘ customs operations.
Service has been very quick:

  • Sunday 10 Aug 2014 9:58: Order received “Yum yum. PCBs. FEED ME! ;)”
  • Sunday 10 Aug 2014 22:30: At board house “Sent to board house, batch #****”
  • Thursday 14 Aug 2014 22:37: Shipped “Thanks for making us part of your project!”
  • Saturday 16 Aug 2014 9:00: Trackable “Order trackable: DHL #**********”
  • Wednesday 20 Aug 2014 15:30: PCBs arrived !! 🙂

Exactly 10 days from Upload to Unboxing, including 4 days of travel.



Got 10 ‘Red’ pcbs, 11 ‘blue’ pcbs + 1 free tweezers and Dangerous Prototypes stickers.


Red PCBs: holes perfectly aligned, soldermask good alignment on both sides, silkscreen has a small offset (< 1 mm) see photos.

Blue PCBs: holes aligned within tolerance, soldermask good alignment on both sides, silkscreen has a small offset (1 mm) + some silkscreen imperfection (dirty) on some pcbs; again see photos.

Conclusion: red pcbs are perfect, some of the blue ones have only some aestetic imperfection. I’m very satisfied.

Some photos follow, please note I don’t have a microscope so the quality is not good (f.i. some have strange reflections, not a good focus, …):Pcbs_20140820_red2


Seleted the worst details of the worst 3 pcbs to show how the worst dirty can be: