How it works:

Chirp Generation

Using a counter and interrupt, the MCU generates a sequence of time periods that vary in period.  At each time period, the ADC is used to output a voltage, alternating between (1.65-amplitude) and (1.65+amplitude) with 1.65 volt as the midpoint (1/2 of supply).  The maximum frequency, minimum frequency, number of pulses, and amplitide can therefore be controlled in software.  Note that this produces a square wave chirp.  Typical ranges used are 60kHz to 30kHz and from 32 cycles to 256 cycles duration (where 1 cycle counts as a positive and negative pulse in the pulse train).

Chirp generated is period modulated using a timer interrupt and DAC.
Chirp generated is period modulated using a timer interrupt and DAC.

Output Stage

The output of the ADC is amplified by two op amps in a push pull fashion, resulting in a gain factor of 12, resulting in a maximum swing of 39.6v p-p output at the ultrasonic transmitter.  The amplifier output drives the ultrasonic transducer in series with an inductor and resistor.  These provide compensation to flatten the response of the transducer, which by itself is tuned at 40KHz.  See this paper for details.

Output Stage
Output stage uses push-pull op amps and 40 volt supply

Ultrasonic Echos

The chirp passes through the air and reflects off of one or more targets.  It also gets transmitted directly to the micrphones, as well as bounces off the surface the sensor rig is on and produces false echos.  We will get to how we deal with those later.

Microphones detect false echos as well as true targets
Microphones detect false echos as well as true targets


MEMS Microphones

The MEMS microphones are within 2.8mm of each other, which is less than 1/2 the wavelength of the signals used, which results in unambiguous phase detection.  Each microphone is sampled at 4MHz to capture signals with high time resolution. 

MEMS Microphones
Distance between the microphones is less than 1/2 wavelength.

MCU Microphone Input

The MCU has an I2S peripheral with 2 channels which is used to sample the microphones at 4MHz.  A fifo buffer of 5 32-bit words is used on each channel with an interrupt on buffer full to write to RAM.   No DMA was used since I could not get it to work and my napkin calcs showed it would not save a lot of processor time.  For each microphone, a maximum buffer of 10,000 32-bit words are used to collect the PDM data.  A 10,000 word buffer holds 80msec of data, which translates to 1060 inches of sound travel, a range of 530 inches.  The size of the buffer is software controlled so that shorter range windows(and corresponding faster processing times) can be configured.

void I2S_Int(void)
//I2S interrupt routine called when buffer is full
//Loop unrolled for speed
{
    if(memsbuffer_i < (sample_size-4))  //buffer of 5
    {
        memsbuffer0[memsbuffer_i]=I2S0_RDR0;
        memsbuffer1[memsbuffer_i]=I2S0_RDR1;
        memsbuffer_i = memsbuffer_i +1;

        memsbuffer0[memsbuffer_i]=I2S0_RDR0;
        memsbuffer1[memsbuffer_i]=I2S0_RDR1;
        memsbuffer_i = memsbuffer_i +1;

        memsbuffer0[memsbuffer_i]=I2S0_RDR0;
        memsbuffer1[memsbuffer_i]=I2S0_RDR1;
        memsbuffer_i = memsbuffer_i +1;

        memsbuffer0[memsbuffer_i]=I2S0_RDR0;
        memsbuffer1[memsbuffer_i]=I2S0_RDR1;
        memsbuffer_i = memsbuffer_i +1;

        memsbuffer0[memsbuffer_i]=I2S0_RDR0;
        memsbuffer1[memsbuffer_i]=I2S0_RDR1;
        memsbuffer_i = memsbuffer_i +1;

        I2S0_RCSR = I2S0_RCSR | I2S_RCSR_FEF_MASK;

    }
    else
    {
        //disable, reset fifos, turn off interrupts, but keeps bit clock on
        I2S0_RCSR =  I2S_RCSR_FR_MASK| I2S_RCSR_WSF_MASK| I2S_RCSR_SEF_MASK| I2S_RCSR_FEF_MASK| I2S_RCSR_FWF_MASK| I2S_RCSR_BCE_MASK;
    }

}
... Read more »