Tecnicamente's Weblog

Just another WordPress.com weblog

Archivi delle etichette: emf rilevator

Rilevatore EMF con Arduino

Avevo scritto l’articolo in inglese sperando di raggiungere un gruppo più ampio di persone, ma così non è stato, quindi lo ripropongo in Italiano.

In alcuni dei miei articoli ho descritto il mio piccolo progetto di un rilevatore EMF realizzato usando arduino, potete leggere qui, qui e qui.

Grazie a questo progetto ho avuto l’opportunità di analizzare alcune interessanti cose come:

  • La teoria delle antenne;
  • I filtri digitali;
  • l’uso della funzione millis() per emulare il multitasking;
  • La trasformata di Fourier.

I temi sono vasti ed interessanti, per ciò posso dire dire che il mio progetto non è veramente completo, ma mi ha dato molte tematiche da studiare e come risultato hanno aumentato la mia conoscenza.

Tornando al progetto posso sintetizzare la mia conclusione con la seguente frase: “TUTTI I PROGETTI DI RILEVATORI EMF CHE USANO SOLO ARDUNO CON UN CAVO ED UNA RESISTENZA COME ANTENNA SONO DELLE PRESE IN GIRO“.

Come prima cosa dovete sapere che non potete leggere o misurare direttamente il CAMPO MAGNETICO con uno strumento siffatto, parlo di arduini e un filo di rame, potete osservare solo le variazioni del CAMPO ELETTRICO, quindi quello che potete fare direttamente con il solo Arduino è osservare le variazione del campo elettrico nell’ambiente circostante.

In Italia la frequenza della rete elettrica è di 50 Hz, per tale motivo la mia aspettativa è quella di vedere le variazioni del campo elettrico in linea con tale frequenza, ma osservate il seguente grafico:

5ms

Nei grafici potete vedere il risultato delle misure con due diverse antenne, la conclusione è che l’antenna non è molto importante in termini della frequenza della variazione del segnale campo elettrico rilevato, altra cosa è che la frequeza di variazione è molto lontana dai circa 50 Hz attesi, molto strano. L’acquisisione è stata fatta con un campionamento di 200 Hz con lo scopo di evitare l’aliasing con il segnale da 50 Hz atteso.

Nei grafici successivi potete vedere i dati acquisiti vicino ad una lampada elettrica, la variazione del campo elettrico è misurata ma avviando l’analisi FFT non si vedono differeze su quelle che sono le frequenze del segnale, quindi la frequenza principale della variazione di campo elettrico è di circa 250 Hz come nell’esperienza precedente.

5ms-sorgente

La domanda è quale è la ragione della variazione del campo elettrico a 250 Hz? Caso interessante da investigare meglio.

Adesso vediamo cosa accade se passo da un campionamento da 200 Hz ad uno a 100 Hz.

Qui i risultati:

10ms

Ed adesso cosa accade se campiono a 50 Hz:

20ms

Ho usato diverse lunghezze di antenne e impedenze, ma l’unica cosa che sembra impattare in modo significativo sulla frequenza del campo elettromagnetico sembra essere la frequenza di campionamento.

Qui il codice usato, anche se un po’ grezzo:

#include <Arduino.h>
#define VERSIONE 4.01-27/10/2014
#define C 0.0048828125
#define T1 20
#define T2 60000

int flag = 0;

void waitForFlush(void){
/*******************************************
* scopo di questa funzione e non impegnare *
* la comunicazione seriale nei primi X *
* secondi. In tal modo il flush e sempre *
* facilmente realizzabile. *
*******************************************/
#define TIMETOWAIT 5000 /* ms */
unsigned long t0,t1;

t0 = millis();
t1 = millis();

while( t1-t0 < TIMETOWAIT){
   t1 = millis();
}
}
void setup(){
/*attivo la comunicazione seriale */
Serial.begin(57600);

/*do disponibilità a flush del controllore*/
waitForFlush();

/*Intezzazione del programma */
Serial.print("EMF DETECTOR V. ");
Serial.println(VERSIONE);
}
float valore, valore1;

void loop(void){
unsigned long t;

t = millis();
/* con t%10 campiono 100 volte al secondo, quindi a 100 Hz
con t%5 campiono 200 volte al secondo, quindi a 200 Hz
*/

if(t%T1 == 0){

valore = analogRead(A0)*C;
valore1 = analogRead(A5)*C;

/*
Serial.print(t);
Serial.print("\t");
*/

Serial.print(valore,5);
Serial.print("\t");
Serial.print(valore1,5);
Serial.println();
}
}

[AGGIORNAMENTO 9-Nov-2014]

Ho speso i giorni passati, per essere onesto le poche ore disponibili, investigando circa la sorgente del segnale e pensando a come applicare un filtro sull’acquisizione.

E’ stata una attività molto interessante ed ho aperto una nuova porta sui filtri digitali, imparando cose interessanti:

  1. I filtri passa-basso e passa-alto sono interessanti, ma richiedono molte risorse di calcolo, questo richiederebbe di programmare il mio arduino direttamente sull’ATMEL in C o ASSEMBLER, ma non sono sicuro dei risultati e sinceramente non ne ho voglia 😉 ;
  2. Ci sono altri approcci più semplici per applicare un filtro:
    1. Utilizzare la media mobile;
    2. Utilizzare la media a finestra mobile.

Ho provato ad implementare entrambi i filtri, scusate il codice poco curato, lo migliorerò in una seconda vita 😉

#include <Arduino.h>
#define VERSIONE "4.03-09/11/2014"

#define C 0.0048828125

#define T1 5
#define T2 60000

#define NCAMPIONI 10

//int flag = 0;

void waitForFlush(void){
/*******************************************
* scopo di questa funzione e non impegnare *
* la comunicazione seriale nei primi X *
* secondi. In tal modo il flush e sempre *
* facilmente realizzabile. *
*******************************************/
#define TIMETOWAIT 5000 /* ms */
unsigned long t0,t1;

t0 = millis();
t1 = millis();

while( t1-t0 < TIMETOWAIT){
   t1 = millis();
}
}

void setup(){

/*attivo la comunicazione seriale */
Serial.begin(57600);

/*do disponibilità a flush del controllore*/
waitForFlush();

/*Intestazione del programma */
Serial.print("EMF DETECTOR V. ");
Serial.println(VERSIONE);
}


float valore;
float campioni[NCAMPIONI];
float campioniSlideWindow[NCAMPIONI];

float somma=0;
float sommaSlideWindow=0;

float mediaMobile = 0;
float mediaSlideWindow = 0;

short int contatore = 0;
short int flag = 0;
short int i;

void loop(void){
unsigned long t;

t = millis();
/**********************************************************
 *con t%10 campiono 100 volte al secondo, quindi a 100 Hz *
 *con t%5 campiono 200 volte al secondo, quindi a 200 Hz  *
 *Applicano il fitro i campionamenti avvengono ogni 10*T  *
 *********************************************************/

if(t%T1 == 0){
  valore = analogRead(A0)*C;
  
  if (contatore < 10){
    campioni[contatore] = valore;
    //somma = somma + campione[contatore];
    contatore++;
  }


  
  if (contatore < NCAMPIONI && flag ==0){
    flag = 1;
    for (i=0; i<NCAMPIONI; i++){
      sommaSlideWindow = campioniSlideWindow[contatore]+sommaSlideWindow;
    }
    sommaSlideWindow = 0;
  }

  if (contatore < NCAMPIONI && flag !=0){
    campioniSlideWindow[contatore] = valore;
   
   for (i=0; i<NCAMPIONI; i++){     sommaSlideWindow = sommaSlideWindow + campioniSlideWindow[i];    }       mediaSlideWindow = sommaSlideWindow/NCAMPIONI;    sommaSlideWindow = 0;   }   if ( contatore >= NCAMPIONI){
      contatore =0;
      for (i=0; i<NCAMPIONI; i++){
         somma = somma + campioni[i];
      }
      mediaMobile = somma/NCAMPIONI;
      somma = 0;
  }
  

  Serial.print(t);
  Serial.print("\t");
  Serial.print(valore,5);
  Serial.print("\t");
  Serial.print(mediaMobile,5);
  Serial.print("\t");
  Serial.print(mediaSlideWindow,5);
  Serial.println();

}
}


