EMF meter using Arduino MEGA2650

So I am completely new to Arduino, and figured I would make this project my first, as I will use it a lot. I know I could have bought one cheaper than all I bought for the project, but I love to tinker, and do some coding, plus there is soooo much I can do with Arduino.

My question is this, I know it is as simple as copying the code for the project, pasting it in software, and uploading it, (but what is the fun in that, I will edit it some). I want to know if anyone else has built one and can give me advice on antenna length and sensitivity?

This is the original site I found the meter on, Hyundai Aftermarket
and here is the code;

/*
   Copyright 2010 Adam N. Outler     Licensed under the Apache License, Version 2.0 (the "License");    you may not use this file except in compliance with the License.    You may obtain a copy of the License at         http://www.apache.org/licenses/LICENSE-2.0     Unless required by applicable law or agreed to in writing, software    distributed under the License is distributed on an "AS IS" BASIS,    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.    See the License for the specific language governing permissions and    limitations under the License. */

//A note on HZ, if you notice meter oscillations on a known steady 
//  signal increase or decrease hertz by 1.  The oscillations are
//  caused when the signals are in near-perfect resonance. 
float FrequencyToMonitor=59; //hertz


//setup pins
#define ANTENNA 31 //antenna pin
//16 LEDs on 16 different pins
int LEDPin[]={ 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52 } ;
int LEDCount=16;    //number of LEDs

//setup initial global values
int LEDCounter=0;               //initial value of LEDs to display
int HalfPeriodMicroseconds=0;// initial value of halfwavelength

/*
   SETUP defines pins and performs POT(Power On Test) on LEDs
*/
void setup()  { 
   double HalfPeriod=((1/FrequencyToMonitor)*.5);   //Half-period in seconds from frequency
   HalfPeriodMicroseconds=int(1000000*HalfPeriod);  //Convert period seconds to microseconds integer

   pinMode(ANTENNA, INPUT);                     //set antenna pin
   for (int Pin=0; Pin < LEDCount; Pin++)  { //initialize each LED 
    pinMode(LEDPin[Pin], OUTPUT);          
    digitalWrite(LEDPin[Pin], HIGH);          //Turn the LED on
    delay(50);
    digitalWrite(LEDPin[Pin], LOW);          //Turn the LED back off
   }
   swingLEDs();         //perform LED check to verify LED functionality
} 


/*
   LOOP checks for value of antenna to go high and then low
   if change is seen, then 2 LEDs are lit, otherwise total number
   of LEDS are decreased.  This allows for a magentic effect when
   near the field.
*/
void loop(){
   int ANTENNAValue=0;    //sets and resets ANTENNAValue
   int OldANTENNAValue=0; // as well as OldANTENNAValue


   for ( int Pass=0; Pass < 4; Pass++ )  {//take 4 readings
    ANTENNAValue=digitalRead(ANTENNA);    //   from the antenna
    if ( ( ANTENNAValue == HIGH ) && ( OldANTENNAValue == LOW ) ) {
        incrementLED(); //If a change is detected increase twice
        incrementLED(); //   4 passes means 3 changes total
    } else if ( ( ANTENNAValue ==  LOW ) && ( OldANTENNAValue == HIGH ) ) {
        incrementLED(); //   This makes the meter rise by
        incrementLED(); //   a total factor of  2 and
    } else {
        decrementLED(); //   if there is no change it falls by 1
    }
        OldANTENNAValue=ANTENNAValue; //Log old value for next pass
        delayMicroseconds(HalfPeriodMicroseconds);  // half-wave pause before next reading
   }
   delayMicroseconds(HalfPeriodMicroseconds); //visual delay between reading passes
   delayMicroseconds(HalfPeriodMicroseconds); //twice to avoid extremely long numbers   
}


