Sound Direction Finder Using Pic18f452 ... help

Thread Starter

tallo

Joined Mar 4, 2011
12
hi everyone

i did a project which is find the direction of sound source using 4 sensors in a square board(one sensor in each corner) and the output of these sensors goes to microcontroller Pic18f452 i need to know the first 2 sensors detect the sound
and then calculate the time delay between these two sensors but i don't know which type of timer should i use in this type of microcontroller ...

thanks
 

JohnInTX

Joined Jun 26, 2012
3,805
Use the capture registers.

Configure TMR1 or TMR3 as a 16 bit free running timer. Configure both CCPs to use the selected timer.
Configure CCP1 for one sensor and CCP2 for the other such that when they receive a signal each captures the 16 bit timer value.
When both captures are done (both sensors heard the sound) compute the difference between the captured values and relate that to the time between signals.
 

Thread Starter

tallo

Joined Mar 4, 2011
12
Use the capture registers.

Configure TMR1 or TMR3 as a 16 bit free running timer. Configure both CCPs to use the selected timer.
Configure CCP1 for one sensor and CCP2 for the other such that when they receive a signal each captures the 16 bit timer value.
When both captures are done (both sensors heard the sound) compute the difference between the captured values and relate that to the time between signals.
Thank you so much .

what do you think if i use TMR0.... if the first sensor detect the sound then
TMR0 starts and when the second sensor detect TMR0 stop .

does this process accurate ? and what do you think in the following code:

void main(){
ADCON1 |= 0x0F; // Configure AN pins as digital
TRISB = 0x0F;
PORTB = 0xF0;
T0CON = 0x08;
TMR0L = 0x00;
TMR0H = 0x00;
INTCON.TMR0IF = 0x0; // TMR overflow interrupt flag disable
INTCON.TMR0IE = 0x0; // TMR overflow interrupt disable

Lcd8_Init(); // Initialize Lcd8
Lcd8_Cmd(_LCD_CLEAR); // Clear display
Lcd8_Cmd(_LCD_CURSOR_OFF); // Cursor off

Lcd8_Out(1,1,txt1); // Welcome Messege
Lcd8_Out(2,1,txt2);

Delay_ms(1000);
Lcd8_Cmd(_LCD_CLEAR); // Clear display

while(y < 2) { // Endless loop
if((PORTB.F0 == 1) && (x[0] == 0) && (y < 2)) {
PORTB.F4 = 0; //cheking sound from mic 45 Deg
y++;
x[0] = y;
}
if((PORTB.F1 == 1) && (x[1] == 0) && (y < 2)) {
PORTB.F5 = 0; //cheking sound from mic 135 Deg
y++;
x[1] = y;
}
if((PORTB.F2 == 1) && (x[2] == 0) && (y < 2)) {
PORTB.F6 = 0; //checking sound from mic 225 Deg
y++;
x[2] = y;
}
if((PORTB.F3 == 1) && (x[3] == 0) && (y < 2)) {
PORTB.F7 = 0; //checking sound from mic 315 Deg
y++;
x[3] = y;
}
if((y == 1) && (z1 == 0)) { //start the timer
T0CON.TMR0ON = 0x1;
z1 = 4;
}
if(y == 2) { //latch the timer value
T0CON.TMR0ON = 0x0; //storp the timer
}
}
tl = TMR0L;
th = TMR0H;
timerH = th<<8;
timer = timerH | tl;
 

ErnieM

Joined Apr 24, 2011
8,005
and what do you think in the following code...
I think you committed the fatal mistake of jumping right to the code without making any design at all.

How far apart are the sensors?
What inputs do you expect?
What level of accuracy to you require?
Where are the equations that determine direction?
 

JohnInTX

Joined Jun 26, 2012
3,805
Here are a few thoughts..


In standard conditions sound travels at a rate of about 73.25us/inch so you have to take that into account. Your code does a lot of polling/qualifying of sensors and maintaining its state in flagging so timing might be an issue.

I understand what your code is supposed to do but don't like the design. Everything is in one big loop with lots of flags, array values etc. to figure out the state of the system. It would be better to break it down into discrete functions i.e.
f1)Wait for sound on any sensor
f2)Start timer
f3)Wait for sound on any OTHER sensor -OR- timeout (no second sound received)
f4)Stop timer and compute result

Your code essentially does that but the all-in-one loop is going to be expensive in CPU cycles and accuracy will suffer. By breaking it down into multiple functions you only test what you have to. You can also test more than one bit on the port at one time, for example (pseudo-code):
Rich (BB code):
init(); // stop timer, clear it etc...

//--------- WAIT FOR FIRST SOUND  --------------
do{
 Sound1=PORTB & 0x0f; // read all 4 sensors, strip off unused bits
}while (Sound1==0);   // until you get something, Sound 1 is image of port when it started and says which mic heard the sound.

//----------- START TIMER  --------------------
TMR0ON = 1; // start timer
TMR0IF = 0; // clear overflow flag
mask = ~Sound1 & 0x0f // eliminate that mic from next test

//------------- WAIT FOR 2ed SOUND  ------------------
do{
 Sound2 = PORTB & mask; // read remaining sensors
}while ((Sound2 == 0) && !TMR0IF); // until 2ed sound heard OR timeout

//-------------- PROCESS RESULT  --------------------
if (timeout) 
 do_error(); // report error, try again
else{
 .. examine Sound1 and Sound2 to see which two got hit by the sound in 
 sequence.  Calculate direction from time.
}
//--------------- WAIT FOR SOUND TO DIE DOWN  ------------
delay(xxx);// sensors are likely still picking up sound (don't forget echoes).  Wait until it dies down
Note how the state of the process is maintained naturally by location in the code, not a bunch of flags, array values which are expensive to maintain etc. You also can add things like a timeout where its called for etc.
 
Top