Vehicle Detection With D1 Mini and Magnetometer

Detect vehicles using QMC5883L and actuate swinging gate using relay to allow exit

Similar projects worth following
My folks have a swinging gate at the entrance of their driveway with a keypad on the outside. Guests can come easily, but due to an auto close but it is an unfortunately manual process to let them exit either by push button on the inside of the gate controller box itself or a garage remote with frustratingly limited range.

They were interested in a vehicle detection induction loop but after finding consumer offerings for no less than $150+ USD, I knew I could do it for cheaper and have it be smarter.

I originally considered an ultrasonic sensor to detect vehicle presence but decided not to in order to have have a cleaner and hopefully more accurate detection. After some basic research I came up mostly empty handed but stumbled on a forum suggesting the use of a QMC5883L magnetometer. $7 and a manual build of ESPHome later I had a working prototype!!


  • QMC5883L: 3v or 5v, GND, D1 (SCL), D2 (SDA) 
  • Reed Switch: GND, D7 Relay: D8 (you can modify the pin # on V2, or physically cut D1 pin and add bodge wire) 
  • Voltage Divider: GND (if not shared ground), A0

Voltage divider and reed switch terminal are soldered to a shared proto board

Initial Prototype:

Breadboard initial build

As I’d suspected, when a vehicle or other large ferrous object (or even a hand placed closely) passed above the magnetometer, its readings would change significantly. Basic tests proved that I would be able to use this for my detection. After some hacking in ESPHome I eventually landed on creating a sensor with a 15 second moving average of heading readings, and triggering my relay if the current heading reading varied from the average for more than 3 seconds. Some additional logic was introduced to filter out sporadic bad readings and prevent gate from actuating too often (or closing on a car passing through!).

The below is what I came up with:

  • Create sensor with average of last 15 heading headings (taken at 1s intervals)
  • Create “automation safety” binary input to prevent rapid firing of gate open from readings
  • If current reading varies ± 2.5° from average turn on internal binary sensor
  • If binary sensor on for more than 3 seconds AND gate is closed AND our “automation safety” binary sensor is off: trigger the relay and turn automation safety on for 120s

In the above we have ensured that:

  1. Something (presumably a large metal object) has caused a change in heading and has stayed for some time
  2. The gate is closed and probably needs opening
  3. We won’t accidentally close the gate on a car passing through since our automation will only fire if the gate is closed.

In addition to vehicle detection there is a gate status sensor (open/closed), battery sensor (gate and microcontroller run on 12V battery), and functionality to open/close gate via app/MQTT. I wanted to be sure this could operate independently (I run Home Assistant at home but they live far away) and have built it so that no external connectivity is required but if present will add additional functionality.

The vehicle detection was worked out in code and functioning as expected and then I dove into the gate and battery status sensors. The gate status was easy, just a simple reed switch. The battery sensor required an additional voltage divider. The D1 Mini has a voltage divider already but cannot accept the voltage of the gate's battery (12V deep cycle). I added an additional voltage divider and wired it to A0. With the additional divider I expect to see a voltage ~15.43 times less than the real voltage.

Prototype 2:

Testing beta build

QMC5883L was connected to proto board via 2 pairs inside CAT5:

Magnetometer mounted inside Sonoff IP66 junction box. This was buried underground inside 4" PVC for protection under rock driveway. (moisture absorbing packets optional, hopefully not needed!)

Completed Front:

Completed Back:

Installed in gate controller housing:


While the device is self contained and doesn't require a network connection, if it does have a connection it will send data over MQTT. The above image is from Grafana. In it we can see the full flow of a vehicle entering the detection zone, the heading deviating from average, automation firing, gate opening, vehicles passing over sensor, timer expiring, and gate closing. This works exactly as intended!


ESPHome YAML file

yaml - 3.69 kB - 09/08/2019 at 19:54


View all 8 components

  • Battery telemetry recovered!

    Andrew10/06/2019 at 03:12 0 comments

    As it turns out it was just a loose wire that caused the loss of battery telemetry data. Swapped it out, tightened down and it's now working as expected!

  • Still no battery data

    Andrew09/08/2019 at 20:38 0 comments

    I've had my father wiggle wires and even move the VCC detection wire of the voltage divider and I'm still not getting a good reading on the battery voltage. This is perplexing since it was working when first installed, but it quickly went downhill. Not sure what the problem could be but I'll have to put a volt meter on it.. 

  • Remote updates

    Andrew09/08/2019 at 20:33 0 comments

    As I've observed MQTT data there have been a few things I needed to tweak. Traditionally with ESPHome you would edit code through the console and click "upload". Since this device is deployed remotely I needed a way to update the code without going on-site. Using ESPHome's web_server component and a raspberry pi I was able to make this happen.

    I have a raspberry pi on the remote network create a persistent tunnel back to my server, allowing me to get back into it without creating NAT rules on the modem. After logging into the rpi I simply create another reverse tunnel between my local workstation and the D1's web server:

    /usr/bin/autossh -M 0 username@local_workstation -p 24 -o "StrictHostKeyChecking=no" -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -N -R 9993:

    The above makes the D1's web server dashboard available on my localhost:9993. From there I can use the "OTA Update" to upload a compiled binary with my changes.

  • Working as expected.. mostly!

    Andrew09/08/2019 at 20:21 0 comments

    This build works just as I'd expect, I'm very pleased with how it turned out. I do have a couple of concerns:

    1. The cat5 I've used is only plenum rated (if that). I didn't bury it in any conduit so there's a decent chance that it will degrade, ingest water, etc. We'll see if this has near-term affects on the function, in the long term it should almost certainly be laid in a conduit, time will tell.

    2. The D1 Mini has a voltage divider on A0 already. It feels weird to stack the voltage dividers and my reading*15.43 was the result of some basic circuit simulation and real-world testing. In addition, the voltage sensor is not currently functioning as I'd expect. I suspect the cable on the battery terminal is loose. In hindsight I should have soldered the sensor wire onto a washer to be tight alongside the other wiring on the battery + terminal. I also didn't attach the GND to the voltage divider. I don't *think* it's necessary since the whole system is battery powered and *should* share the same ground but I'm not an electrical engineer. The D1 pulls power from the gate circuit board's +12v and GND terminals. 

    3. I'm not sure how well the IP66 Sonoff box will do underground in the rock driveway long term. The PVC pipe was a last minute addition and probably the saving grace. Even still I don't know if the plexiglass cover on the junction box will eventually get cracked from pressure or have water seep in by another means. 

View all 4 project logs

Enjoy this project?



Mike N wrote 09/25/2020 at 17:31 point

How long is the cable you use for the cat5 to interface the d1 with the compass sensor? I can't seem to get mine to work for more than a few feet which I get is a limitation of i2c but I'm hoping there is something to do to extend that as I don't get wifi down where I need the sensor.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates