Traffic Detection and Counter Using FG-3+ and Arduino UNO R4 WiFi
Create a low-cost, traffic monitoring system by deploying the FG-3+ fluxgate magnetometer near roads to detect magnetic disturbances caused by passing vehicles. Use the Arduino UNO R4 WiFi to detect vehicles, and optionally timestamp data, and upload real-time traffic analytics to the Arduino Cloud for remote monitoring and historical trend analysis.
Devices & Components
1
Arduino® UNO R4 WiFi
1
40 colored male-female jumper wires
1
FG-3+ Sensor
Software & Tools
Arduino IDE
Project description
Code
Traffic Counter Code
cpp
Traffic Counter Code for Arduino Uno R4 WiFi
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// Car bitmap 7x5 pixels 30const uint8_t carWidth = 7; 31const uint8_t carHeight = 5; 32const uint8_t carBitmap[carHeight] = { 33 0b011110, // roof shape 34 0b1111111, // upper body 35 0b1111111, // lower body 36 0b0110110, // wheels 37 0b0000000 // chassis detail 38}; 39 40uint8_t frame[matrixHeight][matrixWidth]; 41 42void clearFrame() { 43 for (int y = 0; y < matrixHeight; y++) { 44 for (int x = 0; x < matrixWidth; x++) { 45 frame[y][x] = 0; 46 } 47 } 48} 49 50void drawCar(int xPos) { 51 clearFrame(); 52 for (int row = 0; row < carHeight; row++) { 53 for (int col = 0; col < carWidth; col++) { 54 bool pixelOn = carBitmap[row] & (1 << (carWidth - 1 - col)); 55 int x = xPos + col; 56 int y = (matrixHeight - carHeight) + row; // bottom aligned 57 if (pixelOn && x >= 0 && x < matrixWidth && y >= 0 && y < matrixHeight) { 58 frame[y][x] = 1; 59 } 60 } 61 } 62 matrix.renderBitmap(frame, matrixHeight, matrixWidth); 63} 64 65void playCarAnimation() { 66 // Animate car moving from right to left 67 for (int x = matrixWidth; x >= -carWidth; x--) { 68 drawCar(x); 69 delay(150); // Simple blocking delay; consider millis() for non-blocking 70 } 71 matrix.clear(); 72} 73 74void setup() { 75 Serial.begin(115200); 76 pinMode(sensorDig, INPUT); 77 attachInterrupt(digitalPinToInterrupt(sensorDig), sensorDigHandler, RISING); 78 79 matrix.begin(); 80 matrix.clear(); 81 82 // Initialize baseline with first measurement 83 sensorDigCnt = 0; 84 intEnable = 1; 85 delay(measureTime); 86 intEnable = 0; 87 base_line = sensorDigCnt; 88 Serial.print("Initial baseline: "); 89 Serial.println(base_line); 90 91 prevMillis = millis(); 92} 93 94void loop() { 95 unsigned long currMillis = millis(); 96 97 switch (state) { 98 case 1: 99 // Update baseline (moving average) 100 base_line = alpha * sensorDigCnt + (1.0 - alpha) * base_line; 101 102 // Calculate deviation from baseline 103 float diff = sensorDigCnt - base_line; 104 105 if (!inPeakEvent) { 106 // Not currently tracking a peak event 107 if (abs(diff) > base_line_change) { 108 inPeakEvent = true; 109 peakSamplesCount = 1; 110 peakValue = diff; 111 } 112 } else { 113 // Tracking peak event 114 peakSamplesCount++; 115 if (abs(diff) > abs(peakValue)) { 116 peakValue = diff; 117 } 118 119 // End peak detection when signal returns near baseline or max samples reached 120 if (abs(diff) <= base_line_change || peakSamplesCount > N) { 121 Serial.print("Peak detected: "); 122 Serial.println(peakValue); 123 inPeakEvent = false; 124 peakSamplesCount = 0; 125 peakValue = 0.0; 126 127 // Trigger car animation on new peak detected 128 playCarAnimation(); 129 } 130 } 131 132 Serial.print("Sensor= "); 133 Serial.print(sensorDigCnt); 134 Serial.print(" Baseline= "); 135 Serial.println(base_line); 136 137 state = 0; 138 break; 139 } 140 141 if (currMillis - prevMillis >= updateRate) { 142 sensorDigCnt = 0; 143 prevMillis = currMillis; 144 intEnable = 1; 145 delay(measureTime); 146 intEnable = 0; 147 state = 1; 148 } 149} 150 151// Interrupt handler increments counter on rising edge 152void sensorDigHandler() { 153 if (intEnable == 1) { 154 sensorDigCnt++; 155 } 156}
Comments
Only logged in users can leave comments