Tartalomjegyzék:
Videó: DTMF érzékelő: 4 lépés
2024 Szerző: John Day | [email protected]. Utoljára módosítva: 2024-01-30 09:42
Áttekintés
Ennek az eszköznek az elkészítéséhez egy otthoni feladat inspirált a Digitális jelfeldolgozás online tanfolyamon. Ez az Arduino UNO -val megvalósított DTMF -dekódoló, amely az általuk generált hang alapján érzékeli a telefon billentyűzetén megnyomott számjelet hangmódban.
1. lépés: Az algoritmus megértése
A DTMF -ben minden szimbólum két frekvenciával van kódolva a képen látható táblázat szerint.
A készülék rögzíti a mikrofon bemenetét, és nyolc frekvencia amplitúdóját számítja ki. Két maximális amplitúdójú frekvencia ad egy sort és egy oszlopot a kódolt szimbólumból.
Adatgyűjtés
A spektrumelemzés elvégzéséhez a mintákat bizonyos előre látható gyakorisággal kell rögzíteni. Ennek eléréséhez szabadon futó ADC módot használtam maximális pontossággal (128-as előskálázó), amely 9615 Hz mintavételi frekvenciát ad. Az alábbi kód bemutatja, hogyan kell konfigurálni az Arduino ADC -jét.
void initADC () {
// Init ADC; f = (16MHz/előskálázó)/13 ciklus/konverzió ADMUX = 0; // Csatorna sel, right-adj, AREF pin használata ADCSRA = _BV (ADEN) | // ADC engedélyezése _BV (ADSC) | // ADC start _BV (ADATE) | // Automatikus trigger _BV (ADIE) | // Megszakítás engedélyezése _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Szabad futás mód DIDR0 = _BV (0); // A digitális bemenet kikapcsolása az ADC pin TIMSK0 = 0; // Timer0 off} A megszakításkezelő pedig így néz ki: ISR (ADC_vect) {uint16_t sample = ADC; sample [samplePos ++] = sample - 400; if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // A puffer megtelt, a megszakítás kikapcsolva}}
Spektrumanalízis
Mintavétel után számolok szimbólumokat kódoló 8 frekvencia amplitúdóját. Ehhez nem kell teljes FFT -t futtatnom, ezért Goertzel algoritmusát használtam.
void goertzel (uint8_t *minták, lebegő *spektrum) {
úszó 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]))); úszó 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 = (lebegés) (minták ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektrum [k] = amp; }}
2. lépés: A kód
A fenti kép a 3. számjegy kódolásának példáját mutatja, ahol a maximális amplitúdó 697 Hz és 1477 Hz frekvenciának felel meg.
A teljes vázlat a következőképpen néz ki
/** * Csatlakozások: * [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
#befoglalni
#define CS_PIN 9
#define N 256
#define IX_LEN 8 #define THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t minták [N];
illékony uint16_t samplePos = 0;
úszó spektrum [IX_LEN];
// Frekvenciák [697,0, 770,0, 852,0, 941,0, 1209,0, 1336,0, 1477,0, 1633,0]
// 9615 Hz -re számítva 256 minta const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.634393284163645619566056 const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.831469612302545648, typedef structure {
karakterjegy; uint8_t index; } digit_t;
digit_t észlelte_digit;
const char táblázat [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} };
bájtos betűtípus [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/előskálázó)/13 ciklus/konverzió ADMUX = 0; // Csatorna sel, right-adj, AREF pin használata ADCSRA = _BV (ADEN) | // ADC engedélyezése _BV (ADSC) | // ADC start _BV (ADATE) | // Automatikus trigger _BV (ADIE) | // Megszakítás engedélyezése _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1/13 = 9615 Hz ADCSRB = 0; // Szabad futás mód DIDR0 = _BV (0); // Kapcsolja ki a digitális bemenetet az ADC pin TIMSK0 = 0; // Időzítő0 kikapcsolva}
void goertzel (uint8_t *minták, lebegő *spektrum) {
úszó 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]))); úszó 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 = (lebegés) (minták ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = sz * v_2; amp = sqrt (re * re + im * im); spektrum [k] = amp; }}
float avg (float *a, uint16_t len) {
lebegési eredmény =.0; for (uint16_t i = 0; i <len; i ++) {result+= a ; } return result / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float küszöb) {
if (küszöb <THRESHOLD) {return -1; } int8_t ix = -1; for (uint16_t i = 0; i küszöb) {if (ix == -1) {ix = i; } else {return -1; }}} return ix; }
void detect_digit (float *spektrum) {
float avg_row = avg (spektrum, 4); float avg_col = átlag (& spektrum [4], 4); int8_t sor = get_single_index_above_threshold (spektrum, 4, átlag_sor); int8_t col = get_single_index_above_threshold (& spektrum [4], 4, avg_col); if (sor! = -1 && col! = -1 && avg_col> 200) {észlelt_digit.digit = pgm_read_byte (& (táblázat [sor] [oszlop])); detect_digit.index = pgm_read_byte (& (char_indexes [sor] [col])); } else {észlelt_ digit.digit = 0; }}
void drawSprite (byte* sprite) {
// A maszkot arra használjuk, hogy az oszlopbitet lekérjük a sprite sor bájtmaszkjából = B10000000; for (int iy = 0; iy <8; iy ++) {for (int ix = 0; ix <8; ix ++) {lmd.setPixel (7 - iy, ix, (bool) (sprite [iy] & mask));
// tolja el a maszkot egy képponttal jobbra
maszk = maszk >> 1; }
// az oszlopmaszk visszaállítása
maszk = B10000000; }}
void setup () {
cli (); initADC (); sei ();
Sorozat.kezdet (115200);
lmd.setEnabled (igaz); lmd.setIntensity (2); lmd.clear (); lmd.display ();
észlelt_ digit.digit = 0;
}
előjel nélküli hosszú z = 0;
void loop () {
while (ADCSRA & _BV (ADIE)); // Várja meg, amíg az audio mintavétel befejeződik (goetzel) (minták, spektrum); detect_digit (spektrum);
if (észlelt_digit. digit! = 0) {
drawSprite (font [észlelt_digit.index]); lmd.display (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Soros.nyomat (spektrum ); Serial.print ("\ t"); } Sorozat.println (); Serial.println ((int) észlelt_száma. digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // A mintavétel megszakításának folytatása
}
ISR (ADC_vect) {
uint16_t minta = ADC;
minták [samplePos ++] = minta - 400;
if (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // A puffer megtelt, a megszakítás kikapcsolva}}
3. lépés: Sémák
A következő csatlakozásokat kell létrehozni:
Mikrofon Arduino -hoz
Ki -> A0
Vcc -> 3.3V Gnd -> Gnd
Fontos, hogy az AREF -et 3.3V -ra csatlakoztassa
Megjelenítés Arduino számára
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
4. lépés: Következtetés
Mit lehetne itt javítani? N = 256 mintát használtam 9615 Hz -es frekvencián, amely némi spektrumszivárgással rendelkezik, ha N = 205 és a frekvencia 8000 Hz, akkor a kívánt frekvenciák egybeesnek a diszkréciós hálóval. Ehhez az ADC -t kell használni időzítő túlcsordulás módban.
Ajánlott:
DTMF VIDEO STREAMING ROVER: 3 lépés
DTMF VIDEO STREAMING ROVER: sziasztok a LINUX TERMINAL CONTROLLED ROVER és a WIFI DTMF PC Vezérelt ROBOT után ez a harmadik robotom. és a többi kettőhöz hasonlóan itt sem használtam semmilyen mikrokontrollert vagy programozást, hogy egyszerű és könnyen elkészíthető legyen. ez is élő videót közvetít wifi -n keresztül
Egyszerű DTMF (hang) telefonvonal dekódoló készítése: 3 lépés
Egyszerű DTMF (hang) telefonvonal dekódoló készítése: Ez egy egyszerű projekt, amely lehetővé teszi a DTMF jelek dekódolását alapvetően bármely telefonvonalon. Ebben az oktatóanyagban az MT8870D dekódolót használjuk. Előre beépített hangdekódert használunk, mert hidd el, fájdalmas a hátul, ha megpróbálod ezt a
WIFI DTMF ROBOT: 5 lépés
WIFI DTMF ROBOT: sziasztok ebben az oktatóanyagban megmutatom, hogyan készíthet PC -vel vezérelt rovert mikrovezérlő használata nélkül, ez azt jelenti, hogy ebben a projektben nincs magas szintű kód, csak alapvető ismeretekkel kell rendelkeznie a html oldal készítéséről. teljes egészében meg lehet nézni
Mobil vezérlésű robot készítése - DTMF alapú - Mikrokontroller és programozás nélkül - Irányítás a világ bármely pontjáról - RoboGeeks: 15 lépés
Mobil vezérlésű robot készítése | DTMF alapú | Mikrokontroller és programozás nélkül | Irányítás a világ bármely pontjáról | RoboGeeks: Szeretne robotot készíteni, amelyet a világ bármely pontjáról vezérelhet, csináljuk
DTMF és gesztusvezérelt robot kerekesszék: 7 lépés (képekkel)
DTMF és gesztusvezérelt robotkerekek: Ebben a világban számos ember fogyatékos. Életük a kerekek körül forog. Ez a projekt egy megközelítést mutat be a kerekesszék mozgásának vezérléséhez kézmozdulatok felismerése és egy okostelefon DTMF használatával