Study Lights Controller (reworked). Part 7 : IoT, Home Automation

Introduction: Study Lights Controller (reworked). Part 7 : IoT, Home Automation


This Instructable is a reworking of an earlier project named 'Web Enabled Lazy Study Lights Controller' which as the name suggests was a means of controlling my study lights via a web page interface. The link for which is given below;

This rework sees the original embedded software implementing an interactive web server with the Arduino Uno completely re-written and integrated into my recently created OpenHAB home automation infrastructure as an IoT device fully supporting the MQTT message interface.

In porting MQTT functionality I used the PubSubClient Library by Nick O'Leary. Found here;

However, given the Arduino Uno R3 and Ethernet Shield R3 combination was originally sourced to satisfy the requirements of a simple web server it was now heavily resource constrained for an IoT device due primarily to the size of the PubSubClient library, consequently it was not possible to implement the code to support the DS1307Z+ real time clock (RTC) in the initial design.

Instead I implemented non-blocking timer functionality via the millis() function.

As mentioned above this Instructable documents how I re-purposed an existing web based study lights controller into that of an IoT device and integrated this into my IoT infrastructure (see pic three above).

The IoT device in question interfaces with three lights in my study (see pic two above) allowing me good illumination over my work area including the space under my desk where some of my test gear is stowed along with my tool box. Control functionality and network connectivity is achieved via an Arduino Uno and Ethernet Shield.

To set the system up, use the source code (provided) and create the necessary circuitry as before you will need the following;

  • A minimal grasp of electronics,
  • Knowledge of Ardunio and it's IDE,
  • Some patience,
  • Some understanding of your home network.

System entry requirements;

  • Home network with Ethernet,
  • An MQTT Broker correctly configured (See Part 1 and 2 : IoT, Home Automation),
  • MQTTSpy installed and set up. (See Part 2 : IoT Home Automation),
  • Arduino IDE 1.6.9,
  • OpenHAB 1.8.3 (See Part 6 : IoT Home Automation).

You will also need the following parts;

  • 1 off Arduino Uno R3,
  • 1 off Arduino Ethernet Shield R3,
  • 1 off 0.1uF Cap C3,
  • 1 off 0.33uF Cap C2,
  • 3 off 1K Resistor R2, R9, R11,
  • 3 off 1M0 Resistor R5, R6, R7,
  • 1 off 1N4001 Diode D7,
  • 3 off 1N4148 Diode D1, D2, D3,
  • 1 off 250mA GSH15 Fuse F1,
  • 4 off 4K7 Resistor R8, R10, R12, R13,
  • 1 off LM7808 8v LDO Reg IC1,
  • 2 off DCJ0202 DC Supply Jack PWR1, PWR2,
  • 3 off G5V-1 G2R Relay K1, K2, K3,
  • 1 off MCP9700A-E/TO Temp Sensor Q1,
  • 3 off P6KE10A Transorb D4, D5, D6,
  • 3 off PC817X3J000F OPTO COUPLER OK1, OK2, OK3,
  • 3 off VN10KM MOSFET Q3, Q4, Q5.

The article will cover these topics;

  • Very brief overview of the circuit,
  • Overview of the software,
  • OpenHAB Interface,
  • How to test your IoT device and see it in action,
  • References used.


Series Links

To Part 6 : Setting Up and Configuring OpenHAB. Part 6 : IoT, Home Automation

To Part 8 : WiFi IoT Temperature and Humidity Sensor. Part : 8 IoT, Home Automation

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Circuit Overview

I've included a copy of the circuit diagrams above for reference, though it should be noted as support for U1 the DS1307Z+ RTC is no longer available in software the following components are no longer necessary and have been removed from the parts list;

U1, R1, R3, R4, C1, Q2 and G1

Step 2: Software Overview


To successfully compile this source code you will need the following extra libraries;



Full details also given in source code below.

