Introduction: Web Enabled Lazy Study Lights Controller

This Instructable is a write up of my first ever Arduino project.

As is generally the case with hobbyist engineers, I thought long and hard to come up with a project that was not only cool but has some actual practical value. This was the sum total of my deliberations at the time.


The lazy study light controller comprises an Arduino Uno, Arduino Ethernet Shield and some supporting electronics to control outputs (the lights), read inputs (HTTP client and button presses), monitor the server internal enclosure temperature and provision a real time clock (RTC). Block diagram above.

The design allows for two generic ways to cycle the lights;

  1. Web client interaction
  2. Manual button press via switch box

The picture of the web page above is a screen grab of the html delivered by the server to an IE11 client. It allows the user to switch the lights on and off, set current time and date. It also displays the version of software currently operating on the server and gives a countdown of the remaining time before the lights will automatically switch off. It also presents an indication of internal temperature of the server enclosure.

As stated above, manual control is via a switch box. There are three buttons SW1...SW3 which toggle the respective light when pressed. Swan Light, Shelf Light and Under Desk Light.

Should the server enclosure temperature rise above 44 Degrees Celsius the lights will automatically be switched off and the web page will warn of the over temperature situation.

I have also included a truly 'Appalling' video of the light controller in action. You just wouldn't believe I taught Ridley Scott everything he knows.


So, why 'Lazy Study Lights Controller'? Because I only have to reach over and press the on switch to achieve the same outcome. :-)

Though the auto cut off facility has proved very useful.

Step 1: The Lights

There are three groups of lights used in this project;

The Swan Light

This light is ideally suited to deliver illumination on my keyboard without creating any glare on the keys thus allowing me to type easily. Yes, that's right from time to time I shamelessly need to look at the keyboard to type. Mea culpa.

It was a commercial purchase from Amazon costing £45. Located here;

Named the 'Daylight 3.6 watt Long Flexi Arm Clamp on Lamp'

The Shelf Light

This provides local illumination and helps reduce eyestrain as I while away the hours inventing my Instructables.

The Under Desk Light

This is the most important light of all! Without this light I have to hold a torch to see my test gear, laptops and tool kit which I store under my desk.

Light construction

The Shelf and Under Desk lamps I created by cutting relevant lengths of 16mm x 16mm cable trunking (purchased from ScrewFix) and adhering the equivalent lengths of strip LEDs (from Ebay) inside so as to shroud the light output and eliminating glare. These were wired to the terminal blocks on the control unit via black multicore bell wire and put in place with double sided sticky foam (pic above, under desk).

Step 2: System Details

As outlined above the system comprises; Arduino Uno, Arduino Ethernet Shield, Sparkfun Proto Shield v2, Output Board, Input Board and Switch Box.

It was engineered to be easily dismantled for maintenance or repair, meaning all boards are interconnected via fully removable molex connectors and screw fixtures.

  1. The Arduino Uno and Ethernet Shield are vanilla, with the exception that a power connector has been soldered to its 2.1mm supply jack (J15). This is because repeated insertions during the enclosure fabrication phase had compromised the on board 0.1" pitch 'Raw/Vin' connector. Besides I just don't trust Arduino push fit connectors for anything requiring current. With hindsight I should have purchased a Pro version and added my own connectors.
  2. Sparkfun Proto Shield v2. This hosts the RTC and Temperature sensor and three distribution connectors J13, J14 and J16.
  3. The Output board comprises four connectors J1 ... J4 and hosts the Pheonix terminal blocks (green connectors) fed by three 5V G5V-1 relays.
  4. The Input board provisions some protection for the Arduino and serves as power distribution for the rest of the system. This hosts connectors J5 ... J12.
  5. Finally the Switch Box houses three SPST manual input buttons.


I posted pictures of all the various subassemblies above.

The system has been in use now since March 2014 and has not developed any operational faults.

Step 3: Circuit Details

The circuit diagrams above give detailed breakdowns of each subsystem component.

Switch Box

This is just three push buttons (S1...S3) wired to a common ground. Pressing each button shorts the respective opto-coupler input to ground allowing current to flow in the diode signalling an active input to the Arduino.


Provisions signal and supply connections to and from the Arduino. It also contains a DS1307Z+ I2C RTC U1 and an MCP9700A temperature sensor (Q1) feeding Arduino Analogue input A0.

Output Board

Outputs from this board are via G5V-1 SPDT Relays (K1...K3) which are driven via VN10KM FETs (Q3...Q5). Each Relay is fitted with a suppression Diode (D1...D3) to prevent any back EMF transients damaging sensitive components.

The isolated feed to the Swan lamp is also routed via this board (K1). The design decision to isolate the Swan lamp power from the rest of the circuitry was driven by the requirement to not alter the operational characteristics of the lamp. In this way any electrical requirements would not be compromised. Thus reducing the risk of catastrophic failures, fires etc.

Input Board

This board provides power distribution to the rest of the system. Supply +12V on J5 is reduced via Series Shunt Regulator IC1 7808 to +8V to feed Arduino supply. To feed +12V direct would stress the Arduino +5V regulator requiring it to drop +7V. In this way a greater load from the Arduino on board regulator can be used to source supply to other dependant system components without the need for another +5V regulator.

