This experimental project shows how to build an AVR microcontroller based simple PI (Pulse Induction) metal detector. My goals were to make a circuit as simple as possible and to use only popular / cheap electronic parts. The device has been tested with very small coil (55mm diameter, about 30 turns of 0.5 DNE) and only 3.0V power supply. It’s my first design of PI metal detector and I’m really happy with the results! The prototype was able to detect little coins (6cm distance) and wires in the wall. The code is on GitHub, here.
How It Works?Presented metal detector uses PI method to generate a voltage spike in a search coil connected in parallel with capacitor. Next, ATtiny13 uses an Analog Comparator to measure a decay time to zero of resonant circuit. When a metal object nears the loop it will decrease time it takes for the pulse to decay to zero. The change in the width of resonance time is measured to signal the presents of a metal target.
Note that the typical PI detector designs avoid resonant circuit and the measured factor is slightly different!
User Instructions- Turn on the device. The calibration process takes about second and ends with buzzer signal.
- Use variable resistor to adjust detector sensitivity (you can find it somewhere between a continuous buzzer signal and complete silent).
- The device is ready to work!
- ATtiny13 – i.e. MBAVR-1 development board
- T1 – IRF3205 (MOSFET; N-Channel)
- LED1 – basic LED
- D1 – i.e. 1N4007
- D2, D3 – 1N4148
- R1 – variable resistor 10kΩ
- R2, R3 – 220Ω (5%), see LED Resistor Calculator
- R4 – 330Ω (5%)
- R5, R6 – 10kΩ (5%)
- C1 – 470nF
- L1 – ∅ 50-55mm, about 30 turns of 0.5 DNE
This code is written in C and can be compiled using the avr-gcc. All information about how to compile this project is here.
/**
* Copyright (c) 2019, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
* ATtiny13/037
* Example of simple PI (Pulse Induction) metal detector.
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define COIL_PIN PB2
#define BUZZER_PIN PB3
#define LED_PIN PB4
#define PULSE_WIDTH (32) // microseconds
#define CALIBRATION_ATTEMPTS_MAX (128)
#define MEASUREMENT_ATTEMPTS_MAX (2048)
#define SIGNAL_ON() (PORTB |= _BV(LED_PIN)|_BV(BUZZER_PIN))
#define SIGNAL_OFF() (PORTB &= ~(_BV(LED_PIN)|_BV(BUZZER_PIN)))
static uint16_t
measure_decay(void)
{
uint16_t i, counter = 0, decay = 0;
PORTB |= _BV(COIL_PIN); // pulse on
_delay_us(PULSE_WIDTH); // pulse delay
PORTB &= ~_BV(COIL_PIN); // pulse off
for (i = 0; i < MEASUREMENT_ATTEMPTS_MAX; ++i) {
if (ACSR & _BV(ACO)) {
decay = counter;
}
counter++;
}
return decay;
}
static uint16_t
calibration(void)
{
uint8_t i;
uint16_t tmp, decay = 0;
/* calibration process */
for (i = 0; i < CALIBRATION_ATTEMPTS_MAX; ++i) {
tmp = measure_decay();
if (tmp > decay) {
decay = tmp;
}
}
/* signalize end of calibration */
for (i = 0; i < 3; ++i) {
for (tmp = 0; tmp < 64; ++tmp) {
SIGNAL_ON();
_delay_ms(0.3);
SIGNAL_OFF();
_delay_ms(0.3);
}
_delay_ms(64);
}
return decay;
}
int
main(void)
{
uint16_t decay_cur, decay_max;
/* setup */
DDRB = _BV(COIL_PIN)|_BV(LED_PIN)|_BV(BUZZER_PIN); // set COIL, LED and BUZZER pins as output
ACSR = 0; // clear register
decay_max = calibration() - 1;
_delay_ms(500);
/* loop */
while (1) {
decay_cur = measure_decay();
if (decay_cur < decay_max) {
SIGNAL_ON();
_delay_us(100);
}
SIGNAL_OFF();
}
}
References- http://www2.gi.alaska.edu/~jesse/treasure/misc/howdetector.html
- https://svet-el.si/download/Metal%20detector.pdf
- http://www.nuggetshooter.com/articles/UnderstandingPIdetector.html
- ATtiny13 – clap clap switch
- ATtiny13 – randomly flashing LED with PRNG based on BBS
- ATtiny13 – IR remote to control LEDs (NEC proto)
- ATtiny13 – pseudo random numbers
- ATtiny13 – controlling LED RGB | fancy light effects
- ATtiny13 – controlling stepper motor 28BYJ-48
- ATtiny13 – simple timer on TM1637
- ATtiny13 – dance lights with FFT
- ATtiny13 – blinky with timer COMPA (assembler version)
- ATtiny13 – two tone alarm
Comments