"Die Wege eines Bastlers sind unergründlich" ... oder so ähnlich.
Es begann alles wie sonst auch: eine glorreiche Idee, die einfach umzusetzen ist und einen nützlichen EMF-Detektor hervorbringen soll. Nun ja, von "einfach umzusetzen" wurde (wie meistens) ein ziemlich kompliziertes, komplexes und oft frustrierendes Projekt. Vom anfänglichen Konzept blieb eigentlich nur die grundlegende Technik zum Einlesen EMF-Werte. Ich wollte das Ganze in einem Alu-Druckgussgehäuse mit einem eigenen Plastikgehäuse für die LEDs unterbringen, was sich allerdings als nicht machbar herausstellte. Auf der Suche nach einer Alternative habe ich meine Wohnung umgekrempelt und fand meine alte Agfa Synchrobox. TADAAA !!! Neues Gehäuse gefunden !
Nach dem Entfernen des Innenlebens und etlichen, auch mal blutigen Anpassungen konnte ich das Ganze im Gehäuse montieren. Das Verstauen der Kabel gestaltete sich jedoch ziemlich schwierig, aber möglich. Im Endeffekt entstand ein EMF-Detektor mit ein paar Anpassungsfunktionen im Retro-Stil .
Samples: 10 oder 30
Hierbei werden 10 oder 30 Messungen von der Antenne in einer Schleife genommen und dann daraus der Mittelwert berechnet. Dadurch wird ein Signalrauschen weitgehend eliminiert und man erhält einen durchgehenderen Wert: je mehr Samples genommen werden, desto glatter ist der Wert.Empfindlichkeit:
Mit diesem Schalter wird hardwaremäßig zwischen zwei unterschiedlichen Widerständen umgeschaltet. Dabei erhöht bzw. verringert sich die Empfindlichkeit des Eingangssignals der Antenne. Dies kann bei sehr hohen EMF-Werten praktisch sein, wenn dadurch die LEDs bereits am Anschlag sind.Referenz-/Aktueller Wert:
Beim Einschalten werden 100 Samples gezogen und der Mittelwert berechnet. Dieser dient als Referenzwert. Beim aktuellen Wert werden 10 oder 30 Samples gezogen (siehe oben).Der Arduino-Code:
Code: Alles auswählen
/*
* measure adc voltage accurately by taking multiple readings - see notes on this page
* http://www.skillbank.co.uk/arduino/adc1.htm
*
* www.skillbank.co.uk Sept 2020
*/
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
//Analog input and pin assignments
const byte V1Pin = A0; // use will use analog pin 1 for voltage 1
int reading; //the value we read from the ADC
int nSamp1 = 10;
int nSamp = nSamp1; // Number of Samples to take for each reading - best if it's a power of two.
int nSamp2 = 30;
int interval = 2; // milliseconds interval between successive readings
unsigned long sum1 = 0; // the total of nSamp readings from the ADC
//calculating voltages
int result; // calculated value of measured voltage in millivolts
float vScale = 5; //choose the right scale to suit the reference you have chosen.
//float vScale=3.3;
//float vScale=2.56;
//float vScale = 1.1;
//*** If you calibrate the system you can adjust the value of vScale to give more accurate readings.
uint8_t displayVal;
int LED_WEISS1 = 3;
int LED_WEISS2 = 4;
int LED_GRUN1 = 5;
int LED_GRUN2 = 6;
int LED_BLAU1 = 7;
int LED_BLAU2 = 8;
int LED_GELB1 = 9;
int LED_GELB2 = 10;
int LED_ROT1 = 11;
int LED_ROT2 = 12;
float faktor = 1;
int w1 = 110;
int w2 = 220;
int w3 = 330;
int w4 = 440;
int w5 = 550;
int w6 = 660;
int w7 = 770;
int w8 = 880;
int w9 = 990;
int ref = 0;
int spalte2 = 36;
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;) {
digitalWrite(LED_GRUN1, HIGH);
delay(2000);
digitalWrite(LED_GRUN1, LOW);
}; // Don't proceed, loop forever
}
// Clear the buffer
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE, SSD1306_BLACK); // Draw white text
display.cp437(true); // Use full 256 char 'Code Page 437' font
analogReference(DEFAULT); // program is being tested on a 5V Arduino Micro Pro - 32U4 chip so this will be 5.0V
//*** The chip on your Arduino - depending on type - is provided with SOME of the following reference voltages
//DEFAULT: the default analog reference of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards)
//INTERNAL: a built-in reference, equal to 1.1 volts on the ATmega168 or ATmega328 and 2.56 volts on the ATmega8 and 32U4 chip boards.
//EXTERNAL: the voltage applied to the AREF pin. The Arduino Micro Pro does not have a pin to let you do this
vScale = vScale * 1000 / 1024; //scale the reading to read in millivolts
reading = analogRead(V1Pin); // dummy read to settle ADC Mux
delay(500);
pinMode(LED_WEISS1, OUTPUT);
pinMode(LED_WEISS2, OUTPUT);
pinMode(LED_GRUN1, OUTPUT);
pinMode(LED_GRUN2, OUTPUT);
pinMode(LED_GELB1, OUTPUT);
pinMode(LED_GELB2, OUTPUT);
pinMode(LED_ROT1, OUTPUT);
pinMode(LED_ROT2, OUTPUT);
pinMode(LED_BLAU1, OUTPUT);
pinMode(LED_BLAU2, OUTPUT);
// START - LED Test
digitalWrite(LED_WEISS1, HIGH);
delay(100);
digitalWrite(LED_WEISS2, HIGH);
delay(100);
digitalWrite(LED_GRUN1, HIGH);
delay(100);
digitalWrite(LED_GRUN2, HIGH);
delay(100);
digitalWrite(LED_BLAU1, HIGH);
delay(100);
digitalWrite(LED_BLAU2, HIGH);
delay(100);
digitalWrite(LED_GELB1, HIGH);
delay(100);
digitalWrite(LED_GELB2, HIGH);
delay(100);
digitalWrite(LED_ROT1, HIGH);
delay(100);
digitalWrite(LED_ROT2, HIGH);
delay(2500);
digitalWrite(LED_WEISS1, LOW);
digitalWrite(LED_WEISS2, LOW);
digitalWrite(LED_GRUN1, LOW);
digitalWrite(LED_GRUN2, LOW);
digitalWrite(LED_BLAU1, LOW);
digitalWrite(LED_BLAU2, LOW);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
for (byte count = 0; count < 100; count++) {
reading = analogRead(V1Pin); // actual read
sum1 = sum1 + reading;
delay(7);
}
ref = convReadings(sum1, 100, vScale);
if (ref < 0) ref = 0;
//if (ref < w1) faktor = 0.5;
//if (ref > w9) faktor = 2;
pinMode(15, INPUT_PULLUP);
}
void loop() {
sum1 = 0; //ready to start adding values
//add up nSamp successive readings;
for (byte count = 0; count < nSamp; count++) {
reading = analogRead(V1Pin); // actual read
sum1 = sum1 + reading;
delay(interval);
}
// we print reading values to help with calibration
Serial.print(nSamp);
Serial.print(" ");
Serial.print(String(sum1));
result = convReadings(sum1, nSamp, vScale);
Serial.print(" ");
//Serial.print("Voltage is ");
Serial.println(result);
//Serial.println(" millivolts.");
delay(1);
display.setCursor(0, 0);
display.print("R:");
display.setCursor(spalte2, 0);
display.print(String(ref) + " mV ");
display.setCursor(0, 16);
display.print("A:");
display.setCursor(spalte2, 16);
display.print(String(result) + " ");
display.setCursor(spalte2 + 54, 16);
display.print(String(nSamp) + " ");
display.display();
if (result < (w1 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, LOW);
digitalWrite(LED_GRUN1, LOW);
digitalWrite(LED_GRUN2, LOW);
digitalWrite(LED_BLAU1, LOW);
digitalWrite(LED_BLAU2, LOW);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w1 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, LOW);
digitalWrite(LED_GRUN2, LOW);
digitalWrite(LED_BLAU1, LOW);
digitalWrite(LED_BLAU2, LOW);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w2 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, LOW);
digitalWrite(LED_BLAU1, LOW);
digitalWrite(LED_BLAU2, LOW);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w3 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, LOW);
digitalWrite(LED_BLAU2, LOW);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w4 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, HIGH);
digitalWrite(LED_BLAU2, LOW);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w5 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, HIGH);
digitalWrite(LED_BLAU2, HIGH);
digitalWrite(LED_GELB1, LOW);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w6 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, HIGH);
digitalWrite(LED_BLAU2, HIGH);
digitalWrite(LED_GELB1, HIGH);
digitalWrite(LED_GELB2, LOW);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w7 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, HIGH);
digitalWrite(LED_BLAU2, HIGH);
digitalWrite(LED_GELB1, HIGH);
digitalWrite(LED_GELB2, HIGH);
digitalWrite(LED_ROT1, LOW);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w8 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, HIGH);
digitalWrite(LED_BLAU2, HIGH);
digitalWrite(LED_GELB1, HIGH);
digitalWrite(LED_GELB2, HIGH);
digitalWrite(LED_ROT1, HIGH);
digitalWrite(LED_ROT2, LOW);
}
if (result >= (w9 * faktor)) {
digitalWrite(LED_WEISS1, HIGH);
digitalWrite(LED_WEISS2, HIGH);
digitalWrite(LED_GRUN1, HIGH);
digitalWrite(LED_GRUN2, HIGH);
digitalWrite(LED_BLAU1, HIGH);
digitalWrite(LED_BLAU2, HIGH);
digitalWrite(LED_GELB1, HIGH);
digitalWrite(LED_GELB2, HIGH);
digitalWrite(LED_ROT1, HIGH);
digitalWrite(LED_ROT2, HIGH);
}
if (digitalRead(15) == HIGH) {
nSamp = nSamp1;
} else {
nSamp = nSamp2;
}
}
//
// Calculate average sensor reading, convert to voltage
//
int convReadings(unsigned long sum, int number, float scale) {
sum = sum + (number >> 1); // add a correction of 0.5 of the reading - see notes
float mV = sum * scale; // mV = sum * (Vref * 1000 / 1024 )
mV = mV / number; //divide by number of readings last to keep precision high
return ((int)mV); //return the result as an integer as decimal point values arent valid
// (int) is a "cast" to change a float variable to an integer. Values after the decimal point are "cut off" so float 1.93 becomes int 1
}