Detector de Metales de Bolsillo: Arduino Pro Mini con 4 Bobinas de Búsqueda Independientes
Componentes y Suministros
| SparkFun Arduino Pro Mini 328 - 5V/16MHz | ×1 |
Herramientas y Máquinas Necesarias
- Impresora 3D (genérica)
Sobre el Proyecto
Introducción: Detector de Metales de Bolsillo - Arduino
Este detector de metales de bolsillo es lo suficientemente sensible para identificar clavos y tachuelas pequeños en madera, y lo bastante compacto para caber en espacios incómodos, lo que lo hace cómodo de llevar y usar.
La unidad tiene 4 bobinas de búsqueda por inducción de pulso independientes e indicadores LED de color, permitiendo cubrir un área de búsqueda mayor rápidamente mientras se identifica el objetivo con precisión.
El dispositivo es auto-calibrante con un solo botón, recargable por USB y usa LEDs de color, sonido y vibración para indicar la fuerza del objetivo.
El tutorial incluye todos los diseños, pruebas, código y archivos 3D necesarios para construirlo. ¡Espero que disfrutéis construyéndolo y usándolo tanto como yo!
Paso 1: Lista de Materiales y Funcionamiento
1. Cómo Funciona
El detector usa 4 bobinas de inducción de pulso independientes alimentadas por un Arduino Pro Mini. Cada bobina tiene un bobinado TX y RX separado: se induce un pulso en TX creando un campo electromagnético alrededor de RX. El campo cambiante induce voltaje en RX, que se detecta y amplifica antes de leer el ancho de pulso con el Arduino.
Un algoritmo de suavizado en el código elimina ruido de pulsos válidos, dando gran estabilidad. Un algoritmo de calibración promedia lecturas al inicio y establece umbrales de comparación.
Cuando un objeto metálico entra en el campo electromagnético, este se perturba y parte de la energía se desvía hacia "corrientes de Foucault" en el objeto. Este efecto parasitario reduce el ancho de pulso detectado en RX. Esencialmente medimos la pérdida de potencia hacia el objeto objetivo.
Cuando el ancho de pulso cae por debajo del umbral, se encienden LEDs, suena el zumbador y se activa el motor de vibración háptica, según el tamaño predeterminado de la señal objetivo.
El circuito ha evolucionado en el último año a una configuración muy estable y fiable. La configuración y orientación de bobinas maximizan estabilidad y profundidad de detección.
2. Lista de Materiales
- Batería LiPo 3.7V 350mAh (38mm x 20mm x 7.5mm)
- Cargador USB LiPo TP4056 + Hoja de datos
- Resistencia 4.7K para limitar corriente de carga LiPo < 300mA
- Arduino Pro Mini
- Módulo FTDI USB a Serie para programar el Pro Mini
- LM339 Comparador Diferencial Cuádruple IC
- Placa Vero - 2 piezas cortadas a 20x9 y 34x9 agujeros (ver foto orientación)
- Transistor NPN BC548 × 4
- MOSFET 2N7000 × 5
- Zumbador Piezo
- Motor de Vibración Moneda para Feedback Háptico
- Módulo LED RGB WS2812 × 4
- Resistencias: 1k×4, 10k×4, 47Ω×4, 2.2k×4
- Condensador cerámico 150pf × 8
- Condensador poliéster 0.18uF × 4
- Rollo alambre de cobre esmaltado 0.3mm (~25g)
- Pulsador PCB
- Pistola de silicona caliente
- Brocas 10mm
- Taladro manual
- Etiquetadora o cinta para marcar 16 cables
- Hilo de conexión
- Acceso a impresora 3D
3. Operación del Comparador LM339
He recibido preguntas sobre el LM339, así que explico más claro:
El LM339 opera como comparador de voltaje, comparando voltaje diferencial entre pines positivo y negativo, y sacando lógica baja o alta impedancia (lógica alta con pull-up) según polaridad diferencial de entrada.
En este circuito, la entrada positiva del comparador va a Vcc y una resistencia pull-up a Vcc en la salida. En esta configuración, la salida se mantiene alta hasta que el voltaje en la entrada negativa supera 3.5V.
Según la hoja de datos LM339: "input voltage range" entre 0V y Vsup-1.5V. Cuando ambas entradas están en rango común, si IN- < IN+ + offset, salida alta impedancia. Cuando IN- > rango común e IN+ en rango común, salida baja y transistor de salida hunde corriente. Hoja de datos y explicación
Paso 2: Imprimir la Carcasa
La carcasa se imprime en 5 piezas separadas. Dimensiones y archivos 3D en Thingiverse. Diseño centrado en ergonomía y proximidad de bobinas al área de búsqueda.
Imprimir con cuidado y eliminar exceso de plástico. Importante hacerlo ahora para alinear componentes electrónicos antes del montaje final.
Paso 3: Construir y Montar Bobinas de Búsqueda
Enrollar 25 vueltas de alambre de cobre en cada formador impreso. Dejar 20cm extra para conexión a la unidad principal. Usar orificios del formador para enrollado consistente. Ir pegando el formador en la base según se avanza.
Resultado: 8 bobinas montadas (4 TX + 4 RX) con cables orientados consistentemente y longitud suficiente para conectar a la placa principal en la carcasa superior. Usar los dos bloques guía de cables (con orificios para cada bobina) en la base impresa para organizar cada bobina específica.
Coloqué cables de bobinas internas arriba y externas abajo en el bloque guía para rastrear cada bobina fácilmente al conectar a la placa principal.
Paso 4: Construir el Circuito
La unidad tiene 4 circuitos clave independientes: Placa Driver, Placa Principal, Ensamblaje LED y Fuente Recargable. Aquí construimos Driver y Principal.
1. Placa Driver
Cortar placa Vero 22x11 agujeros → resultado 20x9 agujeros (orientación según foto). Marcar con cúter ambos lados y partir. Verificar que entra en base con holgura. Romper pistas marcadas con broca 10mm a mano. Seguir diagrama y foto para ensamblar, evitando cortocircuitos. Reservar para test.
2. Placa Principal
Cortar Vero 36x11 → 34x9 agujeros. Mismo proceso: marcar, partir, romper pistas. Seguir diagrama para Arduino, LM339 y componentes. Verificar sin cortocircuitos. Reservar.
Paso 5: Añadir Indicadores LED
Usé LEDs WS2812 (NeoPixel) con IC integrado, direccionables desde Arduino con 3 hilos, permitiendo amplia gama de colores/brillo mediante librería especial (sección test).
1. Montar LEDs en Tapa de Bobinas
Posicionar 4 LEDs orientados correctamente (VCC/GND alineados, centrados en orificios). Fijar con silicona caliente.
2. Cablear LEDs
Pelado y posicionado 3 hilos unipolares 25cm sobre contactos LED. Soldar asegurando hilo central de datos conectado IN/OUT según foto.
3. Verificación Alineación Carcasa
Verificar que tapa encaja a ras con carcasa de bobinas. Fijar cables con silicona en base de tapa. Reservar para test.
Paso 6: Ensamblar y Testear la Unidad
1. Preparación para Ensamblaje
Testear cada placa progresivamente para facilitar troubleshooting. El Pro Mini necesita adaptador USB-serie para programar desde PC (ver lista piezas). Antes de cargar código, añadir librería FastLED.h en Arduino IDE para WS2812. Se proveen trazas osciloscopio y captura Serial Plotter para troubleshooting.
Dos versiones del código: una con datos seriales de test para troubleshooting.
NOTA: No conectar batería LiPo hasta el último paso. Cortocircuito accidental durante montaje puede causar sobrecalentamiento o incendio.
2. Test Placa Principal
Conectar cable serie Arduino y verificar carga de código. Debe cargar sin errores y sin humo.
3. Conectar Placa Driver
Seguir diagrama para conectar Driver a Principal. Posicionar en carcasa verificando ajuste. Cargar código: sin errores ni humo.
4. Conectar Bobinas
Seguir diagrama conectar bobinas a Principal. Verificar alineación con entradas Driver/Principal. Con código de test, puerto serial muestra ancho de pulso en bobina RX entre 5000-7000µS (visible también en Graph Plotter IDE). Permite troubleshooting cada canal y ver efecto de acercar moneda (reduce ancho pulso). Con osciloscopio, verificar formas de onda en varias etapas. Una vez todos canales ok, posicionar cables para que carcasa cierre.
5. Conectar LEDs
Conectar 3 hilos de LEDs a placa principal. Cargar código y verificar LEDs. Fijar tapa de bobinas con silicona.
Paso 7: Conectar Batería Recargable
NOTAS DE SEGURIDAD:
- No conectar LiPo hasta el final. Cortocircuito accidental puede causar sobrecalentamiento/incendio.
- Manipular batería y cargador con cuidado, evitando cortocircuitar conexiones.
- LiPos son distintas a otras recargables: sobrecorriente en carga es peligroso. Configurar circuito carga correctamente.
- No conectar cable serie Arduino con botón de encendido pulsado, podría dañar batería.
1. Modificar Límite Corriente Cargador
El detector usa LiPo cargable por Micro USB. El cargador TP4056 se modifica con resistencia 4.7K para limitar carga < 300mA. Instrucciones aquí. Requiere desoldar resistencia SMD original y soldar la nueva (foto). Proteger con silicona. Testear conectando cargador móvil Micro USB: luz roja carga debe encender.
2. Instalar Pulsador Encendido
Montar pulsador en posición correcta (sobresale por centro tapa). Soldar según diagrama: entre pulsador, salida cargador y línea VCC Arduino. Al pulsar, activa unidad. Fijar batería con silicona y alinear Micro USB con orificio tapa para carga.
Paso 8: Test Final y Operación
1. Ensamblaje Físico
Reorganizar cables para que carcasa cierre. Fijar placa principal en tapa con silicona y cerrar.
2. Operación
La unidad calibra manteniendo pulsado botón encendido. Todos LEDs parpadean cuando lista. Mantener botón pulsado durante búsqueda. LEDs cambian Azul-Verde → Rojo → Púrpura según fuerza objetivo. Feedback háptico al ponerse púrpura.
¡Listo para usar en aplicaciones prácticas!
Código
Pocket_Metal_Locator_V11.ino
C/C++
/* Pocket Metal Locator - Arduino Pro Mini April 2018 TechKiwiGradgets Version 11 - First Instructable Release */
// WS2812 LED Driver Library Setup
#include "FastLED.h"
#define NUM_LEDS 4
#define DATA_PIN 11
CRGB leds[NUM_LEDS];
// Smoothing Variables for LPF
const float alpha = 0.85;
float smoothedvalue1 = 1000;
float smoothedvalue2 = 1000;
float smoothedvalue3 = 1000;
float smoothedvalue4 = 1000;
int sthreshold = 100;
float ledthreshold1 = 0.93;
float ledthreshold2 = 0.96;
float ledthreshold3 = 0.99;
float ledthreshold4 = 0.998;
// Calibration Variables
boolean sample = false;
int calcounter = 0;
int scount = 200;
int numsamples = 20;
int t1 = 100;
long calav1 = 0, calav2 = 0, calav3 = 0, calav4 = 0;
int div1 = 0, div2 = 0, div3 = 0, div4 = 0;
// Four Channels
int divA = 0; long tempA = 0; long pcounterA = 0;
int divB = 0; long tempB = 0; long pcounterB = 0;
int divC = 0; long tempC = 0; long pcounterC = 0;
int divD = 0; long tempD = 0; long pcounterD = 0;
int pwindow = 7500;
// Timing
int dly1 = 4;
int dly2 = 1;
int dly3 = 500;
int threshdiff = 15;
long pulseav = 0;
// Vibration Motor
boolean haptic = false;
int vduration = 1;
int vcounter = vduration;
void setup() {
pinMode(12, OUTPUT); digitalWrite(12, LOW);
Serial.begin(115200);
LEDS.addLeds(leds,NUM_LEDS);
LEDS.setBrightness(5);
FastLED.setMaxPowerInVoltsAndMilliamps(5,100);
FastLED.setDither(0);
pinMode(10, OUTPUT); // Piezo
pinMode(2, OUTPUT); pinMode(4, OUTPUT); pinMode(6, OUTPUT); pinMode(8, OUTPUT); // TX
pinMode(3, INPUT); pinMode(5, INPUT); pinMode(7, INPUT); pinMode(9, INPUT); // RX
}
void loop() {
// Channel 1
digitalWrite(2, HIGH); delayMicroseconds(dly1);
digitalWrite(2, LOW); delayMicroseconds(dly2);
pcounterA = pulseIn(3, LOW, pwindow);
digitalWrite(2, LOW); delayMicroseconds(dly3);
if (pcounterA >= sthreshold) smoothedvalue1 = (alpha * smoothedvalue1) + ((1 - alpha) * pcounterA);
pcounterA = smoothedvalue1;
// Channel 2
digitalWrite(4, HIGH); delayMicroseconds(dly1);
digitalWrite(4, LOW); delayMicroseconds(dly2);
pcounterB = pulseIn(5, LOW, pwindow);
digitalWrite(4, LOW); delayMicroseconds(dly3);
if (pcounterB >= sthreshold) smoothedvalue2 = (alpha * smoothedvalue2) + ((1 - alpha) * pcounterB);
pcounterB = smoothedvalue2;
// Channel 3
digitalWrite(6, HIGH); delayMicroseconds(dly1);
digitalWrite(6, LOW); delayMicroseconds(dly2);
pcounterC = pulseIn(7, LOW, pwindow);
digitalWrite(6, LOW);
if (pcounterC >= sthreshold) smoothedvalue3 = (alpha * smoothedvalue3) + ((1 - alpha) * pcounterC);
pcounterC = smoothedvalue3;
// Channel 4
digitalWrite(8, HIGH); delayMicroseconds(dly1);
digitalWrite(8, LOW); delayMicroseconds(dly2);
pcounterD = pulseIn(9, LOW, pwindow);
digitalWrite(8, LOW); delayMicroseconds(dly3);
if (pcounterD >= sthreshold) smoothedvalue4 = (alpha * smoothedvalue4) + ((1 - alpha) * pcounterD);
pcounterD = smoothedvalue4;
// Calibration on Powerup
if (sample == false) calcounter++;
if (calcounter > (scount - numsamples)) {
if (pcounterA > sthreshold) { calav1 += pcounterA; div1++; }
if (pcounterB > sthreshold) { calav2 += pcounterB; div2++; }
if (pcounterC > sthreshold) { calav3 += pcounterC; div3++; }
if (pcounterD > sthreshold) { calav4 += pcounterD; div4++; }
}
if ((calcounter > scount) && (sample == false)) {
calav1 /= div1; calav2 /= div2; calav3 /= div3; calav4 /= div4;
// Flash LEDs to show calibration done
for (int i = 3; i >= 0; i--) { leds[i] = CRGB::Blue; FastLED.show(); delay(t1); leds[i] = CRGB::Black; }
for (int i = 3; i >= 0; i--) { leds[i] = CRGB::Green; FastLED.show(); delay(t1); leds[i] = CRGB::Black; }
FastLED.show();
digitalWrite(10, LOW);
sample = true; calcounter = 0;
}
if (sample == true) updateLEDs();
// Haptic Feedback
if (haptic) {
digitalWrite(12, HIGH);
if (vcounter >= 1) vcounter--;
else { digitalWrite(12, LOW); haptic = false; vcounter = vduration; }
}
}
void updateLEDs() {
leds[0] = leds[1] = leds[2] = leds[3] = CRGB::Black;
digitalWrite(10, LOW); digitalWrite(12, LOW);
// Channel 1
if (pcounterA < (calav1 * ledthreshold1)) { leds[3] = CRGB::Purple; digitalWrite(10, HIGH); haptic = true; }
else if (pcounterA < (calav1 * ledthreshold2)) { leds[3] = CRGB::Red; haptic = true; }
else if (pcounterA < (calav1 * ledthreshold3)) { leds[3] = CRGB::Green; haptic = true; }
else if (pcounterA < (calav1 * ledthreshold4)) { leds[3] = CRGB::Blue; }
// Channel 2
if (pcounterB < calav2 * ledthreshold1) { leds[2] = CRGB::Purple; digitalWrite(10, HIGH); haptic = true; }
else if (pcounterB < calav2 * ledthreshold2) { leds[2] = CRGB::Red; haptic = true; }
else if (pcounterB < calav2 * ledthreshold3) { leds[2] = CRGB::Green; haptic = true; }
else if (pcounterB < calav2 * ledthreshold4) { leds[2] = CRGB::Blue; }
// Channel 3
if (pcounterC < calav3 * ledthreshold1) { leds[1] = CRGB::Purple; digitalWrite(10, HIGH); haptic = true; }
else if (pcounterC < calav3 * ledthreshold2) { leds[1] = CRGB::Red; haptic = true; }
else if (pcounterC < calav3 * ledthreshold3) { leds[1] = CRGB::Green; haptic = true; }
else if (pcounterC < calav3 * ledthreshold4) { leds[1] = CRGB::Blue; }
// Channel 4
if (pcounterD < calav4 * ledthreshold1) { leds[0] = CRGB::Purple; digitalWrite(10, HIGH); haptic = true; }
else if (pcounterD < calav4 * ledthreshold2) { leds[0] = CRGB::Red; haptic = true; }
else if (pcounterD < calav4 * ledthreshold3) { leds[0] = CRGB::Green; haptic = true; }
else if (pcounterD < calav4 * ledthreshold4) { leds[0] = CRGB::Blue; }
FastLED.show();
}
Piezas Personalizadas y Carcasas
Thingiverse
Archivos CAD en thingiverse.com
Esquemáticos
Proceso de manufactura
- Filtros Cerámicos para Fundición de Metales Fundidos: Diseño, Producción y Perspectivas de Mercado
- Monitor de temperatura para coche con Arduino: prevención de golpes de calor en niños
- Dominar la Forja: 16 Técnicas Esenciales para Principiantes y Expertos
- Punzonado de Chapa: Ventaja Rentable para la Fabricación Moderna
- Entendiendo el Punzonado de Chapa: Proceso, Herramientas y Aplicaciones
- Máquinas de Metal Perforado de Alta Precisión y sus Aplicaciones
- Entendiendo las Fundiciones: Donde el Metal se Convierte en Bloques de Construcción de la Industria Moderna
- Dominando el Corte de Bobinas: Corte de Precisión de Bobinas Metálicas
- Chapa metálica delgada: aplicaciones versátiles del acero inoxidable
- Enderezado de chapa metálica: qué es y por qué importa
- Soluciones de cizallado de metal de precisión para acero y aluminio