Nei grafici seguenti i risultati dell’applicazione dei filtri.

Il filtro basato sulla media mobile sembra dare risultati migliori (seconda colonna).

20141106_5ms

dopo qualche minuto:

20141106_5mmms[AGGIORNAMENTO 14-Agosto-2015]

in merito alla tecnica di campionamento e conversione AD ho trovato due interessanti articoli della ATMEL

doc2559 e doc8003.

La teoria dell’oversampling è sicuramente cruciale per capire le misure fatte, cercando in rete ho trovato questo interessante articolo in italiano: http://www.mcmajan.com/mcmajanwpr/?p=2618

A presto con i risultati della sperimentazione.

Arduino and EMF detector

Usually I write my short note in italian, but I guess that sometime is better switch to english due to the fact that I can “improve” and I can reach more people in the web, so why do not start to write my post in english? (or better, I’m try to do that 😉 ).

OK let’s go, in some of my previous post I described my little project around an EMF detector using arduino, please read this, this and this.

Thanks to this project I had the opportunity to investigate some interesting things like:

  • Theory of antenna;
  • Digital filters;
  • The use of millis() in order to emulate a multitasking on my Arduino Uno;
  • Fourier transform.

Very interesting topics, so I can say that my project isn’t completed, but it gave me a lot of points where I can study and enlarge my knoledge.

Coming to the project I can write a simple sentence that can summarize the result: “ALL EMF DETECTOR PROJECTS THAT USE ARDUINO, WIRES AND RESISTORS ARE BULLSHIT”

First of all you cannot read or measure MAGNETIC FIELS, but only ELECTRIC FIELDS, so what you can see directly whit you arduino is the variation of the electric field in the enviroment.

Here in Italy the frequency of the electric lines is 50Hz, so I guess that the variation of the EF is reletad to this frequency, but please look at next picture:

5msYou can see the measurement with different antennas, the results is that the antenna is not so importat about the frequency, and that the frequencies are quite far from 50Hz, very strange. I’m aquiring the data at 200Hz in order to avoid the aliasing with a signal of 50Hz.

In the next picture you can see the aquisition of data near to electric light, the variation of the EF is measured but there is no changes on the FFT analysis, so the main frequency of the field is  about 250 Hz as before

5ms-sorgente

The question is what is the reason for a EF at 250Hz? Nice to investigate.

Now what appen if I change the sample rate from 200Hz to 100Hz.

Here the result:

10ms

And now what I find at 50Hz of sample rate:

20ms

Someone can suggest howto detect the field at 50Hz?

I used different leght for antennas and impedence, but the only thing that seems focus on the EF frequency is the sample rate.
Here the code, very raw 😉

#include <Arduino.h>
#define VERSIONE 4.01-27/10/2014
#define C 0.0048828125
#define T1 20
#define T2 60000

int flag = 0;

void waitForFlush(void){
/*******************************************
* scopo di questa funzione e non impegnare *
* la comunicazione seriale nei primi X *
* secondi. In tal modo il flush e sempre *
* facilmente realizzabile. *
*******************************************/
#define TIMETOWAIT 5000 /* ms */
unsigned long t0,t1;

t0 = millis();
t1 = millis();

while( t1-t0 < TIMETOWAIT){
   t1 = millis();
}
}
void setup(){
/*attivo la comunicazione seriale */
Serial.begin(57600);

/*do disponibilità a flush del controllore*/
waitForFlush();

/*Intezzazione del programma */
Serial.print("EMF DETECTOR V. ");
Serial.println(VERSIONE);
}
float valore, valore1;

