找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7062|回复: 2
收起左侧

Arduino学习9-自制DTMF拨号器

[复制链接]
ID:114115 发表于 2016-4-14 03:54 | 显示全部楼层 |阅读模式
怎么拨打电话?也许这个问题很简单:拿起话筒,按话机的数字键盘拨号码。
但是,有没想过,我们可以拿起电话,不需要碰话机键盘就能拨通电话?答案是肯定的。
下面就介绍如何用Arduino生成双音多频信号。

用法介绍:
使用时候,我们拿起电话话筒,将喇叭贴近话筒麦克风位置。在串口发送需要拨号的电话号码(比如10000),稍等片刻即可拨通。

扩展用法:
驱动开关模拟电话摘机事件,用此电路拨号,再由Arduino按照事件控制语音模块(WT588D等)发出不同的语音到电话线。即可完成一个整体的自动拨号机,可以制作报警器,或者电话提醒器。

材料清单:
Arduino一块,
喇叭1个,
100Ω电阻1个(可以选择100Ω~1kΩ),
1uF电容两个(可以选择0.1uF~10uF)。

硬件连接:
142401nhvga3cqn1lvvlnf.gif
程序代码:

1. 下载Tone库,并且解压到arduino-0022libraries文件夹

此Tone库相比自带的tone函数特点是,可以同时在多个输出脚输出不同频率的波形,但是自带tone函数在一段时间内只能在一个引脚输出。

2.写入下面代码到Arduino:

  1.     /*
  2.     使用Arduino生成双音多频
  3.     Ansifa        2011/11/27

  4.     * 软件:需要Tone库,下载地址:
  5.     * 材料:喇叭1个,100Ω电阻1个,1uF电容两个
  6.     * 硬件连接:在D11,D12引脚各接一个1uF电容,之后合并到100Ω电阻一端,
  7.       100Ω电阻另一端接喇叭,然后喇叭另一端接地。

  8.     用法,将喇叭贴近电话机话筒,然后发送要拨的电话号码到串口,比如10000,即可拨通电话10000
  9.     */

  10.     #include

  11.     String Phone_Number = "";
  12.     int i = 0, mark = 0;

  13.     //定义freq1,freq2为Tone实例,并且定义双音多频的频率
  14.     //DTMF频率定义参见:
  15.     Tone freq1;
  16.     Tone freq2;
  17.     const int DTMF_freq1[] = {1336, 1209, 1336, 1477, 1209, 1336, 1477, 1209, 1336, 1477};
  18.     const int DTMF_freq2[] = {941,  697,  697,  697,  770,  770,  770,  852,  852,  852};

  19.     void setup()
  20.     {
  21.         Serial.begin(9600);
  22.         //定义声音产生引脚在Arduino的D11,D12
  23.         freq1.begin(11);
  24.         freq2.begin(12);
  25.     }

  26.     void loop()
  27.     {
  28.         //读出串口数据,串接成Phone_Number字符串
  29.         while (Serial.available() > 0)
  30.         {
  31.             Phone_Number += char(Serial.read());
  32.             delay(2);
  33.             mark = 1;
  34.         }
  35.         //播放DTMF音频,电话号码来自Phone_Number,持续长度200ms,间隔长度300ms
  36.         PlayDTMF(Phone_Number, 200, 300);
  37.            
  38.             //如果刚才接收到串口的电话号码,因为号码已经在喇叭输出了,清空电话号码并且重置mark
  39.         if(mark == 1)
  40.         {
  41.             Phone_Number = "";
  42.             Serial.println();
  43.             mark = 0;
  44.         }
  45.     }

  46.     /*
  47.     DTMF播放函数
  48.     调用格式:playDTMF(数字(0~9), 持续时间)。
  49.     */
  50.     void PlayDTMF(String Number, long duration, long pause)
  51.     {
  52.             //如果输入数字为空,或者持续时间不为正数,或者暂停时间不为正数
  53.             //则视作错误,立即停止执行返回主程序。
  54.         if(Number.length() == 0 || duration <= 0 || pause <= 0) return;
  55.         //将Number逐个文字分离,
  56.         for(i = 0; i < Number.length(); i++)
  57.         {
  58.             //如果Number属于0~9的数字字符,
  59.             if(Number[i] >= '0' && Number[i] <= '9')
  60.             {
  61.                 //则将它ASCII码减去‘0’,得到纯数字,
  62.                 Number[i] -= '0';
  63.                 //然后在串口输出一份,便于查看
  64.                 Serial.print(Number[i], DEC);
  65.                 //输出双音多频之一
  66.                 freq1.play(DTMF_freq1[Number[i]], duration);
  67.                 //输出双音多频之二
  68.                 freq2.play(DTMF_freq2[Number[i]], duration);
  69.                 delay(pause);
  70.             }
  71.         }


  72.     }