/*
FUNCTION swingLEDs tests the LEDs by lighting
them up sequentially.  Each LED is brought high
then low twice. 
*/
void swingLEDs(){
        for (int Pin=0; Pin < LEDCount; Pin++)  {
        digitalWrite(LEDPin[Pin], HIGH);  // instantanious full brightness
   }
   for (int Pin=0; Pin < LEDCount; Pin++)  {
        digitalWrite(LEDPin[Pin], LOW);   // clear LEDs from left to right
        delay(20);
   }
   for (int Pin=LEDCount; Pin > -1; Pin--)  {
        digitalWrite(LEDPin[Pin], HIGH);  // light LEDs from right to left
        delay(20);
   }
   for (int Pin=LEDCount; Pin > -1; Pin--)  {
        digitalWrite(LEDPin[Pin], LOW);   // clear LEDs from right to left
        delay(20);
   }
}

/* 
FUNCTION incrementLED increases the number
of LEDs lit by 1.  
*/
void incrementLED(){
    if ( LEDCounter <  LEDCount  - 1  ){ LEDCounter++;} //if not max increase
    digitalWrite(LEDPin[LEDCounter], HIGH); //light new LED
}

/*
FUNCTION decrementLED decreases the number
of LEDs lit by 1.
*/
void decrementLED(){
   digitalWrite(LEDPin[LEDCounter], LOW); //turn off current LED
   if ( LEDCounter >= 0 ){ LEDCounter-- ;} // if not zero, decrease}

Thank you for your help and advice!

So I have built it, and am having issues. it runs through power on test fine, then when I go to use it only some of the LEDs light up and do not reset back to zero, mainly every other LED lights up to one below pegged and just stays there untill I turn it off. Anyone got any ideas?

EDIT: I tried switching led pins to all odd and antenna to pin 22 and get the same results, is there a problem with the code I am missing or is there a problem with my Arduino?

Are you using the software and hardware exactly the same as shown?

Everything is exactly the same. He is using a mega, just not sure if it is a 2650 ver.xxx or an earlier one but it looks just like mine. I don't know what could be wrong.

Am I missing something here?
EMF = electromotive force, or, more simply, voltage.

Where does frequency come in to it?

Electric Field Meter

That would be EFM, no?

Electro Magnetic Field or Electro Magnetic Force, normally 60Hz on AC supply with transformer.

jonrobertd:
Everything is exactly the same. He is using a mega, just not sure if it is a 2650 ver.xxx or an earlier one but it looks just like mine. I don't know what could be wrong.

Can post a picture on how you connect up?

here is a short video of my meter:

And his meter:

and a pic of wiring and connections:

EDIT: I changed LED pin assignments to pins 6-12 with the antenna on pin 5 with the same results, so it has to be a problem with the code, right? I hope my board is not messed up as I just bought it.

I have been doing other projects with my board and they run just fine, so I guess it is the code. I am at a loss as far as fixing it so any help is welcome and appreciated.

Well it turns out it was the code. Still don't understand how or where, but I rewrote another code and it works. Thanks.

This is the code I tweaked to get my EMF meter working:

// EMF Detector for LED Bargraph v1.0
// 5.12.2009
// original code/project by Aaron ALAI - aaronalai1@gmail.com
// modified for use w/ LED bargraph by Collin Cunningham - collin@makezine.com
// modified to use on MEGA with sensitivity and feild detection changes by Jon D.

#define NUMREADINGS 15 // raise this number to increase data smoothing

int senseLimit = 5; // raise this number to decrease sensitivity (up to 1023 max)
int probePin = 5; // analog 5
int val = 0; // reading from probePin

int LED1 = 52; // connections
int LED2 = 50; // to
int LED3 = 48; // LED
int LED4 = 46; // bargraph
int LED5 = 44; // anodes
int LED6 = 42; // with
int LED7 = 40; // resistors
int LED8 = 38; // in
int LED9 = 36; // series
int LED10 = 34; //
int LED11 = 32; //
int LED12 = 30; //
int LED13 = 28; //
int LED14 = 26; //
int LED15 = 24; //
int LED16 = 22; //

// variables for smoothing

int readings[NUMREADINGS];                // the readings from the analog input
int index = 0;                            // the index of the current reading
int total = 0;                            // the running total
int average = 0;                          // final average of the probe reading


void setup() {

pinMode(22, OUTPUT); // specify LED bargraph outputs
pinMode(24, OUTPUT);
pinMode(26, OUTPUT);
pinMode(28, OUTPUT);
pinMode(30, OUTPUT);
pinMode(32, OUTPUT);
pinMode(34, OUTPUT);
pinMode(36, OUTPUT);
pinMode(38, OUTPUT);
pinMode(40, OUTPUT);
pinMode(42, OUTPUT);
pinMode(44, OUTPUT);
pinMode(46, OUTPUT);
pinMode(48, OUTPUT);
pinMode(50, OUTPUT);
pinMode(52, OUTPUT); 

  Serial.begin(9600);  // initiate serial connection for debugging/etc

  for (int i = 0; i < NUMREADINGS; i++)
    readings[i] = 0;                      // initialize all the readings to 0
}

void loop() {

  val = analogRead(probePin);  // take a reading from the probe

  if(val >= 1){                // if the reading isn't zero, proceed

    val = constrain(val, 1, senseLimit);  // turn any reading higher than the senseLimit value into the senseLimit value
    val = map(val, 1, senseLimit, 1, 1023);  // remap the constrained value within a 1 to 1023 range

    total -= readings[index];               // subtract the last reading
    readings[index] = val; // read from the sensor
    total += readings[index];               // add the reading to the total
    index = (index + 1);                    // advance to the next index

    if (index >= NUMREADINGS)               // if we're at the end of the array...
      index = 0;                            // ...wrap around to the beginning

    average = total / NUMREADINGS;          // calculate the average


if (average > 50){ // if the average is over 50 …
digitalWrite(LED1, HIGH); // light the first LED
}
else{ // and if it’s not …
digitalWrite(LED1, LOW); // turn that LED off
}

if (average > 100){ // and so on …
digitalWrite(LED2, HIGH);
}
else{
digitalWrite(LED2, LOW);
}

if (average > 150){
digitalWrite(LED3, HIGH);
}
else{
digitalWrite(LED3, LOW);
}

if (average > 200){
digitalWrite(LED4, HIGH);
}
else{
digitalWrite(LED4, LOW);
}

if (average > 250){
digitalWrite(LED5, HIGH);
}
else{
digitalWrite(LED5, LOW);
}

if (average > 300){
digitalWrite(LED6, HIGH);
}
else{
digitalWrite(LED6, LOW);
}

if (average > 350){
digitalWrite(LED7, HIGH);
}
else{
digitalWrite(LED7, LOW);
}

if (average > 400){
digitalWrite(LED8, HIGH);
}
else{
digitalWrite(LED8, LOW);
}

if (average > 450){
digitalWrite(LED9, HIGH);
}
else{
digitalWrite(LED9, LOW);
}

if (average > 500){
digitalWrite(LED10, HIGH);
}
else{
digitalWrite(LED10, LOW);
}

if (average > 550){
digitalWrite(LED11, HIGH);
}
else{
digitalWrite(LED11, LOW);
}

if (average > 600){
digitalWrite(LED12, HIGH);
}
else{
digitalWrite(LED12, LOW);
}

if (average > 650){
digitalWrite(LED13, HIGH);
}
else{
digitalWrite(LED13, LOW);
}

if (average > 700){
digitalWrite(LED14, HIGH);
}
else{
digitalWrite(LED14, LOW);
}

if (average > 800){
digitalWrite(LED15, HIGH);
}
else{
digitalWrite(LED15, LOW);
}

if (average > 900){
digitalWrite(LED16, HIGH);
}
else{
digitalWrite(LED16, LOW);
}


    Serial.println(val); // use output to aid in calibrating
  }
}

Now, could someone please help me to get this to play an audible tone on pin 11to an 8 ohm speaker, something simple like a beep, beep every second that the highest pin (LED 16, pin 52) is on. I have the setup from the example tone code with the pitches.h file and am pretty sure I would have to add it to it, but have no Idea how to implement it here. Thank you

So I have the emf meter working perfectly until I add in the tone. Once it hits the level the tone starts, it hangs, gradually lighting an LED every second beep for a few LEDs then decreases one until it hits LED 8 (the tone LED) and hangs. I modified the tone example to suit my needs in this application, but have no idea why it hangs there once it hits level 8. Any help is greatly appreciated.

// EMF Detector for LED Bargraph v1.0
// 5.12.2009
// original code/project by Aaron ALAI - aaronalai1@gmail.com
// modified for use w/ LED bargraph by Collin Cunningham - collin@makezine.com
// modified to use on MEGA with sensitivity and feild detection changes by Jon D.

#include "pitches.h"
#define NUMREADINGS 20// raise this number to increase data smoothing

int senseLimit = 3; // raise this number to decrease sensitivity (up to 1023 max)
int probePin = 5; // analog 5
int val = 0; // reading from probePin

int LED1 = 52; // connections
int LED2 = 50; // to
int LED3 = 48; // LED
int LED4 = 46; // bargraph
int LED5 = 44; // anodes
int LED6 = 42; // with
int LED7 = 40; // resistors
int LED8 = 38; // in
int LED9 = 36; // series
int LED10 = 34; //
int LED11 = 32; //
int LED12 = 30; //
int LED13 = 28; //
int LED14 = 26; //
int LED15 = 24; //
int LED16 = 22; //

// variables for smoothing

int readings[NUMREADINGS];                // the readings from the analog input
int index = 0;                            // the index of the current reading
int total = 0;                            // the running total
int average = 0;                          // final average of the probe reading


void setup() {

pinMode(22, OUTPUT); // specify LED bargraph outputs
pinMode(24, OUTPUT);
pinMode(26, OUTPUT);
pinMode(28, OUTPUT);
pinMode(30, OUTPUT);
pinMode(32, OUTPUT);
pinMode(34, OUTPUT);
pinMode(36, OUTPUT);
pinMode(38, OUTPUT);
pinMode(40, OUTPUT);
pinMode(42, OUTPUT);
pinMode(44, OUTPUT);
pinMode(46, OUTPUT);
pinMode(48, OUTPUT);
pinMode(50, OUTPUT);
pinMode(52, OUTPUT); 

  Serial.begin(9600);  // initiate serial connection for debugging/etc

  for (int i = 0; i < NUMREADINGS; i++)
    readings[i] = 0;                      // initialize all the readings to 0
}

void loop() {

  val = analogRead(probePin);  // take a reading from the probe

  if(val >= 1){                // if the reading isn't zero, proceed

    val = constrain(val, 1, senseLimit);  // turn any reading higher than the senseLimit value into the senseLimit value
    val = map(val, 1, senseLimit, 1, 1023);  // remap the constrained value within a 1 to 1023 range

    total -= readings[index];               // subtract the last reading
    readings[index] = val; // read from the sensor
    total += readings[index];               // add the reading to the total
    index = (index + 1);                    // advance to the next index

    if (index >= NUMREADINGS)               // if we're at the end of the array...
      index = 0;                            // ...wrap around to the beginning

    average = total / NUMREADINGS;          // calculate the average


if (average > 50){ // if the average is over 50 …
digitalWrite(LED1, HIGH); // light the first LED
}
else{ // and if it’s not …
digitalWrite(LED1, LOW); // turn that LED off
}

if (average > 100){ // and so on …
digitalWrite(LED2, HIGH);
}
else{
digitalWrite(LED2, LOW);
}

if (average > 150){
digitalWrite(LED3, HIGH);
}
else{
digitalWrite(LED3, LOW);
}

if (average > 200){
digitalWrite(LED4, HIGH);
}
else{
digitalWrite(LED4, LOW);
}

if (average > 250){
digitalWrite(LED5, HIGH);
}
else{
digitalWrite(LED5, LOW);
}

if (average > 300){
digitalWrite(LED6, HIGH);
}
else{
digitalWrite(LED6, LOW);
}

if (average > 350){
digitalWrite(LED7, HIGH);
}
else{
digitalWrite(LED7, LOW);
}

if (average > 400){
digitalWrite(LED8, HIGH);
int melody[] = {
  NOTE_C4 };

int noteDurations[] = {
  4 };
  
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    int noteDuration = 1000/noteDurations[thisNote];
    tone(8, melody[thisNote],noteDuration);


    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(8);
  }
}
else{
digitalWrite(LED8, LOW);
}

if (average > 450){
digitalWrite(LED9, HIGH);
}
else{
digitalWrite(LED9, LOW);
}

if (average > 500){
digitalWrite(LED10, HIGH);
}
else{
digitalWrite(LED10, LOW);
}

if (average > 550){
digitalWrite(LED11, HIGH);
}
else{
digitalWrite(LED11, LOW);
}

if (average > 600){
digitalWrite(LED12, HIGH);
}
else{
digitalWrite(LED12, LOW);
}

if (average > 650){
digitalWrite(LED13, HIGH);
}
else{
digitalWrite(LED13, LOW);
}

if (average > 700){
digitalWrite(LED14, HIGH);
}
else{
digitalWrite(LED14, LOW);
}

if (average > 800){
digitalWrite(LED15, HIGH);
}
else{
digitalWrite(LED15, LOW);
}

if (average > 900){
digitalWrite(LED16, HIGH);
}
else{
digitalWrite(LED16, LOW);
}


    Serial.println(val); // use output to aid in calibrating
  }
}

