JuncoJet 发表于 2024-6-6 14:58:56

为啥 DTMF 双音拨号识别,用DFT比FFT好?

本来用 FFT 来解析的,能读,但有错误,准确度不高
网上说 DTMF 要用 DFT,有大佬了解吗

FFT 不是比 DFT 高效吗?

Jambalaya 发表于 2024-6-6 15:05:04

https://wenku.baidu.com/view/5f2cfd7eae02de80d4d8d15abe23482fb4da02c5.html?_wkts_=1717657420110&needWelcomeRecommand=1

luosifu 发表于 2024-6-6 15:14:41

本帖最后由 luosifu 于 2024-6-6 15:21 编辑

自己删除了我回复的内容,懒得去翻书了,没有依据的回复容易误导各位:lol

JuncoJet 发表于 2024-6-6 15:19:35

luosifu 发表于 2024-6-6 15:14
我想瞎说的楼上坛友已经找到了,因为双音频的那几个频率是已知且固定的,DFT可以只针对这几个频率去计算。 ...

能用,就绘制图形能用,单看数值结果上看不出规律
都忽高忽低的= =# 也不知道啥问题

MF35_ 发表于 2024-6-6 16:12:45

本帖最后由 MF35_ 于 2024-6-6 16:15 编辑

2楼已经给了答案了,除了频谱仪外,很多涉及到频域分析的仪器,典型的比如阻抗(复数)测试仪,都用DFT而不是FFT,就是因为频率已知的前提下,DFT的计算是非常简单的,只需要一个正弦表和一个余弦表而已

固定单频点的DFT算法还有有其他的名字,数字相干检波、数字鉴相、数字锁相检波等等,其实都一回事,本质上就是用余弦表和正弦表做两次加权积分,或者说加权平均抽取,都是一个概念

JuncoJet 发表于 2024-6-6 22:30:46


DFT没写出来,FFT倒是又可以了

xiaolaba 发表于 2024-6-8 20:41:13

看你用什麼機器 如果8位機用FFT會受不了,因為無法實時解碼

JuncoJet 发表于 2024-6-8 21:11:06

xiaolaba 发表于 2024-6-8 20:41
看你用什麼機器 如果8位機用FFT會受不了,因為無法實時解碼

air001 Cortex-M0

xiaolaba 发表于 2024-6-8 21:29:56

JuncoJet 发表于 2024-6-8 21:11
air001 Cortex-M0

要用1bit adc(比較器)的話可以用dft試試看,就一sin表 然後移相90度參個cos表
如果實時要求就看看Goertzel algorithm ,比dft更有效,8位機都行那arm更是輕鬆

JuncoJet 发表于 2024-6-9 00:47:57

xiaolaba 发表于 2024-6-8 21:29
要用1bit adc(比較器)的話可以用dft試試看,就一sin表 然後移相90度參個cos表
如果實時要求就看看Goer ...

用的 Arduino Goertzel 库,
参考 fsk 的例子做双音识别,失败

#define A1 PA6
// Define the ADC midpoint (512 is the default)
#define ADC_MIDPOINT 512
// Define the sample rate (8800 S/s is the default for 16 MHz Boards)
#define SAMPLE_RATE 8800
// include the Goertzel library
#include <Goertzel.h>
// Array buffer for ADC samples
int Samples;
// Variable for resulting magnitude
float Mag;
// Instantiate class for 440 Hz tone detection
Goertzel f1(697);
Goertzel f2(770);
Goertzel f3(852);
Goertzel f4(941);
Goertzel f5(1209);
Goertzel f6(1336);
Goertzel f7(1477);
void setup() {
Serial.begin(115200);
}
void loop() {
int DEPTH = sizeof(Samples) / sizeof(Samples);
// Get 100 ADC samples from A1 and store them in the buffer
for (int n = 0; n < DEPTH; n++) {
    Samples = analogRead(A1);
}
// Determine the amount of Samples
char str[]="Num:",num=0;
float r1,r2,r3,r4,r5,r6,r7;
r1 = f1.Mag(Samples, DEPTH);
r2 = f2.Mag(Samples, DEPTH);
r3 = f3.Mag(Samples, DEPTH);
r4 = f4.Mag(Samples, DEPTH);
r5 = f5.Mag(Samples, DEPTH);
r6 = f6.Mag(Samples, DEPTH);
r7 = f7.Mag(Samples, DEPTH);
if(r5>r1>0){
    num='1';
}else if(r6>r1>0){
    num='2';
}else if(r7>r1>0){
    num='3';
}else if(r5>r2>0){
    num='4';
}else if(r6>r2>0){
    num='5';
}else if(r7>r2>0){
    num='6';
}else if(r5>r3>0){
    num='7';
}else if(r6>r3>0){
    num='8';
}else if(r7>r3>0){
    num='9';
}else if(r5>r4>0){
    num='*';
}else if(r6>r4>0){
    num='0';
}else if(r7>r4>0){
    num='#';
}
str=num;
// print result to serial
Serial.println(str);
}

iffi123 发表于 2024-6-9 05:47:08

在采样频率和被测频率不是整数倍的时候,FFT有个频谱泄露问题很麻烦,有改善的办法但无法完全避免

快乐毛毛虫 发表于 2024-6-9 13:31:48

用MT8870芯片硬件译码很简单

JuncoJet 发表于 2024-6-9 14:16:43

快乐毛毛虫 发表于 2024-6-9 13:31
用MT8870芯片硬件译码很简单

自己主要是为了学习原理,乐趣
软解也能通用的解决很多类似的问题

快乐毛毛虫 发表于 2024-6-9 21:37:35

20多年前,我用MT8870做电话遥控装置,用MT8880做自动拨打电话卡号和密码的自动拨号器,打IP电话省事多了。

xiaolaba 发表于 2024-6-10 21:33:18

JuncoJet 发表于 2024-6-9 00:47
用的 Arduino Goertzel 库,
参考 fsk 的例子做双音识别,失败

叉回去參考看看
https://github.com/xiaolaba/ATmega-DTMF-Decoder
DFT也是可以的, 第一代PIC用過, 不過源碼找不到了.
页: [1]
查看完整版本: 为啥 DTMF 双音拨号识别,用DFT比FFT好?