Attiny85 Projects: DIY Motion and Temperature Sensor
Updated: Oct 9
I recently made a Wireless Room Motion Sensor using an Attiny85, ESP8266 and a scavenged cabinet light for fun. Now I have a DIY, compact, low-power sensor discreetly placed under my desk that lets me know if there's been any recent movement in the room:
This post covers some of the key steps and learnings along the way. Or directly go to the schematic and source code on Github.
Roll my own motion sensor for home presence detection and Home Assistant. Why buy when you can DIY?
Use what I had. Reuse or upcycle parts when I can. I had:
Attiny85 - My favorite tiny MCU
ESP-12E - I wanted to check viabiliity of an ESP8266 as a "wifi shield" for an Attiny
Transolid Sensio Battery-powered Light - I wanted to scavenge its PIR sensor
Low-power: I hate wires and like the challenge of low power budgeting. A battery-powered ESP8266 project that would last months sounded fun!
1 x Attiny85
1 x ESP8266: I used an ESP12-E with those adapters
1 x MCP1825s: 500mA LDO to regulate 3.3V-sensitive ESP
1 x IRLZ44N: N channel logic-level Mosfet
Multiple ceramic capacitors: 4.7 uF, 1 uF for LDO output; 0.1 uF for decoupling cap on Attiny85
1 x 10 uF electrolytic capacitor for ESP-12E
3 x 10k resistors
1 x PIR sensor (I ended up tapping into the one attached to this light
Lots of hotglue, solder, flux and swearing
Step 1: Figure out how to tap into the PIR in the light
My original plan was to scavenge the PIR sensor from this light (built for kitchen cabinets) but I quickly realized I needed the other ICs (PIR controller/processor) on the PCB. So I decided to reuse the original Sensio light to house the entire circuit. I traced the PCB to the IC (AS083) and its Chinese datasheet, where after, some Google Translate, figured out which pin would go High (2.7V) after Motion Detection, and which Pins controlled it's duration.
Step 2: Connect Attiny to ESP8266 with MQTT
This was pretty straightforward. I read a few guides and decided on simple 1-way serial communications where the ESP would act as a "dumb Wifi relay": Attiny would WRITE, the ESP12-E would blindly ECHO it to its destination.
For the ESP8266, I used Arduino IDE to code up a simple loop to receive serial input and publish it as MQTT events.
Step 3: Prototyping
I was ready to put it all together to test it out. The logic would go like this:
If the PIR sensor detected motion at any time, it'd raise Detect Pin to High
The sleeping Attiny85, connected to that pin, would wake on Pin Change Interrupt and read the voltage, confirm it was High (2.7V+) and take note of motion, and go back to sleep. Otherwise, it'd just go back to sleep.
Periodically, the Attiny85 would wake up, and check if any motion was recently detected. If so, it would power on the ESP12-E (via switching Mosfet) and ask (over serial) the ESP12-E to publish the detection event via MQTT.
After sending, it'd power off the ESP12-E and then sleep again
It worked and I was ready to put it on perfboard! But I quickly ran into a slew of issues and headaches!
Step 4: Rabbit hole: Reading Battery Voltage and Room Temperature with the Attiny85
The headaches that followed were self-induced. Like all tinkerers, I got side-tracked with cool ideas: I became enamored with the idea that my sensor could be both a Motion and Temperature sensor. Because this was going to be battery powered, I thought it'd also be useful to publish its own Battery voltage level so I'd know when to change it out, and even some brown-out/low-voltage detection to stop draining the battery.
The good news is that Yes, you can do all this with the Attiny85. You can get the humble Attiny85 to approximate ambient temperature and read its supply voltage! The bad news is that it required a lot of reading, calibration, experimentation, playing with dubious forum code snippets and time to get it all right. Key things learned:
Calibration required- Your Attiny can read chip temperature (I re-used this code) but it depends on your reference Voltage, which can vary widely due to IC differences. I had to experiment with various offsets and test my breadboard circuit in my room and in my fridge(!!), where I could vet my offsets across the temperature range
Get you internal Reference voltage right - Good temperature and voltage calculations require an accurate Internal Reference Voltage and it quickly got annoying to experiment different offsets, re-compile and upload code to the Attiny. I built another circuit to read calibration offsets from a potentiometer then store into the Attiny85 EEPROM for re-use in other sketches, following this blog post.
Add Delays/Condition before EEPROM Writes - I lost a lot of hair here. The Arduino library makes it easy to read and write values to EEPROM (which I used to store chip-specific reference voltage offsets). I drove myself crazy when I noticed that after running my Voltage Calibration on my Attiny, which wrote to EEPROM, I'd see an entirely different value reading from the EEPROM in a different sketch. What was happening was that the in the brief moments between plugging in my calibrated Attiny to my Uno (acting as an ISP Programmer), and clicking the Upload button, the calibration sketch would immediately run, read in some floating pin values and reflash the EEPROM value to something random. ARGHHHHHH.
Step 5: Making it Low Power
I started with the obvious sources of current draw:
Kill the lights - I was resigned to building my circuit as an attachment (like a parasite) to the Sensio light, meaning I would keep its PCB. The PCB had multiple SMD LED lights which would turn on whenever the PIR sensor triggered, so I quickly desoldered them off. This cut off ~30 mA IIRC
Suppress the rest of the LED driver ICs - Since I was stuck with the PCB (designed for a cabinet light), but only cared about the PIR sensor, it was time to kill off everything else. After some Googling for the datasheet, I identified the pins on the LCD driver that would keep it inactive. This was another 20 to 30 mA cut out
Minimize Attiny85 wake time - I had already coded this part. The Attiny85 mostly slept and would wake only on Pin change Interrupt (motion detection) or an interval using the Watchdog Timer. This Technoblogy blog post is a classic must-read on this topic
Minimizing ESP8266 wake time - Wifi doesn't come cheap in your circuit's power budget, with an expected 200+ mA current draw as a rule of thumb. Common best practices include putting the ESP into deep-sleep and waking when needed. I had some N channel Mosfets sitting around I wanted to use up and didn't want to complicate ESP-side code. Even when most forums advise using high-side P channel Mosfets to switch an ESP, I just went with the Attiny switching it off with the low side N channel Mosfet. No issues
Cutting down wifi boot and connect time - Documented to be the hungriest "step" for ESPs. Using Static IP (instead of DHCP) and caching BSSID, Channel can cut down time chugging valuable battery juice. I used the Fastconnect branch in the WifiManager library to cut the ESP12-E Power-on to Connected time from 8s down to 1.8s!!
Step 6: Putting it all together
My original vision to fit my circuit into the Sensio light housing faded when I got to assessing the actual space I had. But the Sensio light had a lot of things going for it (low profile, battery holder, magnetized) so decided to put my circuit into a small separate scavenged housing (like a "dongle") and connect the two via USB. That resulted in multiple Challenges:
Connecting light to Billy - I used USB wire to carry both the PIR signal and battery power from the light to Billy. I scavenged an SMD USB connector and soldered it onto my circuit. On the light side, I soldered wires and used hot glue to feed the PIR and battery power into the USB cable. Unsteady soldering hands + SMD parts to adhoc surfaces= lots of swearing
Playing Tetris - I had a compact enclosure but had through-hole parts so had to experiment with different layouts, configurations and pieces to fit it all in
Caps and more Caps - With the adhoc layout, I had to cap across power lines, and each IC to filter out noise. You know, that "unnecessary" step we usually skip in Instructables examples...
Finished: Still Alive and Kicking
I finally finished and slapped it under my desk. It's been humming along fine for about a year and I am usually swapping out batteries (4 x NiMH AAA) about every 4-6 weeks.
Get the Schematic, Source code and Home Assistant MQTT sensor configuration here: https://github.com/smashteevee/esp_billy