You will also need to know;

  1. The IP address of your MQTT Broker (in IPv4 format AAA.BBB.CCC.DDD) :

    IPAddress broker(

    W, X, Y, Z


  2. A free IP address to use for your IoT device : byte ip[] = {W,X,Y,Z};

Code Overview

On startup the software connects to the Ethernet network using the pre-supplied connection details above.

Once connected to a LAN the IoT device registers with the MQTT Broker using the following client name 'WIZNet5100-DE:AD:BE:EF:FE:ED' and will publish its details to the following MQTT topics;

  1. /EthernetDevice/SwVerConfirm : This contains a concatenated string, comma separated, formed by the generic device name, unique MAC address of device and the name of the Arduino file used to program the device. in this case 'WIZNet5100,DE:AD:BE:EF:FE:ED,MQTTStudyLightController1_8.ino'.
  2. /EthernetDevice/Study/LightConfirm

    : When this device receives a publication on the /EthernetDevice/Study/LightsQuery topic it responds by publishing to the /EthernetDevice/Study/LightConfirm topic status of the Swan, Top Shelf and Under Desk Lights via a single byte. Value of this byte ranges from 0...7. Bit 0 = Swan Light, Bit 1 = Top Shelf Light, Bit 2 = Under Desk Light. 1 = On, 0 = Off. Note : The same confirm response will happen if a local button push is made.
  3. /EthernetDevice/Study/LightControllerTempAlarmConfirm

    : When this device receives a publication on the /EthernetDevice/Study/LightControllerTempAlarmQuery topic it responds by publishing to the /EthernetDevice/Study/LightControllerTempAlarmConfirm topic the Study Light controller temp alarm status. Active = 1/Inactive = 0.
  4. /EthernetDevice/Study/LightControllerTemp

    : This device publishes the Study Light Controller Internal Temperature to this topic measured in Degrees Celsius and accurate to 2 decimal places after undergoing a rolling average, the samples for which are stored in the following array 'averageTempArray[MAX_TEMPS]'. Updates are only issued if there is an integer change in temperature to prevent this IoT device 'clogging' up the network.

It then subscribes to the following MQTT topics;

  1. /EthernetDevice/SwVerCommand : When notification is received on this topic the device will respond with a /EthernetDevice/SwVerConfirm publication. This is a broadcast response. ie. all devices could respond.
  2. /EthernetDevice/DE:AD:BE:EF:FE:ED/SwVerCommand : When notification is received of this topic the device will respond with a /EthernetDevice/SwVerConfirm publication. This is a targeted response. ie. only this device will respond.
  3. /EthernetDevice/Study/LightsQuery

    : As described above for /EthernetDevice/Study/LightConfirm, this device will respond to this topic publication with a status byte. The value of which is a bitwise representation of the current status of the study lights.
  4. /EthernetDevice/Study/SwanLight : When notification is received on this topic the device will turn on/off the study swan light. The payload value of '1' will turn the light on and '0' off. Once the light output has been updated the current status of the light will be returned via a publication on the /EthernetDevice/Study/LightConfirm topic. In this way the OpenHAB site will reflect the actual value of the respective light.
  5. /EthernetDevice/Study/TopShelfLight : As for /EthernetDevice/Study/SwanLight but control is for Top Shelf Light.
  6. /EthernetDevice/Study/UnderDeskLight : As above but for Under Desk Light.
  7. /EthernetDevice/Study/LightControllerTempQuery : When notification is received of this topic the device will respond with a /EthernetDevice/Study/LightControllerTemp publication with a payload detailing the current internal temperature as outlined above. In this way the Study Light Controller can be polled at any time to determine its current temperature. This mechanism is used to overcome the issue with graph persistence in OpenHAB. (See here for further details
  8. /EthernetDevice/Study/LightControllerTempAlarmQuery : When notification is received on this topic the device will respond with a /EthernetDevice/Study/LightControllerTempAlarmConfirm publication containing a payload detailing the current internal temperature alarm state as outlined above. Also, if the internal temperature has exceeded 40 Degrees Celsius all lights will be automatically switched off and an Active status is published to the /EthernetDevice/Study/LightControllerTempAlarmConfirm topic. In this way the Study Light Controller automatically triggers an update to OpenHAB or can be polled to determine its current temperature alarm state. The message triggers the colour state change to the alarm bell on the 'Light Cont. Config' page and activates the warning sound event.

Once completed the software now drops into a loop monitoring the MQTT Broker connections for topic publications along with any local requests for changes in illumination via the button box inputs, manages systems timers and continually monitors averaged internal temperature status.

Implementing non-blocking timers

As mentioned in the preamble I implemented a non-blocking timer facility, calls to this are as follows;

  • void timer_create(int iTimerNumber, unsigned long ulTimerPeriod, void (*callbackfn)(void));
    • Used to create a new timer 'iTimerNumber' and add its context to the stiTimerArray[]. The required delay time 'ulTimerPeriod' is stated in milliSeconds and a pointer to a call back function is supplied. This call back function is executed if the timer expires.
  • void timer_update(void);
    • This function must be regularly called from with the main loop and is used to update all the timers, check to see if they have expired and if they have, launch the call back function 'callback()'.
  • void timer_start(int iTimerNumber);
    • As it says, a call to this function starts the timer count down period.
  • void timer_stop(int iTimerNumber);
    • As it says, as call to this function will stop the timer counting down.
  • void timer_reset(int iTimerNumber);
    • When called will extend a timeout period to its initial value. Effectively creating a 're-settable mono-stable' timer. In layman's terms, like 'kicking' a watchdog timer.
  • boolean timer_isRunning(int iTimerNumber);
    • Function call to test to see if a given timer is currently running.


If new timers are required then the following must be carried out;

  • Increment the number of MAX_TIMERS
    • #define MAX_TIMERS 3
  • Define a new timer define ie.
    • #define NEW_TIMER 2
  • Define a new callback function void cf(void); and add timer
    • timer_create(NEW_TIMER, 10000, cf);

  • Start the new timer
    • timer_start(NEW_TIMER);

A full copy of the source code is given below.

Step 3: OpenHAB Interface

To integrate the Study Lights Controller into the existing 'SteveQuinn Household' site I made the sitemap changes as outlined in picture one above. Here the shaded screens depict the changes;

  1. The study screen now contains the three switches; Swan Light, Top Shelf Light, Under Desk Light and the internal study light controller temperature is displayed, (see pic 2),
  2. A new Light Controller Configuration (Light Cont. Config) webpage has been added to allow the user to poll the current internal temperature alarm status along with the current internal temperature. (see pic 3, shown here with alarm active in red),
  3. A new trend screen has been added, displaying the controllers internal temperature trend, (see pics 4 & 5).


As before If you wish to use the 'stevequinnhousehold' example all you need to do is unzip the contents of the zip file below and drop the files into the OpenHAB directories shown above in picture 6.


This implementation uses OpenHABs ability to play sound clips. As I mentioned above, should the internal temperature of the Study Light Controller exceed 40 Degrees Celsius the IoT device will signal this error condition to the OpenHAB server by sending a /EthernetDevice/Study/LightControllerTempAlarmConfirm message with payload = '1'. Receipt of this message will trigger the playing of a sound clip 'OverTemp.mp3' on the Raspberry Pi and changing the colour of the 'Internal Temp Alarm' from black to red. See 'Testing Your IoT Device' for further details.

In order to enable OpenHAB to play the sound your OpenHAB install requires a slight change (I am working on the assumption you are following all the parts of this series). I have added this change to the earlier instructable on how to install OpenHAB (Part 6: IoT Home Automation). However for convenience I had also detailed them below. When implementing the changes as always remember to open a PuTTY terminal window to the OpenHAB server and cut and paste to avoid errors.

First edit the openhab file under defaults;

  • sudo nano /etc/default/openhab

locate USER_AND_GROUP and change it to;


now edit openhab.service under systemd;

  • sudo nano /usr/lib/systemd/system/openhab.service

Locate User and Group and change them to;

  • User=root
  • Group=root

And that's it. Now restart OpenHAB for the changes to take effect.

  • sudo service openhab restart

Or reboot

  • sudo reboot now

Step 4: Testing Your IoT Device

In my earlier Instructable 'Setting Up and Configuring OpenHAB. Part 6 : IoT, Home Automation' I described the use of both simulated and live data for testing along with their respective merits.

In this instance we will be using both methods to test our new IoT device. As depicted in pictures one and two above.

For convenience simulated data will be used to trigger an over temperature alarm. Otherwise the Study Light controller would need to be opened up and a temperature of greater then 40 Degrees Celsius applied to the MSP9700A to force an alarm condition.

I have detailed out the message flow for the Over Temperature Alarm Sequence in pic 3 above

For validation of light control and timer functionality the OpenHAB interface and button box will actually be used for testing.

I have also included a video clip of the testing I carried out.

Step 5: Conclusion

Given my current infrastructure and Arduino/MQTT/Raspberry Pi knowledge re-purposing the Study Light Controller as an IoT device in my Home Automation network was relatively simple to accomplish and works well. In fact adding the button debounce library has made the reaction time a lot more responsive that I had originally coded.

However, to miss attribute the famous Bill Gates quote '640 K ought to be enough for anybody' with hind sight I should have picked a bigger Arduino, that way I could have included both the RTC capability and DHCP functionality.

Step 6: References Used

I used the following sources to put this Instructable together;




Decoding binary data for RULES


Charting (including issue with rrd4j persistence)

Problem getting exec binding to execute command (how to get playSound working with OpenHAB)


The oft' miss attributed Bill Gates quote

Be the First to Share


    • Backyard Contest

      Backyard Contest
    • Silly Hats Speed Challenge

      Silly Hats Speed Challenge
    • Arduino Contest 2020

      Arduino Contest 2020