Walkthrough Metal Detector Based on FG-3+ and Arduino UNO R4 WiFi
This project demonstrates a low-cost and sensitive walkthrough metal detector using the FG-3+ fluxgate magnetometer sensor paired with the Arduino UNO R4 WiFi. The device detects the presence of metal objects based on perturbations in the ambient magnetic field, a matrix display shows an exclamation mark "!" whenever a metal object is detected near the walkthrough detector.
Devices & Components
1
Arduino® UNO R4 WiFi
1
40 colored male-female jumper wires
1
FG-3+ Sensor
Software & Tools
1
Arduino IDE
Project description
Code
Walkthrough Detector Code
cpp
Code for Arduino UNO R4
1#include <Arduino_LED_Matrix.h> 2 3const int sensorDig = 2; // Digital pin 2 for sensor input (interrupt pin) 4 5unsigned int updateRate = 100; // Sensor update rate in ms 6unsigned int measureTime = 100; // Sensor measure time in ms 7 8volatile unsigned int intEnable = 0; // Interrupt counter enable flag 9volatile unsigned long sensorDigCnt = 0; // Count of sensor signal changes 10unsigned long prevMillis = 0; // For timing updates 11 12float base_line = 0.0; // Moving average baseline 13const float alpha = 0.1; // Smoothing factor for baseline 14const float base_line_change = 10.0; // Threshold for significant change 15const int N = 10; // Number of samples for peak event duration 16 17int peakSamplesCount = 0; // Samples counted during peak event 18bool inPeakEvent = false; // Flag: tracking a peak event? 19float peakValue = 0.0; // Maximum deviation recorded during peak event 20 21int state = 0; // State machine variable 22 23// LED matrix setup 24ArduinoLEDMatrix matrix; 25 26const int matrixWidth = 12; 27const int matrixHeight = 8; 28 29// Alert sign bitmap 10x7 pixels (largest fitting design) 30// A large exclamation mark ! with border 31const uint8_t alertWidth = 10; 32const uint8_t alertHeight = 7; 33const uint8_t alertBitmap[alertHeight] = { 34 0b0000110000, // border top 35 0b0000110000, // | ! | 36 0b0000110000, // | ! | 37 0b0000110000, // | ! | 38 0b0000000000, // | ! | 39 0b0000110000, // | ! | 40 0b0000110000 // border bottom 41}; 42 43uint8_t frame[matrixHeight][matrixWidth]; 44 45void clearFrame() { 46 for (int y = 0; y < matrixHeight; y++) { 47 for (int x = 0; x < matrixWidth; x++) { 48 frame[y][x] = 0; 49 } 50 } 51} 52 53void drawAlert(int xPos, int yPos) { 54 clearFrame(); 55 for (int row = 0; row < alertHeight; row++) { 56 for (int col = 0; col < alertWidth; col++) { 57 bool pixelOn = alertBitmap[row] & (1 << (alertWidth - 1 - col)); 58 int x = xPos + col; 59 int y = yPos + row; 60 if (pixelOn && x >= 0 && x < matrixWidth && y >= 0 && y < matrixHeight) { 61 frame[y][x] = 1; 62 } 63 } 64 } 65 matrix.renderBitmap(frame, matrixHeight, matrixWidth); 66} 67 68void setup() { 69 Serial.begin(115200); 70 pinMode(sensorDig, INPUT); 71 attachInterrupt(digitalPinToInterrupt(sensorDig), sensorDigHandler, RISING); 72 73 matrix.begin(); 74 matrix.clear(); 75 76 // Initialize baseline with first measurement 77 sensorDigCnt = 0; 78 intEnable = 1; 79 delay(measureTime); 80 intEnable = 0; 81 base_line = sensorDigCnt; 82 Serial.print("Initial baseline: "); 83 Serial.println(base_line); 84 85 prevMillis = millis(); 86} 87 88void loop() { 89 unsigned long currMillis = millis(); 90 91 switch (state) { 92 case 1: 93 // Update baseline (moving average) 94 base_line = alpha * sensorDigCnt + (1.0 - alpha) * base_line; 95 96 // Calculate deviation from baseline 97 float diff = sensorDigCnt - base_line; 98 99 if (!inPeakEvent) { 100 // Not currently tracking a peak event 101 if (abs(diff) > base_line_change) { 102 inPeakEvent = true; 103 peakSamplesCount = 1; 104 peakValue = diff; 105 } 106 } else { 107 // Tracking peak event 108 peakSamplesCount++; 109 if (abs(diff) > abs(peakValue)) { 110 peakValue = diff; 111 } 112 113 // End peak detection when signal returns near baseline or max samples reached 114 if (abs(diff) <= base_line_change || peakSamplesCount > N) { 115 Serial.print("Peak detected: "); 116 Serial.println(peakValue); 117 inPeakEvent = false; 118 peakSamplesCount = 0; 119 peakValue = 0.0; 120 121 // Display alert sign centered on the matrix 122 drawAlert((matrixWidth - alertWidth) / 2, (matrixHeight - alertHeight) / 2); 123 delay(2000); // Display alert for 2 seconds 124 matrix.clear(); 125 } 126 } 127 128 Serial.print("Sensor= "); 129 Serial.print(sensorDigCnt); 130 Serial.print(" Baseline= "); 131 Serial.println(base_line); 132 133 state = 0; 134 break; 135 } 136 137 if (currMillis - prevMillis >= updateRate) { 138 sensorDigCnt = 0; 139 prevMillis = currMillis; 140 intEnable = 1; 141 delay(measureTime); 142 intEnable = 0; 143 state = 1; 144 } 145} 146 147// Interrupt handler increments counter on rising edge 148void sensorDigHandler() { 149 if (intEnable == 1) { 150 sensorDigCnt++; 151 } 152}
Comments
Only logged in users can leave comments