I've got a strange setup:

Background: I'm building a wireless binary transmitter with a couple of low powered CB radios. I've re-soldered the activator button and microphone on one; that sends two different tones (1500hz for 1, 1000hz for 0); this end of the setup runs beautifully with my Arduino.

My issue is with the receiving end: I've tried reading directly from the speaker pins using analogRead, but can't see any difference in the values from before the sounds are received, to after.

My question: how can I patch my way into the speaker on the second CB to Arduino so that I can read the tone/pitch value?

Sort of what I have:


simulate this circuit – Schematic created using CircuitLab

  • \$\begingroup\$ Why did you choose to go this way rather than a modem or DTMF solution? \$\endgroup\$ Dec 31, 2015 at 3:04
  • 1
    \$\begingroup\$ Call it equal parts curiosity and availability; These CB handsets aren't used any longer and would end up in the trash otherwise and they have pretty good distance in my area, haha \$\endgroup\$ Dec 31, 2015 at 3:17
  • \$\begingroup\$ Well, okay, but both solutions will work over CB. \$\endgroup\$ Dec 31, 2015 at 3:18
  • \$\begingroup\$ That much I know, it was more to do with making do with what I already had on hand (I'm in a very remote area of Australia, and wanted a fun project in my down time, haha) \$\endgroup\$ Dec 31, 2015 at 3:21

1 Answer 1


Edit: skip to the bottom for a decent solution.

By default, analogRead() is far to slow to properly sample signals at 1kHz+. There are several things you can/should do if you want to use the Arduino ADC for tone detection:

  • Change the ADC clock prescaler. At 16MHz, I've been able to set ADPS as low as 3, although accuracy will be reduced.

  • Stop using analogRead(), and write your own ADC read wrapper. There is a lot of cruft in analogRead() that you don't need if you know what you're doing.

  • Put the ADC in free-running mode, so you don't have to wait for it to sample.

By doing all these things, it's possible to bring the sample rate of the ADC close to 10kHz or beyond, which is fast enough for your purposes. Note that unless your are quite clever with your code, this process is likely to use up almost all your cycles, leaving you with a not very useful Arduino.

However, there's an alternative: good ol' analog filters. Build two peak filters with high Q at your frequencies of interest, run them both into peak detectors, and then your Arduino need only look at two digital signals.

Edit: another way to do it. Rectify the audio, and clip it to a digital signal. Then count pulses in a constant time interval with the Arduino. This is the easiest way to do things (least hardware, doesn't require too many cycles, can run in an interrupt).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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