Opto-Couplers (OK1...OK3) are used to provide input isolation and some degree of noise immunity thus preventing spurious triggering of outputs. The supply to the external inputs is fused at 250mA for dead short protection via F1 and transient suppressors (D4...D6) are employed as further protection.

Step 4: Software Details


The software was finally compiled and tested using Arduino IDE 1.6.5.

To get going you will need the following libraries created by Paul Stoffregen;

DS1307RTC.h Library

Time.h Library

Unfamiliar with installing Arduino libraries? Then go here for full instructions;


- Startup

On start up the software initialises the Ethernet shield with values for; HTTP Port (80), MAC Address (DEADBEEFFEED), IP Address (Her, no DHCP), Gateway IP Address (Here Router is and Subnet mask (Here Class C, and starts the server 'server.begin()'.

All addresses are IPv 4.

The code then enters the loop section of the Arduino software framework.

- Loop

The software carries out the following actions on each successive pass of the loop;

  1. Read in output from temperature sensor via A0 'sensorPin' and convert to degrees C. If the calculated value is in excess of the 'OVER_TEMP' level all the relay outputs are switched off and an over temperature flag is set. This reduces power dissipation in the server enclosure. The flag is used later to control the format of the HTML displayed by the client, triggering a warning message.
  2. The software then logs the current time '' and reads the status of the input buttons via indirect Boolean flags; 'SwanLightButtonState', 'TopShelfButtonState' and 'UnderDeskButtonState'. The time of this read 'GlobalTimeCurrent' is then compared with 'GlobalElapsedTime'. If 'HOURS_DELAY' + 'MINUTES_DELAY' is has been exceeded the lights will automatically shut off. This code is non-blocking thus allows the Arduino to spend more time monitoring for HTTP connection requests and improving Web Server<=>Client performance. This 'stay on timer' can be extended by a button press (via web page or button box) from any button, forming resettable monostable functionality.
  3. Each actual button input is then sequentially monitored via a 'digitalRead()' using either 'SwanLightButton', 'TopShelfButton' or 'UnderDeskButton' pin references. The code for this uses the 'millis()' call to create software switch de-bounce. Here switch de-bounce is deliberately extended to prevent accidental activation. It's functionality was developed to toggle the light if held permanently in the on position. This serves three purposes; 1: Only one button is needed to turn on/off the respective light, 2: This reduces the number of necessary inputs used on the Arduino, 3: Alerts the user if a button is accidentally pressed as would be the case if something heavy is placed on the button box unknowingly (I leaned this through experience). Again these delay calls are non-blocking.
  4. The code then checks for a client request and reads in any characters from an HTTP GET via a ''.
  5. If the HTTP request is complete, terminated by '\n' the software responds with a series of 'client.println()' commands. Each of which containing an HTML formatted response, forming the 'Study Light' web page in the client, including time, date, temp (or over temp warning), s/w version, remaining on time etc. You will notice from the top of the code I added the response from the compiler indicating how much program memory and dynamic memory was available. The Ethernet library is pretty memory 'hungry' so you need to be aware of your code size. In order to make most efficient use of the available non-volatile memory I surrounded each 'client.println()' string literal with the 'F()' macro such that they would be stored in flash and not code space.
  6. At the end of the response the GET request is checked to see if the client is requesting a time change 'strHTTPTimeLiteral', a date change strHTTPDateLiteral. If this is the case then the RTC is updated accordingly.
  7. Finally a check is made to determine if a change in light status has been requested via the web interface, if so the respective indirect Boolean flags are updated ('SwanLightButtonState', 'TopShelfButtonState', 'UnderDeskButtonState') along with the corresponding Arduino output pin to correctly drive the associated relay.
  8. Loop repeats.


Temperature calculation with the MCP9700

From the manufacturers datasheet, the MCP9700 gives an output change of 10mV/DegC. The equation for calculating the response is Vout = Tc * Ta + Vout0C. (or y=mx + c) Where Tc (Temp Coeff) is 10mV/DegC, Ta is the ambient temp being measured, Vout0C is the MPC9700 output at 0 degrees C.

So temp is calculated as follows; TemperatureDegC = ((sensorValue * (5.0/1024.0))-0.5)/0.01

Other items to consider

  1. Auto time set on start up. Or auto update periodically. Saves having to do it manually.
  2. Display of current status of each indication on web page.
  3. Improve the HTML. Possibly re-write to use served up pages from the Ethernet Shield on-board uSD card. Hardcoded string literals is not a particularly efficient method to use.
  4. If 3 is done, then add an FTP server so updated web pages and be easily uploaded.

Lessons learned

  1. Use an Arduino Pro version so you can add your own, reliable connectors.
  2. Spend more time learning HTML. I cheated and used WireShark in order to see exactly what was going over the Ethernet so I could figure out what was happening in the Ethernet shield. The Arduino IDE is pretty good to get going but woefully inadequate to debug with. Unless you like to use 'print' statements. I don't.



Finally, as always, the code, circuit diagram, construction details etc. are provided free to use in whatever way you see fit (just make a mention of me), though they come unsupported.


Happy inventing.