Diy Arduino based metal detector.

UPDATE: Try using BC547 as transistor people have reported problems with 2n2222.

Me and my son decided to go treasure hunting with a metal detector that we have but we couldn’t find it anywhere. Being proper makers we decided that it would be more fun to build one ourselves rather than keep trying to find it. 

Most metal detectors uses a search coil that act as part of an oscillator circuit. When metal is put in proximity of the search coil the frequency of the oscilations changes.
Many metal detectors (including the one we can’t find) uses another more stable oscillator BFO (beat frequency oscillator) to act as a reference for the frequency of the search coil. Usually the frequency of the BFO is adjusted to exactly match that of the search coil oscillator when no metal is present near this.
The signals from these two oscillators are then fed to a, usually analog, circuit that create an output proportionally to the difference in frequency og the two. This may be either an audiable tone and/or some meter reading.
Another device that are really good at detecting minute frequency changes is a microcontroller. We decided to swap the BFO approach for a microcontroller and came up with following simple circuit:

The oscillator circuit feeds a around 160kHz signal to pin 5 of the Arduino. The Arduino sketch then measures the frequency of this pin very accurately. When the ‘NULL SW.’ button is held this frequency is stored. Any deviation from this frequency is then represented as a series of ‘geiger counter’ clicks on the piezo. The rate of the clicks increases as metal approaches the coil.

We tried different search coils and found that around 30 turns of wirer around a 15cm. plastic bucket worked well.

All we needed then was to tie it all to a discarded Ikea lamp and hey-presto off to the beach to find treasures.
The metal detector has excellent sensitivity and by changing the SENSITIVITY value in the Arduino sketch you are able to tune it for both small and large objects.
Here is the source code if you want to build one yourself.
Happy hunting!

