NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » NerdKits Eletro Magnetic Field Detector

August 15, 2009
by pedroh96
pedroh96's Avatar

Hey Guys!

I did a simple Eletro Magnetic Field Detector with my NerdKits, just using ONE wire! It's working great, take a look:

NerdKtis EMF Detector

If you want the source code, here it is.

I hope you like it!

Bye

August 15, 2009
by mcai8sh4
mcai8sh4's Avatar

pH : Looks good, I'll give this a try on my test board tomorrow.

August 15, 2009
by pedroh96
pedroh96's Avatar

I hope you like it, mcai8sh4! Please test it out and post the result here.

Bye!

August 16, 2009
by mcai8sh4
mcai8sh4's Avatar

pH : pastie.org isn't responding, could you post your code somewhere else? Maybe nerdkits.pastebin.com

Thanks

August 16, 2009
by pedroh96
pedroh96's Avatar

Ofcourse! I'm pastieing here so, :)

// emfdetector.c
// by pH (iBlogeek.com - 2009)

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <avr/pgmspace.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:
//
// PC0 -- Wire

void adc_init() {
    ADMUX = 0;
    ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
    ADCSRA |= (1<<ADSC);
}

uint16_t adc_read() {
    while(ADCSRA & (1<<ADSC)) {
    }
    uint16_t result = ADCL;
    uint16_t temp = ADCH;
    result = result + (temp<<8);

    ADCSRA |= (1<<ADSC);
    return result;
}

double sampleToFahrenheit(uint16_t sample) {
    return sample;
}

void set_lcd_levelbar(uint16_t emf)
{
    // calculate how many bars will be displayed on the LCD
    int opr1 = emf - 160;
    int opr2 = ((opr1 * 20) / 160);
    int bars = opr2;

    if (bars > 20)
    {
        bars = 20;
    }

    lcd_line_three();
    int j;
    for(j = 0; j < bars; j++){
         lcd_write_data(0xff); //write black squares
      }
      for(; j < 20; j++){
         lcd_write_data(' '); //wire spaces on the rest of the characters
      }
}

int main() {

    DDRC |= (1<<PC1);
    DDRC |= (1<<PC2);
    DDRC |= (1<<PC3);
    DDRC |= (1<<PC4);
    DDRC |= (1<<PC5);

    // start up the LCD
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
    lcd_home();

    // start up the Analog to Digital Converter
    adc_init();

    // holder variables for temperature data
    uint16_t last_sample = 0;
    double this_temp;
    double temp_avg;
    uint16_t temp_cent;
    uint8_t i;

  while(1) {
    // take 100 samples and average them!
    temp_avg = 0.0;
    for(i=0; i<100; i++) {
      last_sample = adc_read();
      this_temp = sampleToFahrenheit(last_sample);

      // add this contribution to the average
      temp_avg = temp_avg + this_temp/100.0;

       temp_cent = (temp_avg - 32) / 1.8;
    }

    // write message to LCD

    lcd_home();
    lcd_write_string(PSTR("*******************"));
    lcd_line_two();
    lcd_write_string(PSTR("    EMF DETECTOR   "));
    set_lcd_levelbar(temp_cent);
    lcd_line_four();
    lcd_write_string(PSTR("*******************"));

  }

  return 0;
}

Tell me if it works.

August 16, 2009
by mcai8sh4
mcai8sh4's Avatar

Thanks, I'll work on this tonight/tomorrow - I'll let you know the results :)

(I only have the 2 row LCD, so I may convert this to use LEDs to show the signal strength)

August 17, 2009
by mcai8sh4
mcai8sh4's Avatar

Here's the scoop....

I built the tempsensor prject (like the initial tutorial) then remove the LM34 and put a piece of wire (but to sound more technical... 'a probe') into PC0 then looked at what readings I was getting. Answer - nothing or any real use!!

Then, looking on the internet I saw I should be placing a resistor on PC0 (as well as the probe) going to GND - I did this and results where still not good, but better.

So I threw over half a dozen resistors at it and the results where quite good (after a bit of playing around with the code still not finished - I'll post when happier).

So I thought I'd make it a little more portable, and get rid of the LCD and use PWM with an LED. The higher the EMF reading, the brighter the LED (there's a vid on youtube that shows the same). Problem I'm getting is the LED seems to create interference thus ruining the readings. Can this be overcome easily?

