IR Remote Control Via IoT. Part 10 IoT, Home Automation
by JohnSmith in Circuits > Arduino
6191 Views, 39 Favorites, 0 Comments
IR Remote Control Via IoT. Part 10 IoT, Home Automation
![FrontPic2.png](/proxy/?url=https://content.instructables.com/FNY/EXF4/JAMTT4H1/FNYEXF4JAMTT4H1.png&filename=FrontPic2.png)
Ok, so you've sat down in front of the TV after your rather large Christmas dinner and now you're thinking 'how on earth am I going to change channel and up the sound for the Queen's speech, I've eaten so much I can't move to reach the remotes, let alone stand for the National Anthem'
Fear ye not, the solution is at hand. What you need is an IoT Universal Remote control!
Interested?
Read on...
.
Preamble
This article, the 10th in a series on home automation documents how to create and integrate an IoT Universal IR Remote Controller into an existing home automation system including all the necessary software functionality to enable the successful deployment within a domestic environment.
Introduction
As mentioned above this Instructable details how to make and integrate an IoT Universal IR remote control device. It's primary purpose is to replace the many IR remote controllers typically used to command household audio visual (AV) entertainment equipment such as television, satellite and sound bars etc. The device does not seek to control all AV devices, but a commonly used subset (as above).
The design methodology integrates seamlessly into the MQTT/OpenHAB based IoT network detailed in this series on home automation (HA) building on reused code taken from here. Alternatively as the MQTT interface is fully documented throughout it can be simply added to an existing HA system via MQTT publications.
At it's heart is an ESP8266-12E which is responsible for MQTT communications and controlling all the functionality. The device is configurable via text files on a local SD card, though calibration and network security parameters can also be programmed via remote MQTT calls. Control of IR modulation is offloaded to a separate ATMega328P reducing the processing load on the ESP8266. Given there is insufficient I/O available on the device to meet this needs of this project an I2C I/O expander is used to overcome this limitation.
The unit also contains some local sensing electronics to detect ambient light level, temperature and humidity refactoring functionality available in a previous IoT device replaced by this equipment thus saving on energy consumption within the home.
Finally, the drive to make this device is to expose a consistent interface to the household TV, Satellite box and sound bar in order to ultimately allow connectivity with voice activated control, potentially avoiding a divorce as I regularly get accused of 'hogging the remotes'. As if I do!
.
What parts do I need?
Universal IR Remote Control, Control Unit
- 1 off veroboard (0.1" pitch) here
- 1 off Various lengths 22swg tinned copper wire here
- Various heat shrink tubing (Yellow, Ebay) here
- 1 off DC Power Connector, Plug, 1 A, 2 mm, Panel Mount here
- 1 off 3 way bulkhead socket here
- 1 off TO-220 Heatsink 24.4 °C/W here
- 1 off BH1750 ambient light sensor here
- 1 off DHT22 Temp/Humidity sensor here
- 1 off PN2222A BJT here
- 1 off Heatsink compound here
- 1 off LD1117-33v, 3v3 LDO VReg. here
- 1 off 3mm Red Led here
- 1 off 3mm Blue Led here
- 1 off PCF8574 I/O Extender IC here
- 1 off ESP8266-12E here
- 1 off SD Card reader here
- 1 off ATMega328P-PU here
- 1 off 16MHz Crystal here
- 11 off 10K resistors here
- 2 off 330R resistors here
- 6 off 1K resistors here
- 4 off 0.1uF Ceramic capacitors here
- 2 off 22pF Ceramic capacitors here
- 2 off IDC 10way Socket here
- 2 off IDC 10way Header here
- Various lengths IDC ribbon cable here
- 1 off Diode 1N914 here
- 2 off 1000uF Electrolytic capacitor here
- 1 off 10uF Electrolytic capacitor here
- 1 off 28way 7.62" DIP Socket here
- 1 off 16way 7.62" DIP Socket here
- 1 off 2way molex connector housing here
- 1 off 2way molex header here
- 3 off 3way molex connector housing here
- 3 off 3way molex header here
- 1 off 4way molex connector housing here
- 1 off 4way molex header here
- 1 off 6way molex connector housing here
- 1 off 6way molex header here
- 40 off molex crimps here
- 1 off Light Pipe here
- 1 off 2.54mm Header strip (3way & 4way Ebay) here
- 2 off 2.54mm SIL Socket (2 off 8way Ebay) here
- 2 off 5mm SPST Small Mini Micro Momentary Tactile Push Button (Ebay) here
- TW7-5-11B Plastic Enclosure, Flame Retardant, Multipurpose, ABS, 105mm, 70 mm, 50 mm here
- Various M3 Plastic stand offs (Ebay) here
- Various M3 Panhead, CS BZP screws, fibre washers, star washers and nuts etc.
- 1 off 2GB SD Card
IR Transmitter Unit
- 3 off TSAL6400 IR Leds here
- 1 off 3 way Pin free plug here
- 1 off veroboard (0.1" pitch) here
- 3 off 15R resistors here
- 1 off 270R resistor here
- 1 off BC337 here
- 1 off 1K resistor here
- 1 off 10pF Ceramic capacitor here
- 1 off 0.1uF Ceramic capacitor here
- 1 off 220uF @ 6.3vElectrolytic capacitor here
- 1 off 3mm Red Led here
- 1 off SKY Link Extender here
- Various heat shrink tubing (Yellow, Ebay) here
.
What software do I need?
- Arduino IDE 1.6.9,
- Arduino IDE configured to programme the ESP8266-12E (same as this). Then configure the IDE as indicated in the detailed description provided in the software.
.
What tools do I need?
- Molex connector crimping tool,
- Soldering Iron (with liquid flux pen and flux cored solder),
- Screwdrivers (various),
- Heat gun,
- Drills (various),
- Countersink handtool,
- Files (various),
- Dremel (various bits),
- Sturdy vice (small and large, like a black and decker work mate),
- Scalpel,
- Vernier calipers,
- Spanners and Nut drivers (various),
- Strong tweezers (for SMT soldering),
- Junior Hacksaw,
- Drill (with various drill bits),
- Fine pliers (point and snub nosed), flush cutters,
- DMM with audible continuity check.
.
What skills do I need?
- A lot of patience (in fact you will need a tonne of this if you want to do a half decent job),
- A great deal of manual dexterity and excellent hand/eye coordination,
- Excellent soldering skills,
- Excellent fabrication skills,
- The ability to visualise in 3 dimensions,
- Some knowledge of software development with 'C' (if you want to understand the source code),
- The project contains some interesting code using; variable function arguments (kind of implementation of fscanf, missing from ESP8266 library), linked lists, memory copies, data alignment in memory to allow easy serialisation over I2C, pointers to pointers for generic file reading, multiple timers with call back routines via function pointers, multiple state machines and a very simple cooperative RTOS.
- Some knowledge of Python (how to install and run scripts, if you want to use the automated testing)
- Knowledge of Arduino and it's IDE,
- Some knowledge of electronics,
- Some understanding of your home network.
.
Topics covered
- Circuit Overview
- Main Controller Unit Construction and Assembly Details
- Ambient Light Sensor RetroMods
- SD Card Holder RetroMods
- IR Sender Unit RetroMods
- Software System Overview
- Software Overview
- Sensor Calibration
- OpenHAB Configuration
- Testing Your IoT Device
- Conclusion
- References Used
.
Series Links
To Part 9 : IoT Mains Controller. Part 9 : IoT, Home Automation
To Part 11 : IoT Desktop Console. Part : 11 IoT, Home Automation
Circuit Overview
![Cct1.png](/proxy/?url=https://content.instructables.com/FZZ/E554/JASJJWLA/FZZE554JASJJWLA.png&filename=Cct1.png)
![SAM_1633.JPG](/proxy/?url=https://content.instructables.com/FQD/MO4Q/JAMTT66C/FQDMO4QJAMTT66C.jpg&filename=SAM_1633.JPG)
![SAM_1648.JPG](/proxy/?url=https://content.instructables.com/FCY/4NLF/JASJJCL8/FCY4NLFJASJJCL8.jpg&filename=SAM_1648.JPG)
Overview
The circuit diagram above details the two constituent parts to this device.
- The main controller unit enabling IoT functionality
- IR sender unit
In creating the design it was decided to use only 3v3 parts to minimise the complexity (no requirement for multiple supply rails), lower power consumption and take to advantage of the ready availability of +5v USB PSUs within the household.
Main Controller Unit
This circuit consists of an ESP8266-12E which is connected to the following peripheral devices;
- SD Card reader (SPI interface, J1)
- Used to hold WiFi Network Security details, sensor calibration values and local satellite television channel/remote keypress combinations.
- I/O Expander (I2C interface, IC1)
- Outputs : System Led (LED6), Busy Led (LED5), and IR Sender unit reset input (U2 pin 1)
- Inputs : Busy line from IR sender unit (U2 pin 6)
- IR sender unit controller (ATMega328P via I2C interface, U2). See here
- Used to stack multiple IR button press combinations and control the modulation of the IR leds housed in the IR Sender unit.
- DHT22 Temperature and humidity sensor (single wire interface, J11)
- BH1750 Ambient Light Sensor (I2C interface, J2)
Note 1 : Whilst this diagram is shown as one circuit, to practically implement in a restricted volume enclosure it was broken down into two parts and split across an upper and lower board (see construction details below). Here the I/O expander (IC1) and IR sender unit controller (U2) reside on the lower board and everything else on the top. Electrical connections between boards is via a 10 way IDC.
Note 2 : In the final design the 3v3 V.Reg IC2 is mounted off board, on the side of the enclosure to expose the heat-sink to outside ambient air. This stops the heat being dissipated from the 3v3 regulator artificially raising the output of the DHT22 temperature sensor placed in the top of the unit.
.
IR Sender Unit
This unit houses three IR leds (LED2...4) and a 3mm Red Led (LED1) connected in parallel and controlled via Q2 a BC337 NPN BJT. The 3mm Red Led is used as a visual indication the IR Leds are being activated.
There is also some smoothing capacitance provided by C2 a 220uF Electrolytic and supply rail decoupling with C3 0.1uF.
To further reduce the possibility of RF noise (from the ESP8266) causing spurious activation of Q2, a small 10pF capacitor C1 ties the base to ground.
.
Prototyping the circuit
The second picture above is is that of a prototype construction which was assembled to be as close a facsimile to the target electronics as practically possible. Specifically a long lead between the IR controller output (U2 pin 5) and IR sender unit was trialed to ensure the 38kHz (typical) modulation frequency did not degrade. The image shows transistor Q2 BC337 mounted close to U2, though a layout with Q2 mounted nearest IR leds LED2...4 was also tested (third picture above) along with some extra capacitance C2 (to prevent IR sender unit supply rail droop during output modulation) which yielded the best results. The latter design was finally chosen.
Main Controller Unit Construction and Assembly Details
![boards1.png](/proxy/?url=https://content.instructables.com/FQC/03CX/JAMTT6QQ/FQC03CXJAMTT6QQ.png&filename=boards1.png)
![boards.png](/proxy/?url=https://content.instructables.com/F2B/BSZV/JAMTT6U7/F2BBSZVJAMTT6U7.png&filename=boards.png)
![SAM_1697.JPG](/proxy/?url=https://content.instructables.com/FHG/4NUO/JAMTT6UF/FHG4NUOJAMTT6UF.jpg&filename=SAM_1697.JPG)
![SAM_1712.JPG](/proxy/?url=https://content.instructables.com/FEC/Q1V3/JAMTT6XP/FECQ1V3JAMTT6XP.jpg&filename=SAM_1712.JPG)
![SAM_1750.JPG](/proxy/?url=https://content.instructables.com/FKW/DS10/JAMTT4T7/FKWDS10JAMTT4T7.jpg&filename=SAM_1750.JPG)
![SAM_1824.JPG](/proxy/?url=https://content.instructables.com/FBZ/3DLH/JAMU32O1/FBZ3DLHJAMU32O1.jpg&filename=SAM_1824.JPG)
![SAM_1733.JPG](/proxy/?url=https://content.instructables.com/FIJ/7VL7/JAMTT4Q3/FIJ7VL7JAMTT4Q3.jpg&filename=SAM_1733.JPG)
![SAM_1740.JPG](/proxy/?url=https://content.instructables.com/FN2/E1HN/JAMTT4QZ/FN2E1HNJAMTT4QZ.jpg&filename=SAM_1740.JPG)
![SAM_1731.JPG](/proxy/?url=https://content.instructables.com/FKR/ZPZA/JAMTT4XP/FKRZPZAJAMTT4XP.jpg&filename=SAM_1731.JPG)
![SAM_1726.JPG](/proxy/?url=https://content.instructables.com/FX8/RH1M/JAMTT523/FX8RH1MJAMTT523.jpg&filename=SAM_1726.JPG)
![SAM_1718.JPG](/proxy/?url=https://content.instructables.com/F9Q/0Y2U/JAMTT4ZX/F9Q0Y2UJAMTT4ZX.jpg&filename=SAM_1718.JPG)
![PinOutTopBoard.JPG](/proxy/?url=https://content.instructables.com/FPG/79LN/JAMU346N/FPG79LNJAMU346N.jpg&filename=PinOutTopBoard.JPG)
![PinOutBottomBoard.JPG](/proxy/?url=https://content.instructables.com/F5E/DQRR/JAMU345V/F5EDQRRJAMU345V.jpg&filename=PinOutBottomBoard.JPG)
The Main Controller Unit was a little tricky to fabricate and took the most time by far to ensure it was a good job.
Oddly I started with choice of enclosure first (this was the smallest form factor I thought I could get away with which had a dull finish), I then sited the SD card. The biggest module by far. I tried many positions and orientations to make best use of the available space. Once I had settled on the position I fitted the SD card after cutting the mounting holes and filing the surfaces to give a 'perfect fit'. When I say 'perfect fit' I mean 'perfect fit'. It took days to get it just right. You can see from picture 5 above, there are no gaps between the plastic enclosure and where the SD module protrudes through the box wall. To improve the fit I even filed off 0.5mm diagonally from the leading edge of the SD card PCB (over the full 30mm width). This was because the enclosure walls are slightly wider at the top than the bottom and this allowed the bottom edge of the SD card holder to sit flush with the outside of the enclosure.
Once the SD card was fitted I created a cardboard template I could use to form the veroboards (pic 1 above). The template was necessary to maximise the use of the available space in the enclosure. I carefully cut the veroboards keeping as much of the board intact as possible (pic 2). You'll note from the pictures above I even filed out a 0.1" by 0.2" slot to accommodate the M3 standoffs used to mount the rear of the SD card module.
With the boards fabricated I designed the layout (see here for how to design circuits with veroboard) and put the track cuts in place (see pics 3 & 4).
Next I positioned the boards in the enclosure and selected the appropriate length standoffs to correctly space the cards and sited the IR Sender Unit connector, Power supply connector and 3v3 V.Reg (pic 5) accordingly. I also measured up and drilled out the holes for the system and busy leds. Only with the boards in place can you workout where it is safe to locate the various items which will protrude into the available internal space. Unless of course you are a genius with AutoCAD 360, which I am not.
I then populated the boards with all the components (pic 6).
With the boards complete I made off the interconnection IDC ribbon cable, crimped the wires for the molex connectors and assembled them. I decided to use connectors for all subsystems allowing for full disassembly without the need to de-solder anything (pics 7 & 8).
With the located subsystem boards in place and fully interconnected I sited the DHT22 and BH1750 sensors. This was to ensure there was sufficient clearance under the lid when closed (pics 9 & 10).
Once assembly was fully complete (pic 11) I continuity checked the circuit, applied power, checked supply to all components and peripherals. I then removed power, fitted the SD Card, ICs and ESP8266 (which were all pre-programmed), re-applied power (checking for 'magic smoke', there wasn't any) and ran the pre-written test scripts.
It passed without any issues.
.
Note : Pics 12 and 13 detail the board connector pinouts. These connectors also include the programming interface connections for the ESP8266-13E and the ATMega328P.
Ambient Light Sensor RetroMods
![SAM_1606.JPG](/proxy/?url=https://content.instructables.com/FST/1OTL/JAMTT666/FST1OTLJAMTT666.jpg&filename=SAM_1606.JPG)
![SAM_1616.JPG](/proxy/?url=https://content.instructables.com/F1F/W9Q7/JAMTT6OQ/F1FW9Q7JAMTT6OQ.jpg&filename=SAM_1616.JPG)
The on board 3v3 regulator was removed from the BH1750 module and bridged out as shown in the two pictures above.
SD Card Holder RetroMods
![SAM_1469.JPG](/proxy/?url=https://content.instructables.com/FAY/N7UD/JAMTT6UA/FAYN7UDJAMTT6UA.jpg&filename=SAM_1469.JPG)
![SAM_1471.JPG](/proxy/?url=https://content.instructables.com/F9K/6JV2/JAMTT6UD/F9K6JV2JAMTT6UD.jpg&filename=SAM_1471.JPG)
Using the same technique as above, the on board 3v3 regulator was removed from the SD card reader and also bridged out as shown in the two pictures above.
IR Sender Unit RetroMods
![SAM_1635.JPG](/proxy/?url=https://content.instructables.com/FRF/5PQ8/JAMTT5ZB/FRF5PQ8JAMTT5ZB.jpg&filename=SAM_1635.JPG)
![SAM_1641.JPG](/proxy/?url=https://content.instructables.com/F1L/66OA/JAMTT62V/F1L66OAJAMTT62V.jpg&filename=SAM_1641.JPG)
![SAM_1644.JPG](/proxy/?url=https://content.instructables.com/F7C/ATG4/JAMTT62Y/F7CATG4JAMTT62Y.jpg&filename=SAM_1644.JPG)
![SAM_1667.JPG](/proxy/?url=https://content.instructables.com/FRJ/7A2W/JAMTT5RL/FRJ7A2WJAMTT5RL.jpg&filename=SAM_1667.JPG)
![SAM_1659.JPG](/proxy/?url=https://content.instructables.com/FM1/F89R/JAMTT5MF/FM1F89RJAMTT5MF.jpg&filename=SAM_1659.JPG)
![SAM_1677.JPG](/proxy/?url=https://content.instructables.com/FXG/3VRX/JAMTT5KR/FXG3VRXJAMTT5KR.jpg&filename=SAM_1677.JPG)
To house the IR Transmitter I decided to re-purpose and retrofit the electronics into an IR receiver unit from a TV Link Device (pic 1) for the following reasons;
- It's general aesthetic quality. The surface finish is the same as the main controller unit enclosure, consequently matched well,
- Given it was originally used to house an IR receiver it would aximomatically work with an IR transmitter.
I dismantled the device (pics 2 & 3) and using a Dremel ground off the separation wall and lowered two support posts to maximise the available space and accommodate a retrofitted veroboard circuit (pic 4).
The veroboard insert was created by fashioning a cardboard template as shown above (pic 5) and transferring this correctly dimensioned template onto veroboard (again pic 5).
I then soldered all the parts in place as shown in the last picture (pic 6). It's not possible to see all the parts as the 4 ballast resistors for the leds are SMD and mounted on the underneath.
Note 1 : When the IR enclosure was first dismantled it contained a large piece of mild steel ballast (pic 3). Unfortunately the height of this elevated the veroboard within the enclosure to such an extent it wasn't possible to close the case. To remedy this I replaced the mild steel with a small piece of lead flashing (not shown).
Note 2 : As 'belt and braces' I also added an inline Ferrite Bead (BL01RN1A1D2B) marked in pic 6. This isn't listed in the BoM.
Software System Overview
![SoftSysComp.jpg](/proxy/?url=https://content.instructables.com/FS1/7NH6/JAWTSA7H/FS17NH6JAWTSA7H.jpg&filename=SoftSysComp.jpg)
![Memory.jpg](/proxy/?url=https://content.instructables.com/F9Z/H18V/JAWTSA43/F9ZH18VJAWTSA43.jpg&filename=Memory.jpg)
This IoT Universal Remote Control device contains six key software components as shown in pic 1 above.
SD Card
This is the external SD SPI Flash Filing System and is used to hold the following information (see pic 2 above);
- Icons and 'IR Remote Control Configuration Home Page' html: Served up by the IoT device when it is unable to connect to your IoT WiFi network (usually due to incorrect security information, or first time use) and provides the user with a means of remotely configuring the sensors without the need to re-flash new SD content.
- Security Information: This holds the information used at power up by the IoT device to connect to your IoT WiFi network and MQTT Broker. Information submitted via the 'IR Remote Control Configuration Home Page' is written to this file ('secvals.txt').
- Calibration Information: The information contained within this file ('calvals.txt') is used to calibrate the on-board temperature/humidity sensor should it be necessary. Calibration constants can be written to the IoT device via MQTT commands from an MQTT broker or by re-flashing the SD card.
- Television channel Alias/Value file : ('alivals.txt') contains the pairing of an Alias for a given TV channel and the corresponding numerical remote control button press sequence. Editing this file allows the user to add or remove channels without the need to recompile the software.
.
mDNS Server
This functionality is invoked when the IoT device has failed to connect to your WiFi network as a WiFi station and instead has become a WiFi access point something akin to a domestic WiFi router. In the case of such a router you would typically connect to it by entering the IP Address of something like 192.168.1.1 (usually printed on a label affixed to the box) directly into your browser URL bar whereupon you would receive a login page to enter the username and password to allow you to configure the device. For the ESP8266-12E in AP mode (Access Point mode) the device defaults to the IP address 192.168.4.1, however with the mDNS server running you only have to enter the human friendly name 'IRREMSIM.local' into the browser URL bar to see the 'IR Remote Control Configuration Home Page'.
.
MQTT Client
The MQTT client provides all the necessary functionality to; connect to your IoT network MQTT broker, subscribe to the topics of your choice and publish payloads to a given topic. In short it provisions IoT core functionality.
.
HTTP Web Server
As mentioned above, if the IoT device is unable to connect to the WiFi network whose SSID, P/W etc. is defined in the Security Information file held on the SD Card the device will become an Access Point. Once connected to the WiFi network provided by the Access Point, the presence of an HTTP Web Server allows you to directly connect to the device and change it's configuration via the use of an HTTP Web Browser it's purpose being to serve up the 'IR Remote Control Configuration Home Page' web page which is also held on the SD Card.
.
WiFi Station
This functionality gives the IoT device the capability to connect to a domestic WiFi network using the parameters in the Security Information file, without this your IoT device will not be able to subscribe/publish to the MQTT Broker.
.
WiFi Access Point
The ability to become a WiFi Access Point is a means by which the IoT device allows you to connect to it and make configuration changes via a WiFi station and a browser (such as Safari on the Apple iPad).
This access point broadcasts an SSID = "IRREMSIM" + the last 6 digits of the MAC address of the IoT device. The password for this closed network is imaginatively named 'PASSWORD'
Software Overview
![StateMachine.jpg](/proxy/?url=https://content.instructables.com/FWB/LDOJ/JAMU3HGB/FWBLDOJJAMU3HGB.jpg&filename=StateMachine.jpg)
![LogIn.png](/proxy/?url=https://content.instructables.com/F3J/JAWT/JB3ZP21O/F3JJAWTJB3ZP21O.png&filename=LogIn.png)
![IRCommand.jpg](/proxy/?url=https://content.instructables.com/F3I/6RPO/JB6U3C7B/F3I6RPOJB6U3C7B.jpg&filename=IRCommand.jpg)
![IRCommandPartRaw.jpg](/proxy/?url=https://content.instructables.com/FYJ/EG4O/JB6U3C7N/FYJEG4OJB6U3C7N.jpg&filename=IRCommandPartRaw.jpg)
![IRCommandRaw.jpg](/proxy/?url=https://content.instructables.com/FWA/1IRU/JB6U3CFZ/FWA1IRUJB6U3CFZ.jpg&filename=IRCommandRaw.jpg)
![IRPS1.jpg](/proxy/?url=https://content.instructables.com/FMA/S84Q/JB6U98ZN/FMAS84QJB6U98ZN.jpg&filename=IRPS1.jpg)
![IRPS2.jpg](/proxy/?url=https://content.instructables.com/FHR/9AEG/JB6U98ZL/FHR9AEGJB6U98ZL.jpg&filename=IRPS2.jpg)
![CommsStateMachine.jpg](/proxy/?url=https://content.instructables.com/F53/YCIV/JAMU3HEI/F53YCIVJAMU3HEI.jpg&filename=CommsStateMachine.jpg)
![IRDevStateMachine.jpg](/proxy/?url=https://content.instructables.com/FE7/W4CW/JAMU3HEN/FE7W4CWJAMU3HEN.jpg&filename=IRDevStateMachine.jpg)
![LL1.jpg](/proxy/?url=https://content.instructables.com/FGT/Y66G/JAMU3HES/FGTY66GJAMU3HES.jpg&filename=LL1.jpg)
![LL2.jpg](/proxy/?url=https://content.instructables.com/FL6/MJVL/JAMU3HEU/FL6MJVLJAMU3HEU.jpg&filename=LL2.jpg)
![NamingConvention.jpg](/proxy/?url=https://content.instructables.com/FK0/L4K1/JB3ZP44E/FK0L4K1JB3ZP44E.jpg&filename=NamingConvention.jpg)
Preamble
To successfully compile this source code you will need the following extra libraries;
PubSubClient.h
- By : Nick O'Leary
- Purpose : Enables the device to publish or subscribe to MQTT topics with a given Broker
- From : https://github.com/knolleary/pubsubclient
DHT.h
- By : Adafruit
- Purpose : Library for DHT Temperature/Humidity Sensor
- From : https://github.com/adafruit/DHT-sensor-library
BounceI2C.h
- By : Steve Quinn
- Purpose : Allows switch debouncing over an I2C input device. This is a GITHub fork from Bounce2.h by Thomas O Fredericks.
- From : https://github.com/SteveQuinn1/BounceI2C
BH1750.h
- By : claws
- Purpose : An Arduino library for the digital light sensor breakout boards containing the BH1750
- From : https://github.com/claws/BH1750
Code Overview
The software makes use of the state-machine as shown in pic 1 above (full copy of source here). There are 5 main states as below;
- INIT
- This initialisation state is the first state entered after power up. During this state the Alias/Value file ('alivals.txt') is read with a call to 'readAliasValueInput();'. This TV Channel ID Alias versus IR remote key press is loaded into a linked list, a dynamic data structure for use when connected/active. See Linked list below.
- NOCONFIG
- This state is entered if after power up an invalid or missing secvals.txt file is detected
- PENDING NW
- This state is transitory, entered whilst there exists no WiFi network connection
- PENDING MQTT
- This state is transitory, entered after a WiFi network connection has been made and whilst there exists no connection to an MQTT broker on that network.
- ACTIVE
- This is the normal operational state entered once both a WiFi network connection and an MQTT Broker connection has been established. It is during this state the ambient light level, temperature and humidity at the IR Universal Controller is regularly published to the MQTT Broker.
The events controlling transitions between states are described in pic 1 above. Transitions between states is also governed by the following SecVals parameters;
- 1st MQTT Broker IP Address. In dotted decimal form AAA.BBB.CCC.DDD
- 2nd MQTT Broker Port. In Integer form.
- 3rd MQTT Broker connection attempts to make before switching from STA mode to AP mode. In Integer form.
- 4th WiFi Network SSID. In free form text.
- 5th WiFi Network Password. In free form text.
As mentioned above if the IoT device is unable to connect as a WiFi Station to the WiFi network who's SSID and P/W is defined in secvals.txt held on the SD Card the IoT device will become an Access Point. Once connected to this access point it will serve up the 'IR Remote Control Configuration Home Page' as shown above in Pic 2 (by entering either 'IRREMSIM.local' or 192.168.4.1 into your browsers URL address bar). This home page allows the reconfiguration of the IR Universal Remote Controller via an HTTP browser.
Remote Access whilst in the ACTIVE state
Once connected to the MQTT Broker it is also possible to both re-calibrate and reconfigure the device via MQTT topic publications. The file calvals.txt has R/W access and secvals.txt has write only access exposed.
.
User debug
During the boot sequence the IoT device blue System led gives the following debug feedback
- 1 Short flash : No Config file located on SD Card (secvals.txt)
- 2 Short flashes : IoT device is attempting to connect to WiFi network
- Continuous illumination : IoT device is attempting to connect to MQTT Broker
- Off : Device is active.
During IR code transmission the IoT device red Busy led will remain illuminated during the transmission of the complete sequence. Also, the small red led housed in the IR Sender Unit will flash at the same rate as the modulation frequency.
.
IR Remote Control Functionality in ACTIVE State
The IR Remote controller has three different ways of being commanded over MQTT;
- IR Command : A human readable format providing simple to understand control of a Home IR device
See Picture 3 above for full details - IR Command Part Raw : A human readable format providing simple to understand control of a Home IR device, exposing two numerical parameters to allow prolonged/repeated button presses to be simulated
See Picture 4 above for full details - IR Command Raw : This exposes a complex API allowing full control of the IR Sender Unit
See Picture 5 above for full details
In each case the IoT Universal IR Remote Controller will respond to an IR Command via publication on the topic 'WFD/IRTHSen/1/Rem/Conf'. The payload response for which is numeric, the return value is dependent upon the command being issued. Full details of return values are documented in the source code.
IR Commands sent to the controller are either buffered or sent direct to the IR Sender Unit (after decoding in the case of a compound command) dependent upon the FreshData flag. Full examples are documented in the source code.
.
Communication between the ESP8266-12E and IR Sender Unit Controller (U2) is over I2C (see here). Fixed format command packets are sent to the Controller, which stacks them into an internal buffer until signaled by the ESP8266 to start sending IR remote control packets again by the FreshData flag (see pics 6 and 7 above). In this way the processing load on the ESP8266 is reduced to a minimum.
As mentioned above the trigger for the controller to start sending is by setting the FreshData flag to 'Non-Zero' in the final command packet. The IR controller now asserts it's busy line (pic 6) and commences sending the IR codes stored in it's buffer via the IR Sender Unit. Once compete the IR controller de-asserts the busy line indicating to the ESP8266 and is now available to receive more IR remote control packets (pic 7).
To ensure no IR remote control packets are lost (flow control is implemented back into the MQTT network), partially filled buffers are flushed after a pending timer (command buffer inactivity timer), and the controller never hangs for any reason (busy timer). A series of nested state machines are implemented. These state machines are given above in pics 8 and 9.
.
Use of linked lists
A linked list is a dynamic data structure, similar to an array, differing in so far as it is created with no elements and dimensioned whilst the programme is running. This means the size of the array does not have to be known when the source code is compiled. A linked list (or more accurately a singly linked list in this case, 'ptrHeadOfAliasValueInstances') is used here to allow the addition/removal of satellite television channels without the need to recompile the source code. All the user needs to do is remove power, extract the SD card, edit the 'alivals.txt' file and re-insert. Once the universal remote control power supply is reconnected the software will re-read 'alivals.txt' and add/remove the channel of interest.
During normal operation in the Active state, when a 'WFD/IRTHSen/1/Rem/Command/1' topic is published with a compound command ie. 'chan' containing a channel name alias ie 'BBC1' the software will scan the linked list to see if there is an entry containing the same alias, if there is it will extract the corresponding numeric button presses and queue them in a command buffer for transfer to the IR transmitter device then publish a confirmation payload of '0' via a publication on 'WFD/IRTHSen/1/Rem/Conf'. If no entry is located the response will be Error Code 9 : 'Unable to find Alias in this topic payload'
Picture 10 illustrates linked lists of various lengths and picture 11 depicts how a new element is added to the end of a linked list (the action at start up).
.
Simple cooperative RTOS
As mentioned in the introduction, this code also contains a simple implementation of a cooperative RTOS. To achieve this the none of the code in the loop() function is 'blocking' ie. results in an indefinite loop. Here the functions; timer_update(), doRemoteCommandUpdate(), doIRDeviceUpdate(), checkALSValue(), checkTemperatureAndHumidity() are iteratively executed on each successive pass through the loop() giving control back when complete (ie. not pre-emptive). The outcome of each repetitive execution is dependent upon state variables or timer call back routines each of which independantly changing. In this way the code is effectively handling many pseudo simultaneous tasks.
.
MQTT Topic naming convention
Outlined in pic 12 above is the naming convention used for the MQTT topics and is consistent with the pattern used in my earlier Instructable (here Step 5).
.
Note 1 : The 'IR Remote Control Configuration Home Page' does not use secure sockets and therefore relies on your network being secure.
Note 2 : The source code for this instructable can be downloaded here (ESP8266-12E) and here (ATmega328P U2). See here for details on how to programme the ATMega328P
Sensor Calibration
![SensorCal.jpg](/proxy/?url=https://content.instructables.com/FLP/GR8Q/JB6U8WNB/FLPGR8QJB6U8WNB.jpg&filename=SensorCal.jpg)
When the IoT device powers up, as part of the boot sequence a file named 'cavals.txt' is read from the SD Card. The contents of this file are calibration constants as indicated above in pic 1. These calibration constants are used to adjust the readings acquired from the sensor to bring them into line with a reference device. There is one further value which defines a reporting strategy for the device and is described below along with the procedure followed to calibrate the sensors.
.
Reporting Strategy
This parameter determines how the remote sensor reports any ambient parametric changes local to it. If a value of 0 is selected the remote sensor will publish any change it sees in the temperature, humidity or Ambient Light Levels each time the respective sensor is read (approx every 10 seconds). Any other value will delay the publication of a change by 1...60 minutes. Modifying this parameter allows for optimisation of MQTT network traffic.
.
Temperature calibration
To calibrate the temperature sensor I followed the same process as outlined here step 4, again using a simple y=mx+c relationship. I used IoT Temperature, Humidity Sensor #1 as the reference device.
.
Humidity Calibration
As I possess no means to accurately record or even control local ambient humidity, to calibrate the sensor I used a similar approach to that above here step 4, again using Sensor #1 as reference.
However the above said, I have recently found an excellent article on the web describing how to calibrate humidity sensors. I may well try this approach in the future.
.
Ambient Light Sensor
The datasheet for this device indicated sufficient accuracy to not require any calibration and therefore I didn't export any parameters in calvals.txt for this sensor.
OpenHAB Configuration
![MainScreen.jpg](/proxy/?url=https://content.instructables.com/FR1/JOZJ/JAWU0NVH/FR1JOZJJAWU0NVH.jpg&filename=MainScreen.jpg)
![LivingRoomScreen.jpg](/proxy/?url=https://content.instructables.com/F5K/6GFK/JAWU0NUD/F5K6GFKJAWU0NUD.jpg&filename=LivingRoomScreen.jpg)
![EntertainmentSystemsScreen.jpg](/proxy/?url=https://content.instructables.com/F2S/N7UU/JAWU0NX9/F2SN7UUJAWU0NX9.jpg&filename=EntertainmentSystemsScreen.jpg)
![ALS.jpg](/proxy/?url=https://content.instructables.com/F1N/50RN/JAWU96Q4/F1N50RNJAWU96Q4.jpg&filename=ALS.jpg)
![OpenHABImportantFiles.jpg](/proxy/?url=https://content.instructables.com/F10/URRV/JAWU94B7/F10URRVJAWU94B7.jpg&filename=OpenHABImportantFiles.jpg)
I modified the OpenHAB configuration given in my earlier IoT Instructables (here, here and here) and under the 'Living Room' page added in a new entry for 'Entertainment Systems' in pic 2 above.
This new sitemap contains seven buttons allowing the user to switch on and off each AV device, cancel the Sony TV's 'auto off' function, Volume UP/Down and mute (See pic 3 above). I stopped short of adding further functionality as I want to include this in a voice recognition project.
I also went on to integrate the ambient light sensor, temperature, humidity and RSSI (Received Signal Strength Indication). into the respective site maps (see pic 4 above).
Finally, I moved the existing living room sensor into the 'Loft' and added a new entry to the home page pic 1 above
.
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 5.
.
Note 1 : If you're not sure how to use OpenHAB see here 'Setting Up and Configuring OpenHAB. Part 6 : IoT, Home Automation'
Note 2 : A copy of the modified sitemap, rules and items files, Icons etc. is given below.
Downloads
Testing Your IoT Device
![SystemTest.jpg](/proxy/?url=https://content.instructables.com/FFH/29J4/JASJUTQI/FFH29J4JASJUTQI.jpg&filename=SystemTest.jpg)
![TestExec.jpg](/proxy/?url=https://content.instructables.com/F3Y/LCMT/JASJUTN8/F3YLCMTJASJUTN8.jpg&filename=TestExec.jpg)
![MsgSeq.jpg](/proxy/?url=https://content.instructables.com/FLB/EJP9/JB2JNYF4/FLBEJP9JB2JNYF4.jpg&filename=MsgSeq.jpg)
![When1.jpg](/proxy/?url=https://content.instructables.com/FVL/CX3X/JAWTVLP1/FVLCX3XJAWTVLP1.jpg&filename=When1.jpg)
![When2.jpg](/proxy/?url=https://content.instructables.com/F2J/Y5FN/JAWTVLP2/F2JY5FNJAWTVLP2.jpg&filename=When2.jpg)
![When3.jpg](/proxy/?url=https://content.instructables.com/FF5/EIJR/JAWTVLP3/FF5EIJRJAWTVLP3.jpg&filename=When3.jpg)
![Testing an IoT Universal IR Remote Controller](/proxy/?url=https://content.instructables.com/FL3/BBAF/JB2JNO5U/FL3BBAFJB2JNO5U.jpg&filename=Testing an IoT Universal IR Remote Controller)
General
Throughout this series on IoT I have opted to use MQTTSpy to carryout the testing on what for the most part are simple devices. Picture 1 above depicts the system configuration for simple manual testing.
MQTTSpy was chosen because it is an excellent tool to hand format a given payload and publish it to any topic with ease. It also displays a clear log which is very useful for debugging.
However, given the software in this device is starting to become more complex (>4000 lines) it will also become more time consuming to test accurately and quickly.
Even making a small change/fix in a given area of the code can potentially introduce a risk the software may 'break' elsewhere. To have to retest your code manually each time you make a change is a very inefficient practice.
The Test Executive
This instructable sees a departure from the earlier manual testing methodology and introduces automated testing (pic 2).
At the heart of this automated testing I wrote a Python script to create what is known as a test executive.
A test executive is just a fancy way to say a piece of code which takes some form of input (generally a text script of some form, an excel spread sheet in this case) and uses this to execute a given test (whatever that test may be).
Here the input is a single or multiple spread sheet(s) forming suite of tests. Where each worksheet is a single test comprising either a single or multiple steps (rows).
All tests are based on a command/response principle. Here a command will be the publish of a 'Message' with a 'Payload' from the Test Executive, followed by the receipt of a 'Response' with a 'Payload' from the Unit Under Test (UUT). See Pic 3 above.
Each row comprises the following;
- Instruction :
- Message : Denotes this row is an MQTT Command/Response message
- Delay : Simple delay in mS between steps
- Message :
- Topic to be published. ie. WFD/5c:cf:7f:86:9c:82/SwVer/Command
- Payload :
- Payload of outgoing topic ie. '*'. Special case * means don't care, nothing
- Response :
-
Topic to subscribe to in order to receive response ie. WFD/IRTHSen/SwVer/Confirm
-
- Payload :
-
Payload of incoming topic ie. '*'. Special case * means don't care
-
- Delay :
- The delay 'T' in mS the executive should wait before evaluating the 'When' condition.
- When : (See Pics 4, 5 & 6 above for further details)
- B : Before
- A : After
- NFT : Nothing for time T
- NBT : Nothing before time T
- SBT : Something before time T
- Comment :
- Free form text outlining the purpose of the instruction
When each test executes it generates a 'time stamped log' of each command and response. At the end of execution a pass/fail summary is issued.
.
This was my first attempt at using Python and found the above commands and functionality were sufficient to get reasonable test coverage for this project. I intend to further develop this tool and add more scripts as I go along.
.
The video above shows the execution of the 'MQTTWiFiIRDeviceRealScenario.xlsx' from the command line and MQTTSpy to view the MQTT message traffic. This test scenario carries out the following sequence;
- TV on
- Sound Bar on
- Sky Box On
- Turn to channel BBC1
- Mute Sound Bar
- Turn to channel ITV
- Un-Mute Sound Bar
- Simulate button '1' pressed
- Simulate button '0' pressed
- Simulate button '2' pressed
- Simulate button 'select' pressed
- Sound Bar Vol Down 5
- Sound Bar Vol Up 5
- TV Off
- Sound Bar Off
- Sky Box Off
.
Python Development
I used the PyCharm comunity edition (2017.2.3) IDE by JetBrains with Python v3.5.2.
You'll also need the following modules;
- paho-mqtt 1.3.0 for MQTT client functionality
- OpenPyXL 2.5.0a3 for Microsoft excel access
.
Note 1 : All the above information is also documented in the python script.
Note 2 : I have included a copy of the log file taken from the actual test run below.
Downloads
Conclusion
![conclusion.jpg](/proxy/?url=https://content.instructables.com/F69/UMVL/JAWTS01E/F69UMVLJAWTS01E.jpg&filename=conclusion.jpg)
The design turned out to be pretty robust, building on the core software developed for the IoT Temperature and Humidity sensor platform. At the time of writing this instructable the device has been running now for over a month without any issues, responding flawlessly to random commands to change channel, raise volume, turn on/off etc.
The values streaming from the local sensors look accurate (at least T & H) and keep coming.
With hindsight I would have done the following differently;
- For the Ambient light sensor I used a light pipe from Farnell (in reverse) guiding the external ambient light onto the BH1750 sensor in the enclosure lid. This turned out to be an expensive decision and could equally been replaced by a clear led with bottom cut off. For the third integration of the BH1750 I'll go down the LED route. Why the third you ask? I made the mistake of buying two in case I damaged one.
- It would have been a better design decision to have used a constant current source to switch the diodes in the IR sender unit. This would have potentially given better output from the IR Leds. See here Step 7, for typical circuit.
- After studying the code you may be asking yourself why did I use a linked list 'ptrHeadOfAliasValueInstances' for the channel alias/button press look up and not an array or even the converse for the 'remoteControlButtonType' arrays in 'IRCodes.h'. After all there's no difference right? To some extent this is true. In fact I had intended to use Json for both but abandoned this idea (see below). Instead I opted for the final solution by way of a compromise. Had everything been in linked lists it would have created a noticeable delay in decoding long command sequences. Also in our house hold we don't change the AV system that often so I figured I would only have to recompile the code two or three more times before I'm too old to care about television. However, Sky (before Rupert Murdoch sold a 30% stake in it) do have a habit of adding random channels at various times, such as for the Olympics or Christmas etc. so an easily editable configuration without the need to compile is an advantage.
Finally, I had intended to use the Arduino Json library to enable device configuration but after wrestling with it for some time I decided against it. To be honest whilst I'm sure the library is a brilliant piece of C++ it was in parts unintelligible and sucked all the ram out of the system when in use, so I removed the code.
It's a rule, for constrained devices (ie. an IoT device with little memory) never use code which drains RAM, as you generally don't have much available.
.
Full disclosure : I developed the linked list functionality using Microsoft Visual Studio and ported it over as the Arduino IDE is woefully inadequate to develop code of any reasonable complexity.
References Used
The following sources were used to put this Instructable together;
Source code for IoT IR Universal Remote control
- https://github.com/SteveQuinn1/I2C-IR-Remote-Controller-With-Arduino
- https://github.com/SteveQuinn1/IoT-Universal-IR-Remote-Controller
PubSubClient.h
- By : Nick O'Leary
- Purpose : Enables the device to publish or subscribe to MQTT topics with a given Broker
- From : https://github.com/knolleary/pubsubclient
BounceI2C.h
- By : Steve Quinn
- Purpose : Allows switch debouncing over an I2C input device. This is a GITHub fork from Bounce2.h by Thomas O Fredericks.
- From : https://github.com/SteveQuinn1/BounceI2C
DHT.h
- By : Adafruit
- Purpose : Arduino library for DHT11DHT22, etc Temp & Humidity Sensors
- From : https://github.com/adafruit/DHT-sensor-library
BH1750.h
- By : claws
- Purpose : An Arduino library for the digital light sensor breakout boards containing the BH1750
- From : https://github.com/claws/BH1750
.
TV Link
Adding Extra tabs in Arduino IDE
stristr (implementation for the ESP8266)
isNumber (implementation for the ESP8266)
IR Remote information
F() Memory
To avoid data structure padding to word boundaries
- https://github.com/esp8266/Arduino/issues/1825
- https://github.com/tuanpmt/esp_bridge/blob/master/modules/include/cmd.h#L15
- https://stackoverflow.com/questions/11770451/what-is-the-meaning-of-attribute-packed-aligned4
Generic information on I2C
- https://playground.arduino.cc/Main/WireLibraryDetailedReference
- https://www.arduino.cc/en/Reference/WireSend
Json (Ok, I didn't use it in the end but thought it was worth putting in the references)
- https://github.com/esp8266/Arduino/blob/master/libraries/esp8266/examples/ConfigFile/ConfigFile.ino
- https://www.youtube.com/watch?v=jIOTzaeh7fs
- http://www.jsoneditoronline.org/
- https://jsonformatter.org/
- https://www.w3schools.com/js/js_json_syntax.asp
- https://github.com/bblanchon/ArduinoJson
- http://www.json.org/
- https://en.wikipedia.org/wiki/JSON
IR Remote Control Devices
- https://learn.sparkfun.com/tutorials/ir-communication
- http://www.lirc.org/
- https://cdn-learn.adafruit.com/downloads/pdf/using-an-infrared-library.pdf
- http://www.analysir.com/blog/2013/11/22/constant-current-infrared-led-circuit/
- https://learn.adafruit.com/using-an-infrared-library/overview
- http://tech.cyborg5.com/2014/01/07/constant-current-ir-driver-circuit/
- http://www.righto.com/2010/03/understanding-sony-ir-remote-codes-lirc.html
- http://picprojects.org.uk/projects/sirc/sonysirc.pdf
- http://www.sbprojects.com/knowledge/ir/index.php
- http://www.zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
Wikipedia definitions
- https://en.wikipedia.org/wiki/Test_execution_engine
- https://en.wikipedia.org/wiki/Cooperative_multitasking
Calibrating Humidity Sensors
.