极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 199186|回复: 43

Arduino学习笔记A9 - Arduino自制电话拨号器

  [复制链接]
发表于 2011-11-27 14:22:13 | 显示全部楼层 |阅读模式
Arduino自制电话拨号器


怎么拨打电话?也许这个问题很简单:拿起话筒,按话机的数字键盘拨号码。
但是,有没想过,我们可以拿起电话,不需要碰话机键盘就能拨通电话?答案是肯定的。
下面就介绍如何用Arduino生成双音多频信号。

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

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

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

硬件连接:

程序代码:

1. 下载Tone库,并且解压到arduino-0022\libraries文件夹:
http://rogue-code.googlecode.com/files/Arduino-Library-Tone.zip
此Tone库相比自带的tone函数特点是,可以同时在多个输出脚输出不同频率的波形,但是自带tone函数在一段时间内只能在一个引脚输出。

2.写入下面代码到Arduino:

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

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

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

  10. #include <Tone.h>

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

  13. //定义freq1,freq2为Tone实例,并且定义双音多频的频率
  14. //DTMF频率定义参见:[url]http://zh.wikipedia.org/zh/%E5%8F%8C%E9%9F%B3%E5%A4%9A%E9%A2%91[/url]
  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. }
复制代码
打包下载:

实物效果:

1. 电路连接

2. 喇叭靠近电话拨号

3. 串口端发电话号码

4. 等待喇叭响完拨号音之后,即可听到10000号的应答


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1 +5 收起 理由
弘毅 + 5 这么高级。。。。自动电话拨号的

查看全部评分

回复

使用道具 举报

发表于 2011-11-27 14:51:16 | 显示全部楼层
{:soso_e103:}好高级
回复 支持 反对

使用道具 举报

发表于 2011-11-27 23:37:55 | 显示全部楼层
神奇啊 这什么原理啊 手机也行么{:soso_e103:} 太牛了
回复 支持 反对

使用道具 举报

发表于 2012-2-25 00:35:51 | 显示全部楼层
本帖最后由 沧海笑1122 于 2012-2-25 00:39 编辑

@Ansifa
你好,你写得很清楚,这个程序很好理解,一部分是将串口送下去的一串数字生成双音频;另一个部分就是使用喇叭播放双音频。

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

使用道具 举报

发表于 2012-2-25 18:29:13 | 显示全部楼层
本帖最后由 沧海笑1122 于 2012-2-25 18:52 编辑

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

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

再次感谢Ansifa。

(附图:按照Ansifa的指导改后的图)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1 +30 收起 理由
Ansifa + 30

查看全部评分

回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-2-26 22:30:37 | 显示全部楼层
沧海笑1122 发表于 2012-2-25 18:29
感谢Ansifa的指导。
问题的提出:昨晚按照原图测试,的确出现喇叭播放的“10000”已经在受话器旁响起,可是 ...

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

使用道具 举报

发表于 2012-2-27 10:02:27 | 显示全部楼层
Ansifa 发表于 2012-2-26 22:30
哈哈,支持沧海笑1122的亲自试验,反映的问题我也遇到了,的确成功率不是100%,规范的使用应该是通过电路 ...

遇到脉冲拨号的线路就没辙了,呵呵,好在脉冲都已经淘汰了。
回复 支持 反对

使用道具 举报

发表于 2012-3-3 15:12:00 | 显示全部楼层
zhanggang1971 发表于 2012-2-27 10:02
遇到脉冲拨号的线路就没辙了,呵呵,好在脉冲都已经淘汰了。

脉冲拨号拍挂机键就行了
回复 支持 反对

使用道具 举报

发表于 2012-4-16 22:03:04 | 显示全部楼层
好高级的东西,有时间试一试!
回复 支持 反对

使用道具 举报

发表于 2012-4-19 15:39:31 | 显示全部楼层
很有创意的东西。

能不能想办法在拔号键盘那里接线呢。
回复 支持 反对

使用道具 举报

发表于 2012-4-26 00:37:45 | 显示全部楼层
得试试看,做个好学生
回复 支持 反对

使用道具 举报

发表于 2012-6-15 10:40:04 | 显示全部楼层
有没有能够来电显示的?那样就酷了!
回复 支持 反对

使用道具 举报

发表于 2012-7-13 15:43:41 | 显示全部楼层
Tone::stop()':
F:\arduino-1.0.1\libraries\Tone\Tone.cpp:361: error: 'digitalWrite' was not declared in this scope

我复制的是原程序,下载程序到arduino出现错误,求解。
回复 支持 反对

使用道具 举报

发表于 2012-7-15 00:14:55 | 显示全部楼层
本帖最后由 smfox10 于 2012-7-15 00:18 编辑

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

也就解释了为什么要用Tone库 而不用自带的tone,因为每个数字键需要两个频率声音合成!超版的每个帖子技术含量都是非常的高!感谢超版!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2012-9-12 14:46:30 | 显示全部楼层
那个扩展的Tone很厉害啊,
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 20:09 , Processed in 0.045358 second(s), 31 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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