Automatic Light Switch on the Internet of Things

The creation of an automatic light switch using infrared tripwires.

Favorited Favorite 1


I just moved into my first new home and found the lighting situation in my garden-level office to be absolutely horrendous fluorescent tubes. For the time being I'm using two very large lamps, but I'm bad at remembering to turn them off when I leave, and getting across the room in the dark when I arrive is a dangerous affair. I decided to put my things on the Internet of Things by designing an automatic light switch using the SparkFun ESP8266 Thing Dev, SparkFun Quad Relay, and an infrared LED/receiver pair as a tripwire to turn the lights on and off. You can find all the parts I used for this project below.

Resistor Kit - 1/4W (500 total)

Resistor Kit - 1/4W (500 total)

SparkFun Qwiic Quad Relay

SparkFun Qwiic Quad Relay

SparkFun ESP8266 Thing - Dev Board

SparkFun ESP8266 Thing - Dev Board

Jumper Wires - Connected 6" (M/M, 20 pack)

Jumper Wires - Connected 6" (M/M, 20 pack)

IR Receiver Diode - TSOP38238

IR Receiver Diode - TSOP38238

Transistor - NPN, 50V 800mA (BC337)

Transistor - NPN, 50V 800mA (BC337)

LED - Infrared 950nm

LED - Infrared 950nm

Note!If you're interested in a hardware-focused tutorial on how to set up a 38kHz IR signal using a 555 timer, check out the Boss Alarm Tutorial.


The largest hurdle to this project was creating a 38kHz infrared signal that would act as an invisible tripwire to activate the lamps. The next hurdle was creating a second tripwire to act in conjunction with the first to accurately track people entering and exiting the room. Before we dive into the coding aspect of this project, first you must understand a smidge about infrared. Infrared is EVERYWHERE! Just outside of the visible spectrum, infrared is given off by our body in the form of heat, the sun blasts IR from space all the time and, not to be outdone, other stars share their IR with us as well. Because of this, the infrared tripwire must be modulated to be recognized by the IR receiver.

To create this signal I wanted to start from the ground up to get a better understanding of microcontroller timings. Generating a 38kHz signal from a SparkFun ESP8266 Thing operating at 32MHz will require some delays, but for how long? What will be the duty cycle of this signal, if any? To start I did some simple math:

Frequency of the SparkFun ESP8266 thing: 32MHz
Frequency of the IR signal: 38kHz
Number of cycles in one period of the IR signal (32MHz/38kHz): ~824.105
Period of one clock cycle for the ESP8266 Thing (time = 1/frequency): 31.25ns (wowzers)
Multiply the number of clock cycles to delay, by the length of the clock cycle: ~26.3us.
Final Result: ~26.3us

Logic Analyzer

Alright that's good enough for a starting point. If I did not have a logic analyzer at this point then I wouldn't be able to fine tune the signal to discover some other unknown time hang ups. I took the final result and wrote the IR LED high for half the calculated delay time using the delayMicroseconds() function (13us) and low for the other half (another 13us). Analyzing the signal showed that the signal was too slow, but why? After some investigation I found that writing the pin high takes some time to complete, which is not really something I've had to take into consideration before. I mean of course it does, but this is exactly the kind of stuff that is so great to come across when doing a project, because this is how I learn something new.

The time to write a pin high on an ESP8266 is approximately ~1.5us. Reducing the delay to about 23us gave just enough delay to generate a 37.89MHz wave which is enough for my purposes. Implementing the signal wasn't as successful. Looking at the datasheet for the IR receiver I discovered that blasting it with a IR signal continuously only forces the receiver to turn off signal capture for a time.

I searched our website for some help and came across Nate's tutorial on rebuilding the Lumitune, which really brought the whole thing together. If you look at the tutorial, he provides code for this large project that revolves around blocking an IR signal to play a piano key. In his code he simply pulsed the IR LED for a short burst and immediately read thereafter to see if it had been read. He delays for one millisecond between these bursts to keep from overloading the IR receiver. Of course! Sometimes you go down the rabbit hole and have a hard time getting perspective on your project. This is exactly what I needed to find. I set up the first and second IR transmitter/receiver pair and had two working tripwires. I futzed with the duty cycle to see how it affected the receiver, but found that 50 percent was sufficient.

This is screen shot of the logica analyzer display a 38kHz wave.
A screenshot from the logic analyzer of both the IR signal and just above, the IR receiver going low.

The Code

To have this work correctly I mentioned that my goal was to have two IR tripwires working together to determine whether a person was entering the room. With two I can determine whether a person is coming or going from the room, because it informs me of the direction they're walking.

