色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何用Arduino UNO實現DTMF解碼器

454398 ? 來源:網絡整理 ? 作者:網絡整理 ? 2019-11-25 15:47 ? 次閱讀

步驟1:了解算法

如何用Arduino UNO實現DTMF解碼器

在DTMF中,每個符號根據圖片上的表格使用兩個頻率進行編碼。

該設備捕獲麥克風的輸入并計算八個頻率的幅度。具有最大幅度的兩個頻率給出了編碼符號的一行和一列。

數據采集

為了執行頻譜分析,應以某個可預測的頻率捕獲樣本。為了達到這個目的,我使用了具有最大精度的自由運行ADC模式(預分頻器128),它提供了9615Hz的采樣率。下面的代碼顯示了如何配置ArduinoADC。

void initADC() {

// Init ADC; f = ( 16MHz/prescaler ) / 13 cycles/conversion

ADMUX = 0; // Channel sel, right-adj, use AREF pin

ADCSRA = _BV(ADEN) | // ADC enable

_BV(ADSC) | // ADC start

_BV(ADATE) | // Auto trigger

_BV(ADIE) | // Interrupt enable

_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1 / 13 = 9615 Hz

ADCSRB = 0; // Free-run mode

DIDR0 = _BV(0); // Turn off digital input for ADC pin

TIMSK0 = 0; // Timer0 off

}

And the interrupt handler looks like this

ISR(ADC_vect) {

uint16_t sample = ADC;samples[samplePos++] = sample - 400;

if(samplePos 》= N) {

ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off

}

}

頻譜分析

收集樣本后,我計算出8個頻率的幅度,這些頻率編碼符號。我不需要為此運行完整的FFT,因此我使用了Goertzel的算法。

void goertzel(uint8_t *samples, float *spectrum) {

float v_0, v_1, v_2;

float re, im, amp;

for (uint8_t k = 0; k 《 IX_LEN; k++) {

float c = pgm_read_float(&(cos_t[k]));

float s = pgm_read_float(&(sin_t[k]));

float a = 2. * c;

v_0 = v_1 = v_2 = 0;

for (uint16_t i = 0; i 《 N; i++) {

v_0 = v_1;

v_1 = v_2;

v_2 = (float)(samples[i]) + a * v_1 - v_0;

}

re = c * v_2 - v_1;

im = s * v_2;

amp = sqrt(re * re + im * im);

spectrum[k] = amp;

}

}

步驟2:代碼

上圖顯示了數字3的編碼示例,其中最大幅度對應于697Hz和1477Hz頻率。

完整的草圖如下

/**

* Connections:

* [ Mic to Arduino ]

* - Out -》 A0

* - Vcc -》 3.3V

* - Gnd -》 Gnd

* - Arduino: AREF -》 3.3V

* [ Display to Arduino ]

* - Vcc -》 5V

* - Gnd -》 Gnd

* - DIN -》 D11

* - CLK -》 D13

* - CS -》 D9

*/

#include

#include

#include

#define CS_PIN 9

#define N 256

#define IX_LEN 8

#define THRESHOLD 20

LEDMatrixDriver lmd(1, CS_PIN);

uint8_t samples[N];

volatile uint16_t samplePos = 0;

float spectrum[IX_LEN];

// Frequences [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]

// Calculated for 9615Hz 256 samples

const float cos_t[IX_LEN] PROGMEM = {

0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449,

0.6895405447370669, 0.6343932841636456, 0.5555702330196023, 0.4713967368259978

};

const float sin_t[IX_LEN] PROGMEM = {

0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334,

0.7242470829514669, 0.7730104533627369, 0.8314696123025451, 0.8819212643483549

};

typedef struct {

char digit;

uint8_t index;

} digit_t;

digit_t detected_digit;