void loop(void){
unsigned long t;

t = millis();
/* con t%10 campiono 100 volte al secondo, quindi a 100 Hz
con t%5 campiono 200 volte al secondo, quindi a 200 Hz
*/

if(t%T1 == 0){

valore = analogRead(A0)*C;
valore1 = analogRead(A5)*C;

/*
Serial.print(t);
Serial.print("\t");
*/

Serial.print(valore,5);
Serial.print("\t");
Serial.print(valore1,5);
Serial.println();
}
}

[UPDATE 9-Nov-2014]

I spent last days, to be honest the last free hours, investigating about the source of the signal and how to apply a filter.
So it was good, I opened a new door about digital filters and at the I discovered some important things:

  1. Low and High pass filters are interesting, but to much resource are necessary, due to this in mandatory leave the arduino IDE and use a pure C or Assembler approach to the controller, but I’m not sure about the results.
  2. There are others more simple approach to filter the input signal:
    1. moving average
    2. slide window average.

I tried to implement both, sorry for the dirty code, I will arrange it better in a second life 😉

 

#include <Arduino.h>
#define VERSIONE "4.03-09/11/2014"

#define C 0.0048828125

#define T1 5
#define T2 60000

#define NCAMPIONI 10

//int flag = 0;

void waitForFlush(void){
/*******************************************
* scopo di questa funzione e non impegnare *
* la comunicazione seriale nei primi X *
* secondi. In tal modo il flush e sempre *
* facilmente realizzabile. *
*******************************************/
#define TIMETOWAIT 5000 /* ms */
unsigned long t0,t1;

t0 = millis();
t1 = millis();

while( t1-t0 < TIMETOWAIT){
   t1 = millis();
}
}

void setup(){

/*attivo la comunicazione seriale */
Serial.begin(57600);

/*do disponibilità a flush del controllore*/
waitForFlush();

/*Intestazione del programma */
Serial.print("EMF DETECTOR V. ");
Serial.println(VERSIONE);
}


float valore;
float campioni[NCAMPIONI];
float campioniSlideWindow[NCAMPIONI];

float somma=0;
float sommaSlideWindow=0;

float mediaMobile = 0;
float mediaSlideWindow = 0;

short int contatore = 0;
short int flag = 0;
short int i;

void loop(void){
unsigned long t;

t = millis();
/**********************************************************
 *con t%10 campiono 100 volte al secondo, quindi a 100 Hz *
 *con t%5 campiono 200 volte al secondo, quindi a 200 Hz  *
 *Applicano il fitro i campionamenti avvengono ogni 10*T  *
 *********************************************************/

if(t%T1 == 0){
  valore = analogRead(A0)*C;
  
  if (contatore < 10){
    campioni[contatore] = valore;
    //somma = somma + campione[contatore];
    contatore++;
  }


  
  if (contatore < NCAMPIONI && flag ==0){
    flag = 1;
    for (i=0; i<NCAMPIONI; i++){
      sommaSlideWindow = campioniSlideWindow[contatore]+sommaSlideWindow;
    }
    sommaSlideWindow = 0;
  }

  if (contatore < NCAMPIONI && flag !=0){
    campioniSlideWindow[contatore] = valore;
   
   for (i=0; i<NCAMPIONI; i++){     sommaSlideWindow = sommaSlideWindow + campioniSlideWindow[i];    }       mediaSlideWindow = sommaSlideWindow/NCAMPIONI;    sommaSlideWindow = 0;   }   if ( contatore >= NCAMPIONI){
      contatore =0;
      for (i=0; i<NCAMPIONI; i++){
         somma = somma + campioni[i];
      }
      mediaMobile = somma/NCAMPIONI;
      somma = 0;
  }
  

  Serial.print(t);
  Serial.print("\t");
  Serial.print(valore,5);
  Serial.print("\t");
  Serial.print(mediaMobile,5);
  Serial.print("\t");
  Serial.print(mediaSlideWindow,5);
  Serial.println();

}
}


In the next picture you can see the graphical results of the filters.
The filter based on the simple moving average seems better (2nd col).

20141106_5ms

and after some minutes:

20141106_5mmms