92 thoughts

  1. It detects a 1euro coin at about 15 cm distance if you are patient…
    Wire is just plain 0,12mm2 plastic coated wire not critical..
    I will try and make a TINY45/85 version and post it here..

    1. The 2N2222 has quite little gain (hFe) of about 30 (depending on the current flowing). The KT315 may have a much higher gain of about 100-200 – maybe that causes trouble with the base current on the npn transistor. You could try higher values for the resistors. As far as I understand the circuit it's just a kind of voltage divider and as that functions as a base current limiter for the transistor. Not sure if it affects the circuit if you alter the values…

  2. Nice work !

    I've built mine, But after some tests I think it needs some tuning. I've tried in my garden, but some objects (bike, table etc..) seems to alter the frequency so this is quite hard to localise a coin. (50 euro cents)

  3. Nice project – Any improvements you have come up with after some field testing? I added a 10K pot to an analog pin, using the value to set the sensitivity at the same time as null. Have not had a chance to test it out outdoors yet, but my kids are sure to enjoy this!

  4. Nice project! I got this to work using the BC547 as you suggested. One thing I'd like to point out to your readers who also try this circuit is that you need to be wary of prototyping this on a breadboard. The parasitic inductance, capacitance, and resistance can cause problems at this frequency in the circuit. I could only keep this circuit stable for about a minute or two before these effects broke it down.

    For those who try, this is how I got it working. Without any changes to the circuit or the sketch, try setting the sensitivity real low (Ok, one change in the sketch) and then sense a big piece of metal (I set 100, sensing a pair of pliers at 5 cm). That should be good enough for a proof of concept. I used 30 turns of 29 gauge magnet wire around a 15cm diameter form. Also watch the quality of your loop as that will impact performance – keep it tight and compact. Finally, I suggest prototyping with an external supply voltage to further remove secondary effects from your PC connection. I used a 9V battery to an Uno board.

    Really awesome and thanks again. Clever circuit. I'm going to etch a board in the coming weeks as time allows to build this proper.

  5. Great project. Thous I am not very familiar with metal detector stuff and don't completely understand how everything works. I add some stuff to Your code – also pot adjustment. Maybe will soon put code and entire project on my blog.
    I use 2n2222a and it works ok. Range could be better.

    1. If we use 12v to coil could it boost up detecting depth?
    2. Why not to generate pulse with arduino microcontroller? Then it would give possibility to test different frequencies. Of course we need to add additional components.
    3. I read about BFO concep. But did not completely understand how timing calculation works in this code. Can somebody explain code in details?

    Anyway many thanks!

  6. Подскажите пожалуйста, как поменять в скетче номер пина (5) на как либо другой, никак не могу запустить этот девайс, есть подозрение что что-то с пином не то

  7. Hi all,

    I used 2n2222a and I'm not able to make it work. I can read the frecuency modifying source code in void loop():

    Serial.print("Frecuency: ");

    And before and after I press NULL SW button, Frecuency value is the same: Frecuency: 0.0

    Could you please help me to solve this issue?

    Many Thanks in advance!

  8. The circuit works, but I did not use the code mentioned here, I created my own, so I cant really comment the code.
    Nice project, but I'd like to know more about the oscillator circuit… a LC circuit produces a oscilatory signal when you apply a DC current? … didnt know that.
    the transistor part of the circuit, is it just to change the voltage level? it has nothing to do with the oscillator part?

  9. hi xouri can you upload your code? Because i've triple checked the schematic and my coil is fine but still doesn't work, but I couldn't understand the code well cause i'm a beginner in programming.

  10. Ok for some reason my null switch isn't working and I have another question about this code. What does this do for the code and why does it not ever get called? //-Generate interrupt every 1000 oscillations of the search coil

  11. I only obtained @25KHz oscillation using the 22nanoFarad caps (.022 uF or microFarad) suggested in his drawing; when I changed the pair to .001 uF the oscillator ran about 250KHz (target was @160KHz). I could not detect a coin; but it worked on a hammer. Thinking I need higher Q capacitors and to dead-bug the assembly instead of protoboard.

  12. Sinusoidal oscillations on emitter of transistor are weak with waveform voltage swing from +2V to +3V in my example. Depending on components can be even lesser and this is maybe not enough for arduino to consider this as binary 0 / 1. It is good to add one additional BC547 saturating amplifier between emitter of oscillator transistor and arduino, which will ensure that voltage swing is 0 to +5V. (copy schematic to notepad fixed font)


  13. I just finished building and testing. It works great!! The only change in circuit values I made was to use a BC337-25 transistor (since I had a bunch of them that I'm trying to use up.) My coil is 30 turns of #27 magnet wire wound around a plastic jar lid 12.5 cm diameter. I set the Sensitivity parameter at 1500 in the sketch but it works fine from 500 to 3000. At 1500 it will reliably detect a US penny coin from around 5 cm. It will detect an aluminum beer can from around 14 cm away. It seems more sensitive to non-ferrous metals than to ferrous but detects my pocket knife quite well at 8 cm distance. I put a red LED and 1.8K resistor in parallel across the Piezo element to act as a visual indication since the Piezo ticking is low in volume.
    I used poly film capacitors for all 4 caps and constructed the circuit on a piece of wood with bare copper wire busbars and a socket for the transistor. The Arduino code compiled and runs without problems on the genuine Uno. The base frequency with the coil I made is around 90kHz.
    I'm going to add a pot and statements in the code to set Sensitivity using analogRead and map statements, but at 1500 it seems to work quite well.
    Thanks for a cool project!

    1. I can't get this to work. I newer get to the part of the code:

      if(digitalRead(12)==LOW) //-Check NULL SW.

      I have tried with 2 different push buttonts but no success.

      I don't know what to try anymore. Can someone please help me? I have put Serial.print -messsages around the code and that part is newer executed. Thank you for your help!

    2. What Arduino version are you using? I copy-pasted the sketch code directly from the link above, into the IDE and it compiled and ran properly without any alterations. But because of the way the timers are called in the code, it may be specific to the ATMega328P . I just tried it on an Arduino MEGA with the ATMega2560 chip and it does not work, but it works fine with the Uno and ATMega328P chip. I think this is because of the way the timers/interrupts are called in the sketch.
      You may want to refer to the references here:
      to see if modifying the timer numbers will help.
      Or just try it with an Uno using the 328P chip.

  14. Can the author (or anyone who has successfully used the schematic) clarify the capacitor values, since the handwriting is a little ambiguous? I initially assumed the units were microfarads (μ), but my friend thinks it's nanofarads (n). Thanks!

    1. I also thought the drawing said (μ), but if you read some of the comments above, you will read that others are using (n) and that theirs work. Look at
      James Dinsmore post on November 30, 2014. Also some have videos. Like TinselKoala post from June 13, 2015.

      To all the people that say that the NULL button doesn't work. You are probably not getting a signal from your oscillator. Check your circuit. Make sure you are using Nano Farad capacitors.

  15. Very well done, I made it today exactly according your description except the transistor which I use the BC547 and it works fine from the beginning. I like to know or some one has a description and code for adjusting with potmeter.


  16. Today I use it as a pinpointer small coil around ferret rod.
    Also change to sound to more high tone, see part of sketch below.

    //-Click generator
    // Play the pitch *** Detection ***
    tone(13, 3000, 30); // Play over pin D13 tone, pitch
    delay(20); // delay in between
    noTone(13); // Stop tone
    // digitalWrite(13,LOW);
    noTone(13); // Stop tone

  17. The sketch refuses to compile. I get this error message:

    Arduino: 1.6.7 (Windows XP), Board: "Arduino/Genuino Uno"

    collect2.exe: error: ld returned 5 exit status

    exit status 1
    Error compiling.

    This report would have more information with
    "Show verbose output during compilation"
    enabled in File > Preferences.

  18. Arduino: 1.6.5 (Windows 7), Board: "Arduino/Genuino Uno"

    Build options changed, rebuilding all

    metal_detektor:1: error: 'v' does not name a type
    metal_detektor.ino: In function 'void __vector_11()':
    metal_detektor:27: error: 't0' was not declared in this scope
    'v' does not name a type

    This report would have more information with
    "Show verbose output during compilation"
    enabled in File > Preferences.

  19. hi i built the metal detector but my was un stable and relly jumping around eaven when not moving anything, and when i went out in lower temperature about 0degrees celsius it went ballistic. how can i solve that problem?

  20. i have tried it on my arduino uno r3 atmega 328 r-b ,it did not work. when up loading sketch (libray found not working).i checked circuit by powring it with 9 v battery near am radio and moved piece of metal over the coil, radio responding to metal movment. i am new to arduino and need your help. thank you

  21. i built the oscillator circuit with some temporary materials. work fine. drifts a little at the beginning, but not bad considering im using 40 years old caps 😀
    waiting for the proper components and wire. then will connect the artduino. great project.

  22. Some findings:
    1) This Sketch does not work on an Arduino Mega 2560! (this is due to the lack of the T1 pin)
    2) The oszillator-circuit is some sort of "common base collpit-oscillator", try wikipedia to get more informations
    3) You can definitely use an BC337-25 Transistor instead of the mentioned one

    1. 5) If you use an arduino MEGA, use the following code and Pin 47 instead of Pin 5:

      // Arduino based metal detector
      // (C)Dzl july 2013

      // Connect search coil oscillator (20-200kHz) to pin 5
      // Connect piezo between pin 13 and GND
      // Connect NULL button between pin 12 anf GND


      // Präprozessor Makros
      // Beeinflussen Bit Nr. y im Bivektor x
      #define SET(x,y) (x |= (1< löst erst wieder in 1000 Takten vom externen Oszillator aus
      t = micros() – t0; // Wieviel Zeit ist zwischen diesem und dem letzten Interrupt vergangen?
      t0 += t; // Merke dir die aktuelle Zeit für den nächsten Interrupt
      tflag = 1; // Lässt Loop() starten

      void setup()
      // Piezo-Element an Pin 13
      pinMode(13, OUTPUT);

      // Interner PullUp für den Null-Taster an Pin 12

      // Set up counter1 to count at pin 5
      TCCR5A = 0; // Timer/Counter1 Control Register A
      TCCR5B = 0x07; // Timer/Counter1 Control Register B, 0x07: Externe Quelle am T1 Pin, steigende Flanke
      SET(TIMSK5, OCF5A); // Bei erreichen des Wertes im OCR1A soll ein Interrupt ausgelöst werden. OCF1A: Output Compare Flag 1A

      // Für's debuggen
      Serial.println("hi there!");

      //-Float ABS
      float absf(float f)
      return -f;
      return f;

      int v0=0; //-NULL value
      float f=0; //-Measurement value
      unsigned int FTW=0; //-Click generator rate
      unsigned int PCW=0; //-Click generator phase
      unsigned long timer=0; //-Click timer

      void loop()
      if(digitalRead(12)==LOW) //-Check NULL SW.
      v0=t; //-Sample new null value
      f=f*0.9+absf(t-v0)*0.1; //-Running average over 10 samples
      tflag=0; //-Reset flag

      float clf=f*SENSITIVITY; //-Convert measurement to click frequency


      //-Click generator

Leave a Reply