2

I am working on a project that requires me to sample 6 microphones as close to simultaneously as possible at a rate of at least 11 kHz each and then run a processing algorithm on the data in real time. I have been using a Raspberry Pi Zero, since it is important that I use a very small computer. The microphones need to be rather small as well, so I am currently using ADMP401 microphone breakouts from Sparkfun. They output an analog voltage, which I am reading through MCP3002 ADC chips with a C++ program. I am using the spidev library and the ioctl function to sample the ADC's. With this setup, I have been unable to consistently sample just one microphone faster than 10 kHz.

My biggest issue is with delays between SPI transmissions. I have tested a loop that simply samples the ADC over and over. Between each sample there is usually a 60 to 80 microsecond delay between the clock line sequences and sometimes it is significantly longer. (I verified this with an oscilloscope). The length of this delay is not affected by the SPI frequency that I am setting, even though the clock rate does change when I change the SPI frequency. This delay is not likely due to the conversion time of the ADC since its data sheet says it has a sample rate between 75,000 and 200,000 samples per second, which corresponds to a sampling interval range of 5 to 13 microseconds. The other big issue is that the inconsistent nature of the delay between samples lowers the quality of my data processing.

My probable next approach is to purchase a multi-channel, simultaneous sampling ADC, which I will connect to my 6 microphones. I will use an Arduino to sample the ADC and ensure a consistent frequency with a timer interrupt. I will store the data in an array of 50 to 100 samples and then each time the array fills up, I will send its contents to the Raspberry Pi with SPI. Hopefully this will greatly diminish the impact of the inter-packet delays. Does anyone see any potential issue with this approach?

I feel like there should be another way to do this without using an Arduino. I did a little research into improving SPI frequency and I came upon this thread which spawned the project discussed here. If I tried to build my own kernel (am I saying that right?) for the Pi with this approach, would it lessen the inter-packet delay or just improve the clock frequency within each packet? Should I write a Linux device driver or kernel module as discussed here?

Perhaps the Raspberry Pi isn't even the best CPU for my project. Someone recommended using an FPGA. Is that appropriate? I am open to changing anything and everything about my approach.

1

I can suggest an approach which may work on the Pi.

The approach is outlined here.

By using bit-banging it is possible to get 12 bit ADC samples from one or more MCP3202s simultaneously. Rates of 25ksps per ADC can be achieved. Conventional SPI only allows one device to talk at a time. By using bit-banging you can share one CLK, MOSI, and SS (slave select) lines between many ADCs but give each its own MISO.

An advantage of bit-banging is that you have tight control of when the samples are taken, in the case given every 40 μs, not as and when the SPI driver gets around to it.

To bit-bang a chain of DMA blocks is used to switch the CLK, MOSI, and SS lines on/off according to the SPI requirements. The DMA blocks also contain gpio reads to capture the data transmitted by the ADC MISO lines. All gpios are read simultaneously (that's the way the Broadcom SOC works) so as many ADCs can be read as can be connected. In my experiment I used 2 ADCs as that is all I have.

The method requires an ADC per microphone and can only sample one channel of a multi-channel ADC at a time. For that reason there is little point in buying a multi-channel ADC.

See SPI bit bang read MCP3202 (12-bit ADC) for an example using the MCP3202.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.