Sound Direction Finder Using Pic18f452 ... help

Discussion in 'Programmer's Corner' started by tallo, May 27, 2013.

  1. tallo

    Thread Starter New Member

    Mar 4, 2011
    12
    0
    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
     
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,342
    1,024
    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.
     
  3. tallo

    Thread Starter New Member

    Mar 4, 2011
    12
    0
    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;
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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?
     
  5. JohnInTX

    Moderator

    Jun 26, 2012
    2,342
    1,024
    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):
    Code ( (Unknown Language)):
    1.  
    2.  
    3. [FONT=Verdana][SIZE=2]init(); // stop timer, clear it etc...
    4.  
    5. //--------- WAIT FOR FIRST SOUND  --------------
    6. do{
    7.  Sound1=PORTB & 0x0f; // read all 4 sensors, strip off unused bits
    8. }while (Sound1==0);   // until you get something, Sound 1 is image of port when it started and says which mic heard the sound.
    9.  
    10. //----------- START TIMER  --------------------
    11. TMR0ON = 1; // start timer
    12. TMR0IF = 0; // clear overflow flag
    13. mask = ~Sound1 & 0x0f // eliminate that mic from next test
    14.  
    15. //------------- WAIT FOR 2ed SOUND  ------------------
    16. do{
    17.  Sound2 = PORTB & mask; // read remaining sensors
    18. }while ((Sound2 == 0) && !TMR0IF); // until 2ed sound heard OR timeout
    19.  
    20. //-------------- PROCESS RESULT  --------------------
    21. if (timeout)
    22.  do_error(); // report error, try again
    23. else{
    24.  .. examine Sound1 and Sound2 to see which two got hit by the sound in
    25.  sequence.  Calculate direction from time.
    26. }
    27. //--------------- WAIT FOR SOUND TO DIE DOWN  ------------
    28. delay(xxx);// sensors are likely still picking up sound (don't forget echoes).  Wait until it dies down[/SIZE][/FONT]
    29.  
    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.
     
  6. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    JohnInTX likes this.
Loading...