Direction is vital because I can keep track of the number of people entering or exiting a room. By keeping track of the number of people in the room, I can prevent the lights from turning off whenever any one person departs the room and instead only when the room is empty. That's an important distinction and a common use case for my automatic light switch. Of course this is not a perfect system; I can imagine an instance where two separate people, one leaving and one entering, trigger both IR tripwires simultaneously. I can imagine a line of Redcoats walking down my hallway shoulder to shoulder, and my setup only senses one person when there are actually three in a line.

For all the edge use cases I'm simply going to put a button near the entrance to turn off the lights, and because we're on the internet, I'll be able to turn the lights on and off with my phone as well. To implement this well, I want the second IR tripwire to trigger after the first in a specific window of time so that I can accurately determine direction. Is there something else I should be considering? Let me know below.

The code for setting up two SparkFun EP8266's was not difficult. Our hookup guide shows how to set up a simple server and the client example code provided by Espresif was all I needed to get communication between the two working. Looking toward, the future I want the web page to have a better indicator for the lights. If you're interested in the code for your own project or are feeling curious, I've linked all the code below.

Infrared Circuit

Belolw is the circuit for the infrared tripwires. One thing to note is that the IR LED can use up to 50mA of current, which is more than the pin on the ESP8266 can provide. I use a NPN transistors with 68 Ohm resistors to provide the proper current. I actually breadboarded the circuit on two seperate breadboards so I could separate them as much as possible. However, the IR LEDs still managed to trigger the wrong receivers so I used aluminum foil to create a cone around each LED.

alt text

The ESP8266 controlling the SparkFun Qwiic Quad Relay was hooked up to the I2C pins. Check out the hookup guide for the Quad Relay if you want to know more. That's all, folks! In the GIF below I show a single lamp being turned with the specific order using the "direction" logic talked about in the code above, followed by the lights turning off by going in the opposite "direction."

This gif shows the IR leds getting covered in a particular order to turn on the lamp and then in the opposite order to turn off the lamp.
Notice the Aluminum cones?

The Physical Housing

The design for the physical housing of the project will have to occur sometime after this post. As of right now it's just a hodge podge of wires. My plan is to place the IR LED and receiver pairs some distance apart in the hallway. I'll probably laser cut small boxes to house the hardware with a small hole to direct the LED and alternatively, a small hole to house the receiver.

Looking to the future

As I was working on the write up for this project it occurred to me that if two people were walking close together that the logic of the code would not work. The first tripwire will be off until the first person either triggers the second or the window of time to trip the second ends. If two people are close together then a person could slip in without being sensed! I think instead it would be smarter to create a "stack" of entrances and exits, where each tripped tripwire has an associated time stamp. I can then compare tripped tripwires and their timestamps and make decisions based on the time between them. Let me know if you guys have any suggestions in the comments below!