const char table[4][4] PROGMEM = {

{‘1’, ‘2’, ‘3’, ‘A’},

{‘4’, ‘5’, ‘6’, ‘B’},

{‘7’, ‘8’, ‘9’, ‘C’},

{‘*’, ‘0’, ‘#’, ‘D’}

};

const uint8_t char_indexes[4][4] PROGMEM = {

{1, 2, 3, 10},

{4, 5, 6, 11},

{7, 8, 9, 12},

{15, 0, 14, 13}

};

byte font[16][8] = {

{0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x38}, // 0

{0x04,0x0c,0x14,0x24,0x04,0x04,0x04,0x04}, // 1

{0x00,0x30,0x48,0x04,0x04,0x38,0x40,0x7c}, // 2

{0x00,0x38,0x04,0x04,0x18,0x04,0x44,0x38}, // 3

{0x00,0x04,0x0c,0x14,0x24,0x7e,0x04,0x04}, // 4

{0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x38}, // 5

{0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38}, // 6

{0x00,0x7c,0x04,0x04,0x08,0x08,0x10,0x10}, // 7

{0x00,0x3c,0x44,0x44,0x38,0x44,0x44,0x78}, // 8

{0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x78}, // 9

{0x00,0x1c,0x22,0x42,0x42,0x7e,0x42,0x42}, // A

{0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x7c}, // B

{0x00,0x3c,0x44,0x40,0x40,0x40,0x44,0x7c}, // C

{0x00,0x7c,0x42,0x42,0x42,0x42,0x44,0x78}, // D

{0x00,0x0a,0x7f,0x14,0x28,0xfe,0x50,0x00}, // #

{0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10} // *

};

void initADC() {

// Init ADC; f = ( 16MHz/prescaler ) / 13 cycles/conversion

ADMUX = 0; // Channel sel, right-adj, use AREF pin

ADCSRA = _BV(ADEN) | // ADC enable

_BV(ADSC) | // ADC start

_BV(ADATE) | // Auto trigger

_BV(ADIE) | // Interrupt enable

_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1 / 13 = 9615 Hz

ADCSRB = 0; // Free-run mode

DIDR0 = _BV(0); // Turn off digital input for ADC pin

TIMSK0 = 0; // Timer0 off

}

void goertzel(uint8_t *samples, float *spectrum) {

float v_0, v_1, v_2;

float re, im, amp;

for (uint8_t k = 0; k 《 IX_LEN; k++) {

float c = pgm_read_float(&(cos_t[k]));

float s = pgm_read_float(&(sin_t[k]));

float a = 2. * c;

v_0 = v_1 = v_2 = 0;

for (uint16_t i = 0; i 《 N; i++) {

v_0 = v_1;

v_1 = v_2;

v_2 = (float)(samples[i]) + a * v_1 - v_0;

}

re = c * v_2 - v_1;

im = s * v_2;

amp = sqrt(re * re + im * im);

spectrum[k] = amp;

}

}

float avg(float *a, uint16_t len) {

float result = .0;

for (uint16_t i = 0; i 《 len; i++) {

result += a[i];

}

return result / len;

}

int8_t get_single_index_above_threshold(float *a, uint16_t len, float threshold) {

if (threshold 《 THRESHOLD) {

return -1;

}

int8_t ix = -1;

for (uint16_t i = 0; i 《 len; i++) {

if (a[i] 》 threshold) {

if (ix == -1) {

ix = i;

} else {

return -1;

}

}

}

return ix;

}

void detect_digit(float *spectrum) {

float avg_row = avg(spectrum, 4);

float avg_col = avg(&spectrum[4], 4);

int8_t row = get_single_index_above_threshold(spectrum, 4, avg_row);

int8_t col = get_single_index_above_threshold(&spectrum[4], 4, avg_col);

if (row != -1 && col != -1 && avg_col 》 200) {

detected_digit.digit = pgm_read_byte(&(table[row][col]));

detected_digit.index = pgm_read_byte(&(char_indexes[row][col]));

} else {

detected_digit.digit = 0;

}

}

void drawSprite(byte* sprite) {

// The mask is used to get the column bit from the sprite row

byte mask = B10000000;

for(int iy = 0; iy 《 8; iy++ ) {

for(int ix = 0; ix 《 8; ix++ ) {

lmd.setPixel(7 - iy, ix, (bool)(sprite[iy] & mask ));

// shift the mask by one pixel to the right

mask = mask 》》 1;

}

// reset column mask

mask = B10000000;

}

}

void setup() {

cli();

initADC();

sei();

Serial.begin(115200);

lmd.setEnabled(true);

lmd.setIntensity(2);

lmd.clear();

lmd.display();

detected_digit.digit = 0;

}

unsigned long z = 0;

void loop() {

while(ADCSRA & _BV(ADIE)); // Wait for audio sampling to finish

goertzel(samples, spectrum);

detect_digit(spectrum);

if (detected_digit.digit != 0) {

drawSprite(font[detected_digit.index]);

lmd.display();

}

if (z % 5 == 0) {

for (int i = 0; i 《 IX_LEN; i++) {

Serial.print(spectrum[i]);

Serial.print(“ ”);

}

Serial.println();

Serial.println((int)detected_digit.digit);

}

z++;

samplePos = 0;

ADCSRA |= _BV(ADIE); // Resume sampling interrupt

}

ISR(ADC_vect) {

uint16_t sample = ADC;

samples[samplePos++] = sample - 400;

if(samplePos 》= N) {

ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off

}

}

步驟3:原理圖

應進行以下連接:

麥克風與Arduino

Out -》 A0

Vcc -》 3.3V

Gnd -》 Gnd

將AREF連接到3.3V很重要。

顯示到Arduino

Vcc -》 5V

Gnd -》 Gnd

DIN -》 D11

CLK -》 D13

CS -》 D9

步驟4:結論

這里可以改進什么?我以9615Hz的速率使用N = 256個樣本,該速率有一些頻譜泄漏,如果N = 205且速率為8000Hz,則所需頻率與離散化網格重合。對于該ADC,應在定時器溢出模式下使用。
責任編輯:wv

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 解碼器
    +關注

    關注

    9

    文章

    1143

    瀏覽量

    40768
  • DTMF
    +關注

    關注

    1

    文章

    74

    瀏覽量

    47096
  • Arduino
    +關注

    關注

    188

    文章

    6471

    瀏覽量

    187219
收藏 人收藏

    評論

    相關推薦

    無線網解碼器怎么連接

    無線網解碼器的連接方式可能因設備型號、品牌以及應用場景的不同而有所差異。以下提供的是一種較為通用的連接步驟,但請注意,在實際操作中應參考具體設備的說明書或官方指導進行操作。 一、設備準備 無線網
    的頭像 發表于 10-15 16:31 ?408次閱讀

    無線網解碼器怎么用

    無線網解碼器通常指的是能夠解析無線網絡信號中的編碼信息,將其還原成原始信號或數據流的電子設備。然而,需要強調的是,未經授權的無線網絡解碼行為可能涉及法律問題,因為它可能侵犯了他人的隱私和網絡安全
    的頭像 發表于 10-15 16:28 ?573次閱讀

    無線解碼器的質量標準是什么

    無線解碼器,作為現代通信系統中的關鍵組件,其質量標準對于確保數據傳輸的可靠性、安全性和效率至關重要。 1. 性能指標 1.1 靈敏度 靈敏度是無線解碼器能夠接收到的最小信號強度。高靈敏度意味著解碼器
    的頭像 發表于 10-15 16:21 ?371次閱讀

    解碼器和控制區別是什么

    字電子電路中,解碼器根據輸入的編碼形式進行邏輯運算,輸出對應形式的信號,實現數字之間的轉換。例如,在音視頻領域,解碼器負責將壓縮的音視頻數據解壓縮,生成可以直接觀看和聆聽的媒體內容。 應用場景 :
    的頭像 發表于 09-30 14:27 ?492次閱讀

    控制解碼器的使用方法

    控制解碼器是一種用于解析和執行控制信號的設備,廣泛應用于工業自動化、機器人技術、航空航天等領域。它通常與傳感、執行等設備配合使用,以實現
    的頭像 發表于 09-30 14:24 ?585次閱讀

    遙控解碼器怎么使用

    遙控解碼器是一種用于解碼和復制遙控信號的設備,它可以幫助用戶在遙控丟失或損壞的情況下,重新獲得對設備的控制。 遙控
    的頭像 發表于 09-30 14:23 ?883次閱讀

    全景聲解碼器

    全景聲解碼器是一款將音頻技術推向極致的產品。它不僅提供高質量的音頻解碼,還讓用戶體驗到一種前所未有的聲音空間。無論您是想要享受音樂、觀看電影,還是沉浸于游戲世界,全景聲解碼器都能為您打開一個新的音頻維度,讓每一次聆聽都成為一次精
    的頭像 發表于 09-24 10:40 ?399次閱讀
    全景聲<b class='flag-5'>解碼器</b>

    為什么好的播放還要配解碼器

    好的播放之所以需要配備解碼器,是因為音頻和視頻文件的編碼和解碼是一個復雜的過程,涉及到多種技術和標準。解碼器的作用是將壓縮的音頻和視頻數據還原成可以被播放設備識別和播放的格式。 播放
    的頭像 發表于 09-23 18:02 ?1295次閱讀

    9740解碼器配什么光柵

    關于9740解碼器配什么光柵的問題,由于直接針對特定型號(如9740解碼器)與光柵配套信息的資料可能較為有限,且這種信息可能因廠商、產品系列及具體應用場景的不同而有所差異,因此無法給出一個絕對確定
    的頭像 發表于 09-23 18:01 ?362次閱讀

    光柵解碼器損壞的表現有哪些

    光柵解碼器是一種用于將光信號轉換為電信號的設備,廣泛應用于光學存儲、光學測量、光學通信等領域。當光柵解碼器損壞時,可能會出現多種異常表現。以下是一些可能的表現,以及相應的分析: 信號失真 : 原因
    的頭像 發表于 09-23 17:57 ?566次閱讀

    數字播放解碼器

    數字播放解碼器的組合能夠提供更優質的音頻體驗。數字播放負責處理和傳輸音頻數據,而解碼器則負責將這些數據轉換為高質量的模擬信號。它們的配合可以確保你聽到的音頻既清晰又真實。
    的頭像 發表于 09-06 17:35 ?1096次閱讀
    數字播放<b class='flag-5'>器</b>和<b class='flag-5'>解碼器</b>

    USB多路音頻解碼器模組

    USB多路音頻解碼器模組能夠高效地處理和輸出高質量的音頻信號,適用于各種多媒體應用場景。
    的頭像 發表于 05-30 15:45 ?935次閱讀
    USB多路音頻<b class='flag-5'>解碼器</b>模組

    超低功耗立體聲編解碼器Arduino評估板ARD-AUDIO-DA7212數據手冊

    電子發燒友網站提供《超低功耗立體聲編解碼器Arduino評估板ARD-AUDIO-DA7212數據手冊.rar》資料免費下載
    發表于 05-15 17:17 ?0次下載
    超低功耗立體聲編<b class='flag-5'>解碼器</b><b class='flag-5'>Arduino</b>評估板ARD-AUDIO-DA7212數據手冊

    音視頻解碼器硬件加速:實現更流暢的播放效果

    思想是利用專門的硬件資源,如GPU或專用的解碼芯片,來分擔原本由CPU承擔的解碼任務。這種方式不僅可以大幅提高解碼速度,還能降低CPU的負載,從而實現更流暢的播放效果。 硬件加速的優勢
    的頭像 發表于 02-21 14:40 ?990次閱讀
    音視頻<b class='flag-5'>解碼器</b>硬件加速:<b class='flag-5'>實現</b>更流暢的播放效果

    如何使用Arduino UNO板和電位控制伺服電機

    在本Arduino伺服電機教程中,您將學習如何使用Arduino UNO板和電位控制伺服電機。
    的頭像 發表于 02-11 10:11 ?2850次閱讀
    如何使用<b class='flag-5'>Arduino</b> <b class='flag-5'>UNO</b>板和電位<b class='flag-5'>器</b>控制伺服電機
    主站蜘蛛池模板: 久久这里只有精品1| 香蕉精品国产自在现线拍| 野花韩国高清完整版在线 | 欧美大香线蕉线伊人久久| 4484在线观看视频| 日本xxxxxxxxx老师59| 国产亚洲精品久久久久小| 8090碰成年女人免费碰碰尤物| 日本三级黄色大片| 精品国产国偷自产在线观看| 99日韩精品| 亚洲AV蜜桃永久无码精品红樱桃| 伦理片在线线手机版韩国免费6| 抽插妇女疯狂视频| 亚洲午夜无码久久久久蜜臀av| 秋霞电影院兔费理论观频84mb| 国产在线播放不卡| 俺来也俺去也视频久久| 伊人青青久| 深夜草逼逼| 麻豆精品一卡2卡三卡4卡免费观看 | 无止侵犯高H1V3无止侵犯| 久久综合网久久综合| 国产精品久久人妻无码网站一区L| 在线观看中文字幕码2021不用下载| 色多多旧版污污破解版| 久久热r在线视频精品| 国产高清视频在线播放www色| 中文字幕在线免费视频| 无码毛片内射白浆视频| 欧美videos人牛交| 精品亚洲国产熟女福利自在线| 动漫美女被h动态图| 91精品国产色综合久久不| 亚洲精品成人A8198A片漫画| 日本高清无人区影院| 久久视频精品38在线播放| 国产九九熟女在线视频| 成人网站国产在线视频内射视频| 怡红院美国分院一区二区| 新版孕妇bbwbbwbbw|