August 15, 2009
by pedroh96
|
Hey Guys!
I did a simple Eletro Magnetic Field Detector with my NerdKits, just using ONE wire! It's working great, take a look:
If you want the source code, here it is.
I hope you like it!
Bye |
August 15, 2009
by mcai8sh4
|
pH : Looks good, I'll give this a try on my test board tomorrow. |
August 15, 2009
by pedroh96
|
I hope you like it, mcai8sh4! Please test it out and post the result here.
Bye! |
August 16, 2009
by mcai8sh4
|
pH : pastie.org isn't responding, could you post your code somewhere else? Maybe nerdkits.pastebin.com
Thanks |
August 16, 2009
by pedroh96
|
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
|
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
|
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
|
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
|
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
|
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. |