Innholdsfortegnelse:
Video: DTMF -detektor: 4 trinn
2024 Forfatter: John Day | [email protected]. Sist endret: 2024-01-30 11:24
Oversikt
Jeg ble inspirert til å bygge denne enheten av et hjemmeopgave på Digital Signal Processing online -kurs. Dette er en DTMF -dekoder implementert med Arduino UNO, den oppdager et siffer som trykkes på et tastatur på telefonen i tonemodus av lyden den produserer.
Trinn 1: Forstå algoritmen
I DTMF er hvert symbol kodet med to frekvenser i henhold til tabellen på bildet.
Enheten fanger inngang fra mikrofonen og beregner amplituder på åtte frekvenser. To frekvenser med maksimale amplituder gir en rad og en kolonne med det kodede symbolet.
Datainnsamling
For å utføre spektrumanalyse bør prøver tas med en viss forutsigbar frekvens. For å oppnå dette brukte jeg frikjør ADC-modus med maksimal presisjon (prescaler 128) det gir samplingsfrekvens 9615Hz. Koden nedenfor viser hvordan du konfigurerer Arduinos ADC.
ugyldig initADC () {
// Init ADC; f = (16MHz/prescaler)/13 sykluser/konvertering ADMUX = 0; // Channel sel, right-adj, use AREF pin ADCSRA = _BV (ADEN) | // ADC aktiver _BV (ADSC) | // ADC start _BV (ADATE) | // Autotrigger _BV (ADIE) | // Avbryt aktiver _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Friløpsmodus DIDR0 = _BV (0); // Slå av digital inngang for ADC pin TIMSK0 = 0; // Timer0 off} Og avbryterbehandleren ser slik ut: ISR (ADC_vect) {uint16_t sample = ADC; samples [samplePos ++] = sample - 400; hvis (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer full, avbryt}}
Spektrumanalyse
Etter å ha samlet prøver beregner jeg amplituder på 8 frekvenser som koder for symboler. Jeg trenger ikke å kjøre full FFT for dette, så jeg brukte Goertzels algoritme.
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])); flyte 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) (prøver ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektrum [k] = amp; }}
Trinn 2: Koden
Bildet ovenfor viser eksemplet på koding av siffer 3 hvor maksimal amplitude tilsvarer frekvensene 697Hz og 1477Hz.
Hele skissen ser slik ut
/** * Tilkoblinger: * [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
#inkludere
#define CS_PIN 9
#define N 256
#define IX_LEN 8 #define THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t prøver [N];
flyktig uint16_t samplePos = 0;
flytespekter [IX_LEN];
// Frekvenser [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// Beregnet for 9615Hz 256 sampler const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343932841636456, 0.5555; const float sin_t [IX_LEN] PROGMEM = {0.44961132965460654, 0.49289819222978404, 0.5349976198870972, 0.5956993044924334, 0.7242470829514669, 0.7730104533627369, 0.8314696123025451, 0.88
typedef struct {
røye siffer; uint8_t indeks; } digit_t;
digit_t detect_digit;
const char tabell [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 skrift [16] [8] = {
{0x00, 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38}, // 0 {0x04, 0x0c, 0x14, 0x24, 0x04, 0x04, 0x04, 0x04}, // 1 {0x00, 0x30, 0x48, 0x0, 0x04, 0x38, 0x40, 0x7c}, // 2 {0x00, 0x38, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38}, // 3 {0x00, 0x04, 0x0c, 0x14, 0x24, 0x7e, 0x04, 0x0 }, // 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} // *};
ugyldig initADC () {
// Init ADC; f = (16MHz/prescaler)/13 sykluser/konvertering ADMUX = 0; // Kanalsel, høyre-adj, bruk AREF-pin ADCSRA = _BV (ADEN) | // ADC aktiver _BV (ADSC) | // ADC start _BV (ADATE) | // Autotrigger _BV (ADIE) | // Avbryt aktiver _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Friløpsmodus DIDR0 = _BV (0); // Slå av digital inngang 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])); flyte 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) (prøver ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); spektrum [k] = amp; }}
float avg (float *a, uint16_t len) {
flyte resultat =.0; for (uint16_t i = 0; i <len; i ++) {resultat+= a ; } returresultat / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float terskel) {
if (terskel <THRESHOLD) {return -1; } int8_t ix = -1; for (uint16_t i = 0; i terskel) {if (ix == -1) {ix = i; } annet {retur -1; }}} returner ix; }
void detect_digit (float *spectrum) {
float avg_row = avg (spektrum, 4); float avg_col = avg (& spectrum [4], 4); int8_t rad = get_single_index_above_threshold (spektrum, 4, avg_row); int8_t col = get_single_index_above_threshold (& spectrum [4], 4, avg_col); hvis (rad! = -1 && col! = -1 && avg_col> 200) {detect_digit.digit = pgm_read_byte (& (tabell [rad] [col])); detect_digit.index = pgm_read_byte (& (char_indexes [rad] [kol])); } annet {detect_digit.digit = 0; }}
void drawSprite (byte* sprite) {
// Masken brukes til å hente søylebiten fra 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));
// skift masken med en piksel til høyre
maske = maske >> 1; }
// tilbakestill kolonnemaske
maske = B10000000; }}
ugyldig oppsett () {
cli (); initADC (); sei ();
Serial.begin (115200);
lmd.setEnabled (true); lmd.setIntensity (2); lmd.clear (); lmd.display ();
detect_digit.digit = 0;
}
usignert lang z = 0;
void loop () {
mens (ADCSRA & _BV (ADIE)); // Vent på at lydsampling er ferdig med goertzel (prøver, spektrum); detect_digit (spektrum);
hvis (detect_digit.digit! = 0) {
drawSprite (font [detect_digit.index]); lmd.display (); } hvis (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (spektrum ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) detect_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // Fortsett prøvetaking avbryt
}
ISR (ADC_vect) {
uint16_t sample = ADC;
prøver [samplePos ++] = sample - 400;
hvis (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer full, avbryt}}
Trinn 3: Skjemaer
Følgende tilkoblinger bør gjøres:
Mikrofon til Arduino
Ut -> A0
Vcc -> 3.3V Gnd -> Gnd
Det er viktig å koble AREF til 3,3V
Display til Arduino
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
Trinn 4: Konklusjon
Hva kan forbedres her? Jeg brukte N = 256 prøver med en hastighet på 9615Hz som har noe spektrumlekkasje, hvis N = 205 og frekvensen er 8000Hz, faller de ønskede frekvensene sammen med diskretiseringsnettet. For at ADC skal brukes i timeroverløpsmodus.
Anbefalt:
DTMF VIDEO STREAMING ROVER: 3 trinn
DTMF VIDEO STREAMING ROVER: hei etter min LINUX TERMINAL CONTROLLED ROVER og WIFI DTMF PC CONTROLLED ROBOT dette er min tredje robot. og som andre to her, brukte jeg ikke noen mikrokontroller eller programmering for å holde det enkelt og enkelt å lage. det streamer også live video over wifi
Hvordan lage en enkel DTMF (tone) telefonlinjedekoder: 3 trinn
Hvordan lage en enkel DTMF (tone) telefonlinjedekoder: Dette er et enkelt prosjekt som lar deg dekode DTMF -signaler på i utgangspunktet hvilken som helst telefonlinje. I denne opplæringen bruker vi dekoderen MT8870D. Vi bruker en forhåndsbygd tonedekoder fordi, tro meg, det er vondt bak å prøve å gjøre det med
WIFI DTMF ROBOT: 5 trinn
WIFI DTMF ROBOT: hei i denne opplæringen jeg skal vise deg hvordan du kan lage en pc -kontrollert rover uten å bruke mikrokontroller, dette betyr at i dette prosjektet er ingen kode på høyt nivå involvert, du trenger bare grunnleggende kunnskap om html -sideopprettelse. kan se full
Hvordan lage en mobilstyrt robot - DTMF -basert - Uten mikrokontroller og programmering - Kontroll fra hvor som helst i verden - RoboGeeks: 15 trinn
Hvordan lage en mobilstyrt robot | DTMF -basert | Uten mikrokontroller og programmering | Kontroll fra hvor som helst i verden | RoboGeeks: Vil du lage en robot som kan kontrolleres fra hvor som helst i verden, la oss gjøre det
DTMF og bevegelseskontrollert robotrullestol: 7 trinn (med bilder)
DTMF og bevegelseskontrollert robotrullestol: I denne verden er en rekke mennesker funksjonshemmede. Livet deres dreier seg om hjul. Dette prosjektet presenterer en tilnærming for å kontrollere rullestolbevegelser ved hjelp av håndbevegelsesgjenkjenning og DTMF av en smarttelefon