复制代码

打包下载: Dialer.zip (1.48 KB, 下载次数: 14)
回复

使用道具 举报

ID:114115 发表于 2016-4-14 03:58 | 显示全部楼层
问题:
你好,你写得很清楚,这个程序很好理解,一部分是将串口送下去的一串数字生成双音频;另一个部分就是使用喇叭播放双音频。

我的问题是,摘机后,听筒里面的拨号音仍然长鸣。这时我也能听到喇叭播放的“10000”已经在受话器旁响起,可是拨号音同时也在听筒里响着,因此拨号后,没有反应啊。何解?希望指点一二。
谢谢

答案:
问题的提出:昨晚按照原图测试,的确出现喇叭播放的“10000”已经在受话器旁响起,可是拨号音同时也在听筒里响着的现象,受话器没有识别拨号音。
增大音量的尝试:今天在Ansifa的指导下,做了以下尝试。
(1)甩开两只电容,因为我使用的电容是0.1uf的,参数小,因此甩开。原设计是为了保护喇叭。(这两个电容后来我又加上去,也拨号成功了。)
(2)11、12pin每个支路增加一只电阻,整个回路电阻是降低的。改后喇叭音量增大。
改后拨打10000号成功,第一个音响起后,话机里的等待拨号音就中止了,10000号拨完,就听到了电脑话务员的声音。

启示
这个实验的目的是用arduino的PWM脚(11、12)合成不同频率的声音,并且输出至喇叭。
Ansifa介绍为保证成功率,应该是直接接到电话线里面的。如果你感兴趣,也可以分别甩开11、12pin,感受一下单音频与双音频的不同。
注意:受环境,受话器质量、喇叭与受话器距离的影响,拨号识别不是每次都成功,需要多拨几次,但证明这个方案是可行的。


(附图:按照Ansifa的指导改后的图)
1832526i6jfrfc9yrf9jgy.png


哈哈,支持沧海笑1122的亲自试验,反映的问题我也遇到了,的确成功率不是100%,规范的使用应该是通过电路直接接到电话线上的。这样就成了拨号机了




科普一下“电话线同样只能传送声音。我们不能对着机器念电话号码,机器听不懂,所以电话机必须用一个统一的格式,把数字转变为声音来传送。每次当你按下数字键,电话机就会发出一个声音。这个声音的频率是事先约定的,不同数字各不相同(其实就是你按键时听到的那种高低不同的“滴滴”声)。机器收到这个频率的声音,就知道你要拨什么号码了。
正因为如此,我们在拨号的这段时间,用嘴或者用任何音响设备发出的声音,都有可能传到电信局,成为一次拨号——但是这种情况太难发生了。每一个数字键发出的声音,其实是两个频率声音的组合(频率的组合表见图)。而且机器对频率的认定非常严格,差一点点都不行,这样做就能有效地避免杂音被误当成了拨号。”
001559azxwb4a0b0a0sa8n.jpeg
也就解释了为什么要用Tone库 而不用自带的tone,因为每个数字键需要两个频率声音合成!超版的每个帖子技术含量都是非常的高!感谢超版!
回复

使用道具 举报

ID:162374 发表于 2018-4-25 13:44 | 显示全部楼层
请问能不能一个arduino读取传真信号,然后通过esp模块传递给另一个arduino?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表