Introduction: Minimal Arduino Metal Detector

With an Arduino, 10m of wire and a 100 Ohm resistor you can build a metal detector in 10 minutes! It is based on sound physics and works for a large range of coil sizes and shapes. The sensitivity is not enough for treasure-hunting, but it can be made into a small hand-held device that is very useful indoors to check for the presence of metals. It will help you find nails inside wood or heating pipes in the wall, and to check the composition of tools and furniture. The method can also be used as a proximity sensor for metals as part of another project.

Step 1: Make a Coil

You will need a coil of at least 20 windings but it works better with 50 or more windings. The detector is sensitive to items that are larger than about one tenth of the coil diameter, so smaller coils are better. Finally, make sure that the resistance is less than 10 Ohm. Here I describe the coil I made, but anything will go, even a 10m roll of breadboard wire.

I used AWG26 enameled wire, which has a diameter of 0.4mm and a resistance of 0.13 Ohm per meter. The wire was wound 60 turns around a candy can with a diameter of 6.3cm. Leave one turn extra length for connection leads. The wire comes at ~12m and the resistance 1.5 Ohm. I put some electric isolation tape around it and then squeezed it in an oval shape and completed covering it in isolation tape. It protects the coil and keeps it stable. Remove the isolation at the last few centimeters of the wire with sandpaper.

Step 2: Make a Prototype

Upload the attached sketch to an Arduino Uno or Nano. Connect the coil between pin 8 and pin 10 and a 100 Ohm resistor between ground and pin 8. To get sound, connect a passive buzzer in series with a 10microfarad electrolytic capacitor between ground and pin 12. Calibration can be implemented with a dangling jumper cable on ground. Connect it to pin A0 to force a recalibration.

Try it out! The built-in LED on pin 13 should start flashing when a metal object is brought nearby the coil. The buzzer will click at the same frequency.

If it doesn’t work and the LED on pin 13 is flashing with a regular pattern, you can inerpret the error from the flashing pattern:

  • Single flash: No pulse on probe pin - check connections
  • Double flash: Delay too short - try more windings
  • Triple flash: Delay too long - try fewer windings
  • Quadruple flash: No robust pulse on pulse length scan - check coil resistance

To get more detailed feedback, change “debug false” to “debug true” in the code and check the output of the serial monitor. The minimum value of the measured ‘delay’ is 5 clock cycles, but things work better if the coil has more windings, and the value of ‘delay’ is at least 20.

If there are too many false signals, you may need to reduce the sensitivity from 5000 to 2000 or 1000.

Step 3: How Does It Work?

Detailed tech talk here - feel free to skip to the next step to start building!

This metal detector works by sending pulses to a RL low-pass filter, where the ‘L’ is the inductance of the search coil, and 'R' the external 100 Ohm resistor. The Arduino measures the delay between input pulse (pin 10) and the output pulse (pin 8). This delay is proportional to the inductance of the coil. A conductor near the coil will reduce the inductance because the eddy currents oppose the external magnetic field.

The challenge is that this delay is very short: the characteristic time of an RL circuit is tau=L/R, with L in Henry and R in Ohm. The inductance of the coil we use is circa 300 microHenries, so for R=100 Ohm, tau=3microseconds. We are looking for variations in the inductance of 1 in 5000, so the time needs to be measured with a precision of better than 1 nanosecond.

The Arduino has a clock speed of 16 MHz, and the input capture feature of timer1 can provide a timestamp of a pin change with the accuracy of 1 clock cycle. One such measurement is not precise enough, but by combining a large number of measurements the precision can be improved.

Simply repeating the measurement is not enough because the quantisation error is always the same: if the delay changes from say 3.03 to 3.02 microseconds, the delay is always 48 clock cycles. To overcome this, we measure the timing of the falling edge of a short pulse, and scan this pulse length between 3 and 5 times the value of the delay found originally.

The code aims to measure the inductance 100 times per second, so that the response is quick. For a pulse delay of 25 clock cycles, timer one gets set to a repetition every 215 clock cycles, so in 10ms, a full scan of 50 pulse lengths can be repeated 15 times, and the summed delay of 750 pulses provides the measurement, providing a resolution of order 10^-4 on the delay time.

At startup, the first measurement is taken as a reference value. Whenever a measurement differs by more than a predefined threshold, a phase counter starts to increment. When the phase counter goes over maximum, a 1ms light pulse is produced and a tick is produced on the buzzer. For differences right at threshold, the frequency is 1 Hz, for differences of 10x the threshold, the frequency will be 10Hz etc. The threshold value is determined as the reference measurement divided by the value of ‘sensitivity’. So setting ‘sensitivity’ at 1000 means that the detector will react to changes in the inductance of 10^-3. For a soldered battery-operated device, (see next step) the sensitivity can be set to 5000.

Slow drifts are compensated for by incrementing or decrementing the reference value by 1 if the threshold is not exceeded. In case the reference is not good, it can be quickly zero-ed by momentarily connecting the pin A0 to ground.

Step 4: Make a Hand-held Device

To make a practical device, the detector needs to run on batteries and have a suitable housing. A large-size tic-tac box has ample space for a 9V battery, and Arduino Nano, cabling and buttons. It can be put together in an hour or two.

Required components:

  • Arduino Nano
  • 60-turn search coil
  • 9V battery and battery clip
  • 100 Ohm resistor
  • An on/off switch
  • A push-button
  • A passive buzzer
  • A 10 muF capacitor
  • 2 skewer sticks
  • 7 pieces of 8-cm stranded wire
  • Heat-shrink tube in various diameters

Tools:

  • Soldering iron
  • Wire clipper
  • Sharp tweezer
  • Hot glue gun

With the tweezers, punch holes in the lid of the tic-tac box for the leads of the on/off button, the push-button, the buzzer and the coil leads feedthrough. Apply little solder blobs on all leads. Prepare 7 pieces of stranded wire, 8cm each, strip the ends en pre-tin them.

Solder all the connections according to the provided schematic. Best is to start with the wires of the components on the lid of the box, since space is confined there. Once all is connected, the Nano and battery can be squeezed in the box.

To fix the coil, I hot-glued skewer sticks to the tic-tac box, making sure that the lid can come off to replace the battery or reprogram the Nano. Then the search coil is fixed to the skewers with ordinary scotch.

Upload the code and you are ready to go. I noticed that once soldered and powered from a battery, the stability was much better and I could change the value of the sensitivity in the code from 1000 to 5000.

The calibration button is now handily accessible: whenever the detector starts ticking without metal present, just push it and it will use the present measurement as a new reference value.