I'll keep playing (a nice little one night project this... that may turn into several nights) and let you know how I get on

August 17, 2009
by Nerdful_com
Nerdful_com's Avatar

I tested with no resistor and made a new code that beeps like a gieger counter (using included piezoelectric buzzer), the closer you are the slower it beeps and lower the tone, further away and it goes faster and higher pitch.

My hack is using the tempsensor.c combined with the Happy Birthday song player tutorial. Put a long wire in PC0 and put piezo to PB1. You might actually ahve to touch the wire to get any readings going.

Here's my tested code:

#define F_CPU 14745600
#include <avr/io.h>
#include <util/delay.h>

void play_tone(uint16_t delay, uint8_t duration) {
uint16_t tmp = 100 * duration;
uint16_t delaysm = delay / 50;
uint16_t cycles = tmp / delaysm;

while(cycles > 0) {
PORTB |= (1<<PB1);
_delay_us(delay);
PORTB &= ~(1<<PB1);
_delay_us(delay);
cycles--;
}
}

void adc_init() {
ADMUX = 0;
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRA |= (1<<ADSC);
}

uint16_t adc_read() {
while(ADCSRA & (1<<ADSC)) {
}
uint16_t result = ADCL;
uint16_t temp = ADCH;
result = result + (temp<<8);
ADCSRA |= (1<<ADSC);

return result;
}

double sampleToFahrenheit(uint16_t sample) {
return sample * (5000.0 / 1024.0 / 10.0);    
}

int main() {
adc_init();

uint16_t last_sample = 0;
double this_temp;
double temp_avg;
uint8_t i;

// Hacked by www.nerdful.com

OSCCAL = 176;
DDRB |= (1<<PB1);
while(1) {
play_tone(temp_avg, 1);
temp_avg = 0.0;
for(i=0; i<100; i++) {
last_sample = adc_read();
this_temp = sampleToFahrenheit(last_sample);
temp_avg = temp_avg + this_temp/100.0;
}
_delay_ms(temp_avg);
}

return 0;
}
August 17, 2009
by Nerdful_com
Nerdful_com's Avatar

Opps wrong version, that's code for AVR Studio that doesn't use libnerdkits, here's code for our NerdKit:

#define F_CPU 14745600
#include <avr/io.h>
#include "../libnerdkits/delay.h"
/*
Hacked by www.nerdful.com
*/
void play_tone(uint16_t delay, uint8_t duration) {
uint16_t tmp = 100 * duration;
uint16_t delaysm = delay / 50;
uint16_t cycles = tmp / delaysm;

while(cycles > 0) {
PORTB |= (1<<PB1);
delay_us(delay);
PORTB &= ~(1<<PB1);
delay_us(delay);
cycles--;
}
}

void adc_init() {
ADMUX = 0;
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRA |= (1<<ADSC);
}

uint16_t adc_read() {
while(ADCSRA & (1<<ADSC)) {
}
uint16_t result = ADCL;
uint16_t temp = ADCH;
result = result + (temp<<8);
ADCSRA |= (1<<ADSC);

return result;
}

double sampleToFahrenheit(uint16_t sample) {
return sample * (5000.0 / 1024.0 / 10.0);    
}

int main() {
adc_init();

uint16_t last_sample = 0;
double this_temp;
double temp_avg;
uint8_t i;

OSCCAL = 176;
DDRB |= (1<<PB1);
while(1) {
play_tone(temp_avg, 1);
temp_avg = 0.0;
for(i=0; i<100; i++) {
last_sample = adc_read();
this_temp = sampleToFahrenheit(last_sample);
temp_avg = temp_avg + this_temp/100.0;
}
delay_ms(temp_avg);
}

return 0;
}
August 17, 2009
by Nerdful_com
Nerdful_com's Avatar

BTW, I did not have the temperature sensor on the breadboard with my test. My test works like a theremin when you wave your hands near/far to the wire.

Post a Reply

Please log in to post a reply.

Did you know that you can adjust most wire strippers to make it easier to strip insulation faster? Learn more...