/* * EMF Meter with OLED Display * OpenParanormal Project * * Shows EMF reading on OLED screen with bar graph * * Hardware: * - ESP32 DevKit * - 0.96" OLED I2C Display (128x64) * - Hall effect sensor or coil * - Optional: LEDs for visual alerts * * Wiring: * OLED: * VCC → 3.3V * GND → GND * SCL → GPIO 22 * SDA → GPIO 21 * * Sensor: * VCC → 3.3V * GND → GND * OUT → GPIO 34 * * Libraries needed: * - Adafruit SSD1306 * - Adafruit GFX */ #include #include #include #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define SENSOR_PIN 34 #define SAMPLES 20 int readings[SAMPLES]; int readIndex = 0; int total = 0; int maxReading = 0; void setup() { Serial.begin(115200); // Initialize OLED if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println("OLED init failed!"); while(1); } display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.println("OpenParanormal"); display.println("EMF Meter"); display.println(); display.println("Initializing..."); display.display(); delay(2000); pinMode(SENSOR_PIN, INPUT); // Initialize readings for (int i = 0; i < SAMPLES; i++) { readings[i] = 0; } } void loop() { // Read sensor with smoothing int rawValue = analogRead(SENSOR_PIN); total = total - readings[readIndex]; readings[readIndex] = rawValue; total = total + readings[readIndex]; readIndex = (readIndex + 1) % SAMPLES; int emfValue = total / SAMPLES; // Track max for display scaling if (emfValue > maxReading) { maxReading = emfValue; } // Slowly decay max if (maxReading > 0) { maxReading--; } // Update display display.clearDisplay(); // Title display.setTextSize(1); display.setCursor(0, 0); display.println("EMF Detector"); // Numeric value display.setTextSize(2); display.setCursor(0, 12); display.print(emfValue); display.setTextSize(1); display.print(" mG"); // Bar graph int barWidth = map(emfValue, 0, 4095, 0, 128); display.fillRect(0, 35, barWidth, 10, SSD1306_WHITE); display.drawRect(0, 35, 128, 10, SSD1306_WHITE); // Level indicator display.setCursor(0, 50); if (emfValue < 100) { display.print("Level: BASELINE"); } else if (emfValue < 500) { display.print("Level: LOW"); } else if (emfValue < 1000) { display.print("Level: MEDIUM"); } else if (emfValue < 2000) { display.print("Level: HIGH"); } else { display.print("Level: VERY HIGH!"); } display.display(); delay(100); }