Adrianotiger / phoneDTMF

Detect DTMF without external devices
29 stars 6 forks source link

Working with Ham Radio rather than Telephone #4

Open KDMcMullan opened 6 months ago

KDMcMullan commented 6 months ago

I've put the example programs on an ESP3866 Mini, connected to a handheld walkie-talkie. The radio is receiving DTMFs from a transmitter. I scoped the output from my radio jack at 0 .. 8V, and build a potential divider to split that down to 0 .. 3.3V.

When I try to use the library to recognise DTMFs, it's very unreliable. It recognises, maybe 1 tone pair in every 20.

If I write a little program to dump the ADC values, and inject 3.3V into the ADC, it registers 1023. The dump shows an average value of 15 when nothing is being sent, 511 when I press transmit and random numbers up to 1023 when I send a DTMF. This is all as I would expect, so I have confidence in my hardware.

Is if important that the sampling frequency is 6000? I set it at 12000 and MaxFrequence returned 11363, which I think is quite good. (It defaults to a little over 14000.)

I note that you mention a 12 bit ADC, which I'm confused about, since my values would suggest a 10 bit ADC with a 0 .. 3.3V scale.. I have tried "amplifier" values of 2 and 4, and also increased the sample size to 300. I believe each of these made it worse.

Do you have any suggestions for something else I might try, please?

Adrianotiger commented 6 months ago

Hi McMullan, Are you able to output your measurements? It is important to have a clear signal, since the library will just listen 10 different frequencies.

Can you measure the DC value? I think this should be ~1.6V.

In my module, I need to detect the signal 2-3 times to get the pressed button. If you can output some debug values, you can play with the parameters to get a better result.

Begin() is also important to detect the amplitude of your signal and should be called when you don't have any "sound" on the line.

KDMcMullan commented 6 months ago

Ooops. I neglected to add the DC filter. I've added one, and now, rather than 0 .. 3.3V, the signal at the ADC is -1.6 .. 1.6V. Why would this work? Surely the ADC is single-ended? (Only takes +ve values.) I can confirm that if(button > 0) never goes true, so I don't even have the opportunity to make 2-3 detections.

Adrianotiger commented 5 months ago

Hi Ken, I would say that the 0-3.3V should be a better signal than -1.6-1.6V. After calling begin, the library should detect the DC component. On a 10-bit ADC, this should be ~500. If you add a DC filter, it is better to add a diode, since the voltage should not be less than -0.3V.

To be honest, I just have a single project using this library... But it works.

KDMcMullan commented 5 months ago

I hope to get it to work in order to remove the MT 8870 from my project and basically miniaturise it down to a single small PCB. I also hope that other ham / IoT enthusiasts will pick it up and run with it. I hope you can help me understand further. The audio out from my radio is in the range 0 .. 8V. I have potted than down to be in the range 0 .. 3.3V, as I believe that to be the valid input range for the ADC of my ESP8266. This did not work. I then realised that you had a capacitor to filter DC, but when I added the capacitor, the input to the ADC became -1.6 .. 1.6V. This also did not work, and I think it is beyond the capability of my ADC.

I have a feeling the problem may be that there is no DC offset unless the transmitter is actually transmitting, whereas with a phone, there is always an offset. In my native setup, my output would read 0V while there is no transmission. This goes to 4V when there is a silent transmission, and the waveform is from 0 to 8V when the DTMF actually starts,

How can I dump the contents of the ADC buffer acquired by the phone DTMF library? If I could get a look at it, it would help me understand if the problem is electrical or software.

Thanks for your patience.

Adrianotiger commented 5 months ago

If you are able to get an ADC from 0 to 3.3, you should get a nice signal and detect the tones. Do you have a display to connect to your ESP8266? You can also output the data to the serial.

Play around with detect(float* pMagnitudes, float magnitude)

Here an example:

void loop()
{
  float magnitudes[8];
  dtmf.detect(magnitudes, -1.0f);
}
now you have the magnitudes of the 8 frequencies to detect: 
  697,
  770,
  852,
  941,
 1209,
 1336,
 1477,
 1633

If nothing was detected, the 8 float array, have similar values. If something was detected, you should see 2 values with a much higher number. If so, you detected a tone.

With the helper functions getAnalogCenter(), getBaseMagnitude() and getRealFrequence() you can check if the measurement was good. the analogcenter is updated on each measurement. Maybe the first measurement is not good, but the second should be ok.

Be sure to call dtmf.detect() many times, as the measurement is made in 20-30ms. If you didn't detected anything, you need to call it again and again, until the returned values are valid.

KDMcMullan commented 5 months ago

Right. I finally got back to this. I feel that putting the capacitor in circuit was a mistake: the potential divider on teh output from my radio already gave me a 0 .. 3.3V signal. Now, a feature of this (a typical) radio is that there is 0V on the speaker output until a carrier is received. On receipt of a carrier, the output goes t 4V. This does NOT mean that a DTMF is being received. The DTMF then causes that 4V baseline to modulate from 0 to 8 V. (Per my original log.)

The observations are:

This makes sense: I believe that the software expects this "carrier" to be permanently present (it is for a phone). If I understand the documentation correctly, the first call to dtmf.connect() "calibrates" it to the "nothing received" voltage. In my case this is zero volts, which is different from "transmission received, but it wasn't a DTMF" (4V).