找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 8253|回復(fù): 2
收起左側(cè)

Arduino學(xué)習(xí)9-自制DTMF撥號(hào)器

[復(fù)制鏈接]
ID:114115 發(fā)表于 2016-4-14 03:54 | 顯示全部樓層 |閱讀模式
怎么撥打電話?也許這個(gè)問題很簡(jiǎn)單:拿起話筒,按話機(jī)的數(shù)字鍵盤撥號(hào)碼。
但是,有沒想過,我們可以拿起電話,不需要碰話機(jī)鍵盤就能撥通電話?答案是肯定的。
下面就介紹如何用Arduino生成雙音多頻信號(hào)。

用法介紹:
使用時(shí)候,我們拿起電話話筒,將喇叭貼近話筒麥克風(fēng)位置。在串口發(fā)送需要撥號(hào)的電話號(hào)碼(比如10000),稍等片刻即可撥通。

擴(kuò)展用法:
驅(qū)動(dòng)開關(guān)模擬電話摘機(jī)事件,用此電路撥號(hào),再由Arduino按照事件控制語音模塊(WT588D等)發(fā)出不同的語音到電話線。即可完成一個(gè)整體的自動(dòng)撥號(hào)機(jī),可以制作報(bào)警器,或者電話提醒器。

材料清單:
Arduino一塊,
喇叭1個(gè),
100Ω電阻1個(gè)(可以選擇100Ω~1kΩ),
1uF電容兩個(gè)(可以選擇0.1uF~10uF)。

硬件連接:
142401nhvga3cqn1lvvlnf.gif
程序代碼:

1. 下載Tone庫,并且解壓到arduino-0022libraries文件夾

此Tone庫相比自帶的tone函數(shù)特點(diǎn)是,可以同時(shí)在多個(gè)輸出腳輸出不同頻率的波形,但是自帶tone函數(shù)在一段時(shí)間內(nèi)只能在一個(gè)引腳輸出。

2.寫入下面代碼到Arduino:

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

  4.     * 軟件:需要Tone庫,下載地址:
  5.     * 材料:喇叭1個(gè),100Ω電阻1個(gè),1uF電容兩個(gè)
  6.     * 硬件連接:在D11,D12引腳各接一個(gè)1uF電容,之后合并到100Ω電阻一端,
  7.       100Ω電阻另一端接喇叭,然后喇叭另一端接地。

  8.     用法,將喇叭貼近電話機(jī)話筒,然后發(fā)送要撥的電話號(hào)碼到串口,比如10000,即可撥通電話10000
  9.     */

  10.     #include

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

  13.     //定義freq1,freq2為Tone實(shí)例,并且定義雙音多頻的頻率
  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.         //定義聲音產(chǎn)生引腳在Arduino的D11,D12
  23.         freq1.begin(11);
  24.         freq2.begin(12);
  25.     }

  26.     void loop()
  27.     {
  28.         //讀出串口數(shù)據(jù),串接成Phone_Number字符串
  29.         while (Serial.available() > 0)
  30.         {
  31.             Phone_Number += char(Serial.read());
  32.             delay(2);
  33.             mark = 1;
  34.         }
  35.         //播放DTMF音頻,電話號(hào)碼來自Phone_Number,持續(xù)長(zhǎng)度200ms,間隔長(zhǎng)度300ms
  36.         PlayDTMF(Phone_Number, 200, 300);
  37.            
  38.             //如果剛才接收到串口的電話號(hào)碼,因?yàn)樘?hào)碼已經(jīng)在喇叭輸出了,清空電話號(hào)碼并且重置mark
  39.         if(mark == 1)
  40.         {
  41.             Phone_Number = "";
  42.             Serial.println();
  43.             mark = 0;
  44.         }
  45.     }

  46.     /*
  47.     DTMF播放函數(shù)
  48.     調(diào)用格式:playDTMF(數(shù)字(0~9), 持續(xù)時(shí)間)。
  49.     */
  50.     void PlayDTMF(String Number, long duration, long pause)
  51.     {
  52.             //如果輸入數(shù)字為空,或者持續(xù)時(shí)間不為正數(shù),或者暫停時(shí)間不為正數(shù)
  53.             //則視作錯(cuò)誤,立即停止執(zhí)行返回主程序。
  54.         if(Number.length() == 0 || duration <= 0 || pause <= 0) return;
  55.         //將Number逐個(gè)文字分離,
  56.         for(i = 0; i < Number.length(); i++)
  57.         {
  58.             //如果Number屬于0~9的數(shù)字字符,
  59.             if(Number[i] >= '0' && Number[i] <= '9')
  60.             {
  61.                 //則將它ASCII碼減去‘0’,得到純數(shù)字,
  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.     }
復(fù)制代碼

打包下載: Dialer.zip (1.48 KB, 下載次數(shù): 15)

實(shí)物效果:

1. 電路連接
142111jkfre4eogko9ee9z.jpg
2. 喇叭靠近電話撥號(hào)
14211311k99k972d90222d.jpg
3. 串口端發(fā)電話號(hào)碼
14211096blmt8f81hjt8dl.gif
4. 等待喇叭響完撥號(hào)音之后,即可聽到10000號(hào)的應(yīng)答

回復(fù)

使用道具 舉報(bào)

ID:114115 發(fā)表于 2016-4-14 03:58 | 顯示全部樓層
問題:
你好,你寫得很清楚,這個(gè)程序很好理解,一部分是將串口送下去的一串?dāng)?shù)字生成雙音頻;另一個(gè)部分就是使用喇叭播放雙音頻。

