# Sound Direction Finder Using Pic18f452 ... help

#### 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
4,601
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.

#### 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,196
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
4,601
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{
}while ((Sound2 == 0) && !TMR0IF); // until 2ed sound heard OR timeout

//-------------- PROCESS RESULT  --------------------
if (timeout)
delay(xxx);// sensors are likely still picking up sound (don't forget echoes).  Wait until it dies down