for (int thisNote = 0; thisNote < 8; thisNote++) {

Should this perhaps be....

for (int thisNote = 0; thisNote <= 8; thisNote++) {

....instead?

Thanks for the help, but that's a no go. Still doing same thing. It's weird because it works ok as long as the reading is 7 or below, but as soon as it hits 8 it hangs up like there is something not telling it to turn back off if the reading is lower, or keep lighting up if it is higher.

I would re-examine your tone code. Maybe try getting it working by itself (without LEDs, etc) then insert it back into full program.

It looks like you "borrowed" that code from the Tone Tutorial. The tutorial uses arrays to play multiple tones. You kept it as an array, but are only playing one tone. An array of one? I'd try rewriting it/redefining it without using arrays.

[quote author=jonrobertd link=topic=170092.msg1296426#msg1296426 date=1372444099]
So I have the emf meter working perfectly until I add in the tone. Once it hits the level the tone starts, it hangs, gradually lighting an LED every second beep for a few LEDs then decreases one until it hits LED 8 (the tone LED) and hangs. I modified the tone example to suit my needs in this application, but have no idea why it hangs there once it hits level 8. 


 
int melody[] = {
  NOTE_C4 };

int noteDurations[] = {
  4 };
  
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    int noteDuration = 1000/noteDurations[thisNote];
    tone(8, melody[thisNote],noteDuration);


    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(8);
  
}

[/quote]

Lose the above code. That's for playing a melody. You're setting an array of one note. Then, pausing between notes....but you're only playing one note. So....probably why it's hanging.

Replace it with something simple, like -

tone(speakerPin, 1000, 500);
NoTone(speakerPin);

Plays a tone on speakerPin of 1000 Hz for 500 ms (1/2 sec).
Then, turns off tone so won't interfere with nothing else.

And in beginning of code, maybe add an

Const int speakerPin = 8;

I'm guessing from your code that's where you have speaker hooked up.

With all those If/else statements though....it might be difficult to smoothly add in beeps & such.

Should be able to map the input of sensor to a set of values equal to the number of LEDs, assign LEDs to an array, then just call the mapped values to turn the correlating LEDs HIGH.

Yes I used the tone code, hoping it would work but I see now why it doesn't. Thank you for all of your help and I will try what 1ChigagoDave suggested and will try tinkering some more.