Comments 16 comments

  • I am a newbie in this field, but it seems very interesting! I want to Know Where should I start with, is it difficult for me. By the way, sports camera is trendy products for different kinds of sports such as cycling, climbing, hiking, swimming, skiing. They are good helpers for most kinds of outdoor sports and water sports due to their light weight and good capability and easy to use. Meanwhile, they have superior features that normal cameras do not have like waterproof and dustproof.

  • Sorry for an amateurish question, but can you mention why you needed to "creat[ing] a 38kHz infrared signal that would act as an invisible tripwire"

    In other words, why did you have to adjust the signal? Why 38kHz?

    • That's a great question! As I mentioned in the post, infrared is literally everywhere. Not only does it rain down from the sky but if you've seen any FLIR camera images or Predator movies, than you've seen how infrared is given off by all objects (to some degree). Since infrared is everywhere, you simply can't turn on an infrared LED and hope that your receiver will pick it up among all the infrared in the environment. As a result, infrared receivers are tuned to pick up certain frequencies of infrared; specifically 38kHz for the receiver I used in my project. There are other receivers that use 36kHz or 40kHz but the one we sell is tuned to 38kHz. Hope that helps, come on back if you have any other questions!

  • Sounds like an interesting project!

    I'd be inclined to put in a "watch-dog" timer, that is, if the people-in-the-room doesn't change within some given time (maybe two or three hours?) you assume that there's an error in the count and turn off the ights. (Although it could benefit from my "hot-button" issue of having RTCs [Real Time Clocks] on board, which would also allow ajusting the time out value based on time of day, just going off millis() value is probably good enough.)

    Of course, you could also incorporate a PIR sensor. I like reliance on the "count" of people in the room as "primary" -- I recall incidents where PIR-based lights didn't sense me sitting at the computer late at night, and having to jump up waving arms to get the lights back on!

    • I've seen coworkers waving their arms like you mentioned because the PIR sensor doesn't sense them in their office. I worried about the same thing with this project which is how I settled on counting individuals. I'm too committed at this point to go back to a PIR sensor I think.

      • There's nothing that says you can't have BOTH sensor systems! Indeed, as I type this, it's looking like the two 737-Max 8 crashes may have been caused by a system that only looked at a single sensor (which failed).

        Thought: If the PIR sensor gets triggered (maybe multiple times in a short period), but the doorway sensors claim a count of "zero", have the IoT device send you a text message about a possible "intruder"... (i.e., someone might have came in through the window...)

        • Rather than considering it an "intruder" I'd be inclined to use a PIR as a sanity check for the occupancy count: if the count is zero, and motion is detected, set the count to one. Also, if the count is non-zero, and the PIR has not activated in a long time, set the count back to zero.

          To prevent being suddenly plunged into darkness, I might also add some sort of audible cue (buzzer chirp, audio trigger board, etc) that the lights are about to go off. When the last person exits (count goes to zero) don't cut the lights immediately, but give a chirp then turn off the light a few seconds later. In the case of the count going to zero prematurely (miscount of the trip sensors or long PIR timeout) this gives you some warning and lets you wave your arms to keep the lights on. Because this also sets the count to one, you will only have to do the wave thing once, until someone else leaves the room. Rather than just a delay, the "count reached zero" chirp also gives you some comfort when you are the last person leaving, in that you know the lights will go off shortly, and your don't have to stop you n the hallway to see if that is the case.

          If you use something like the WAV trigger board, you can have additional sounds for count up, count down, number of people in the room, etc., although that might get annoying over time.

          If the system knows the time (ESP32 can get it from the Internet even without an RTC) you can also use the time as a backup to turn off the lights at night in case the count got out of sync. You can also use the time to automatically switch the PIR into signaling intruders during the night.

          • long PIR timeout

            IMHO, if you're using a PIR as an input to a micro, you're probably better off setting the PIR to it's minimum timeout and doing the actual "time out" in software. This allows for adjusting it based on other inputs -- e.g., if the "count" is zero, have a shorter timeout than if the count is higher.

            I really like the idea of an audible warning on "lights out", though you want to be careful not to make it too confusing, especially if you have other folks visiting your home.

            One further point on time-of-day, you could keep some sort of record of when the lights were turned on and off, and then have a setting to "replay" that when you're away for security. (LOTS beter than a simple timer!). If you really want to get fancy, also calculate the time of sunset/sunrise and adjust for that, but that's probably overkill.

          • Yeah, you're making some great points! I especially like the idea of some kind of cue before the lights turn out. I had considered keeping count on one of our mini-OLED screens or better yet the transparent OLED.... ....but I would have to be on the wrong side of the tripwires to check that the count went to zero. The audible cue on the other hand is smart AND fun. A Mario coin sound every time someone enters the room and the Mario tunnel sound when the last person leaves, neat! I also like how you expanded on the PIR sensor that the other user suggested. Thanks for the thoughtful post =).

            • jma89 / last month / 1

              You could also just flash the lights (or maybe one and then the other) to indicate a pending shutdown. I've seen several office lighting systems that do this and then wait 1 minute before shutting the lights off for the night. Anybody can then meander over and tap the light switch to cancel the shutoff.

        • It'll also tell me if my dogs are in my office....not a bad idea.

  • Did you consider using one of the hardware timers to drive the IR LED? Software delays can get real messy.

    Also assuming you're not using lenses with the IR components, what kind of range do you think you will get with your setup? I'm assuming a doorway or hall, 3-4 ft?

    And had you considered using some of the range sensors like your Maxsonar or the Sharp GP2 series?

    • Yes I agree and for a moment I did look into it, but had some difficulty finding the low level pin assignments. Let's use Atmel chips as an example because I'm more familiar their datasheets. Where do you find the pin assignments for PORTB or access the timers, TCCx for example? I had trouble finding them in the Arduino folder structure.

      I'm not using lenses but I am looking at how to focus their beam. I am just considering some PVC pipe at the moment. You guessed right, they will only be shooting 3-4 feet.

      I thought about range sensors, but didn't want to over engineer the project. IR LEDs seemed simple enough in design and in code. Have you had success tracking a number of people and their direction using them?

      • I’ve used the sharp sensors for many robotic sensors for maze runners and mini-sumo, no people counting. The ones that feature an analog output would be the easiest to interface with, no real timing issues. I only use the AVRs and while the info is In the data sheets, the hard part is figuring out how to use some of the internal hardware via Arduino, as you have mentioned. One could always write the C code, no Arduino. Most of my robotic projects were done in assembly.

Related Posts

Recent Posts

Antenna Connectors


All Tags