我的問題是,摘機(jī)后,聽筒里面的撥號(hào)音仍然長(zhǎng)鳴。這時(shí)我也能聽到喇叭播放的“10000”已經(jīng)在受話器旁響起,可是撥號(hào)音同時(shí)也在聽筒里響著,因此撥號(hào)后,沒有反應(yīng)啊。何解?希望指點(diǎn)一二。
謝謝

答案:
問題的提出:昨晚按照原圖測(cè)試,的確出現(xiàn)喇叭播放的“10000”已經(jīng)在受話器旁響起,可是撥號(hào)音同時(shí)也在聽筒里響著的現(xiàn)象,受話器沒有識(shí)別撥號(hào)音。
增大音量的嘗試:今天在Ansifa的指導(dǎo)下,做了以下嘗試。
(1)甩開兩只電容,因?yàn)槲沂褂玫碾娙菔?.1uf的,參數(shù)小,因此甩開。原設(shè)計(jì)是為了保護(hù)喇叭。(這兩個(gè)電容后來我又加上去,也撥號(hào)成功了。)
(2)11、12pin每個(gè)支路增加一只電阻,整個(gè)回路電阻是降低的。改后喇叭音量增大。
改后撥打10000號(hào)成功,第一個(gè)音響起后,話機(jī)里的等待撥號(hào)音就中止了,10000號(hào)撥完,就聽到了電腦話務(wù)員的聲音。

啟示
這個(gè)實(shí)驗(yàn)的目的是用arduino的PWM腳(11、12)合成不同頻率的聲音,并且輸出至喇叭。
Ansifa介紹為保證成功率,應(yīng)該是直接接到電話線里面的。如果你感興趣,也可以分別甩開11、12pin,感受一下單音頻與雙音頻的不同。
注意:受環(huán)境,受話器質(zhì)量、喇叭與受話器距離的影響,撥號(hào)識(shí)別不是每次都成功,需要多撥幾次,但證明這個(gè)方案是可行的。


(附圖:按照Ansifa的指導(dǎo)改后的圖)
1832526i6jfrfc9yrf9jgy.png


哈哈,支持滄海笑1122的親自試驗(yàn),反映的問題我也遇到了,的確成功率不是100%,規(guī)范的使用應(yīng)該是通過電路直接接到電話線上的。這樣就成了撥號(hào)機(jī)了




科普一下“電話線同樣只能傳送聲音。我們不能對(duì)著機(jī)器念電話號(hào)碼,機(jī)器聽不懂,所以電話機(jī)必須用一個(gè)統(tǒng)一的格式,把數(shù)字轉(zhuǎn)變?yōu)槁曇魜韨魉汀C看萎?dāng)你按下數(shù)字鍵,電話機(jī)就會(huì)發(fā)出一個(gè)聲音。這個(gè)聲音的頻率是事先約定的,不同數(shù)字各不相同(其實(shí)就是你按鍵時(shí)聽到的那種高低不同的“滴滴”聲)。機(jī)器收到這個(gè)頻率的聲音,就知道你要撥什么號(hào)碼了。
正因?yàn)槿绱,我們(cè)趽芴?hào)的這段時(shí)間,用嘴或者用任何音響設(shè)備發(fā)出的聲音,都有可能傳到電信局,成為一次撥號(hào)——但是這種情況太難發(fā)生了。每一個(gè)數(shù)字鍵發(fā)出的聲音,其實(shí)是兩個(gè)頻率聲音的組合(頻率的組合表見圖)。而且機(jī)器對(duì)頻率的認(rèn)定非常嚴(yán)格,差一點(diǎn)點(diǎn)都不行,這樣做就能有效地避免雜音被誤當(dāng)成了撥號(hào)!
001559azxwb4a0b0a0sa8n.jpeg
也就解釋了為什么要用Tone庫 而不用自帶的tone,因?yàn)槊總(gè)數(shù)字鍵需要兩個(gè)頻率聲音合成!超版的每個(gè)帖子技術(shù)含量都是非常的高!感謝超版!
回復(fù)

使用道具 舉報(bào)

ID:162374 發(fā)表于 2018-4-25 13:44 | 顯示全部樓層
請(qǐng)問能不能一個(gè)arduino讀取傳真信號(hào),然后通過esp模塊傳遞給另一個(gè)arduino?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表