Indholdsfortegnelse:
Video: DTMF -detektor: 4 trin
2024 Forfatter: John Day | [email protected]. Sidst ændret: 2024-01-30 08:28
Oversigt
Jeg blev inspireret til at bygge denne enhed af en hjemmeopgave på Digital Signal Processing online kursus. Dette er en DTMF -dekoder implementeret med Arduino UNO, det registrerer et ciffer, der trykkes på et telefontastatur i tonefunktionen af den lyd, det producerer.
Trin 1: Forståelse af algoritmen
I DTMF er hvert symbol kodet med to frekvenser i henhold til tabellen på billedet.
Enheden fanger input fra mikrofonen og beregner amplituder på otte frekvenser. To frekvenser med maksimale amplituder giver en række og en kolonne med det kodede symbol.
Dataindsamling
For at udføre spektrumanalyse skal prøver fanges med en bestemt forudsigelig frekvens. For at opnå dette brugte jeg fritløbende ADC-tilstand med maksimal præcision (prescaler 128) det giver samplingshastighed 9615Hz. Koden herunder viser, hvordan du konfigurerer Arduinos ADC.
ugyldig initADC () {
// Init ADC; f = (16MHz/prescaler)/13 cyklusser/konvertering ADMUX = 0; // Kanalsel, højre-adj, brug AREF pin ADCSRA = _BV (ADEN) | // ADC aktiver _BV (ADSC) | // ADC start _BV (ADATE) | // Auto trigger _BV (ADIE) | // Afbryd aktivering _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Free-run mode DIDR0 = _BV (0); // Sluk digital input for ADC pin TIMSK0 = 0; // Timer0 off} Og interrupt handler ligner denne ISR (ADC_vect) {uint16_t sample = ADC; samples [samplePos ++] = sample - 400; hvis (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer fuld, afbryd}}
Spektrumanalyse
Efter indsamling af prøver beregner jeg amplituder på 8 frekvenser, der koder for symboler. Jeg behøver ikke at køre fuld FFT til dette, så jeg brugte 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])); flyde 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; }}
Trin 2: Koden
Billedet ovenfor viser eksemplet på kodning af ciffer 3, hvor maksimal amplitude svarer til frekvenserne 697Hz og 1477Hz.
Den komplette skitse ser således ud
/** * Tilslutninger: * [Mic til Arduino] * - Ud -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [Display til Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #include #include
#omfatte
#define CS_PIN 9
#definer N 256
#define IX_LEN 8 #define THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t prøver [N];
flygtig uint16_t samplePos = 0;
float spektrum [IX_LEN];
// Frekvenser [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// Beregnet til 9615Hz 256 prøver const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343932841636456, 0.5365 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 {
char ciffer; uint8_t indeks; } ciffer_t;
digit_t opdaget_digit;
const char tabel [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 skrifttype [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 cyklusser/konvertering ADMUX = 0; // Kanalsel, højre-adj, brug AREF pin ADCSRA = _BV (ADEN) | // ADC aktiver _BV (ADSC) | // ADC start _BV (ADATE) | // Auto trigger _BV (ADIE) | // Afbryd aktivering _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 Hz ADCSRB = 0; // Free-run mode DIDR0 = _BV (0); // Sluk digital input for ADC pin TIMSK0 = 0; // Timer0 fra
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])); flyde 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 gns. (float *a, uint16_t len) {
float resultat =.0; for (uint16_t i = 0; i <len; i ++) {resultat+= a ; } returnere resultat / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float tærskel) {
hvis (tærskel <THRESHOLD) {return -1; } int8_t ix = -1; for (uint16_t i = 0; i tærskel) {if (ix == -1) {ix = i; } else {return -1; }}} returner ix; }
void detect_digit (float *spectrum) {
float avg_row = gennemsnit (spektrum, 4); float avg_col = avg (& spektrum [4], 4); int8_t række = get_single_index_above_threshold (spektrum, 4, avg_row); int8_t col = get_single_index_above_threshold (& spektrum [4], 4, avg_col); hvis (række! = -1 && col! = -1 && avg_col> 200) {detect_digit.digit = pgm_read_byte (& (tabel [række] [col])); detekteret_digit.index = pgm_read_byte (& (char_indexes [række] [kol])); } andet {opdaget_digit.digit = 0; }}
void drawSprite (byte* sprite) {
// Masken bruges til at hente søjlebitten fra sprite række byte maske = 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 pixel til højre
maske = maske >> 1; }
// nulstil kolonnemaske
maske = B10000000; }}
ugyldig opsætning () {
cli (); initADC (); sei ();
Serial.begin (115200);
lmd.setEnabled (sand); lmd.setIntensity (2); lmd.clear (); lmd.display ();
detekteret_digit.digit = 0;
}
usigneret lang z = 0;
void loop () {
mens (ADCSRA & _BV (ADIE)); // Vent på, at lydsampling er færdig med goertzel (prøver, spektrum); detect_digit (spektrum);
hvis (opdaget_digit.digit! = 0) {
drawSprite (font [opdaget_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) opdaget_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // Genoptag prøveudtagningsafbrydelse
}
ISR (ADC_vect) {
uint16_t sample = ADC;
prøver [samplePos ++] = prøve - 400;
hvis (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // Buffer fuld, afbryd}}
Trin 3: Skemaer
Følgende forbindelser skal foretages:
Mikrofon til Arduino
Ud -> A0
Vcc -> 3.3V Gnd -> Gnd
Det er vigtigt at tilslutte AREF til 3,3V
Skærm til Arduino
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
Trin 4: Konklusion
Hvad kan forbedres her? Jeg brugte N = 256 prøver med en hastighed på 9615Hz, som har noget spektrumlækage, hvis N = 205 og hastigheden er 8000Hz, falder de ønskede frekvenser sammen med diskretiseringsgitteret. Til denne ADC bør bruges i timeroverløbstilstand.
Anbefalede:
DTMF VIDEO STREAMING ROVER: 3 trin
DTMF VIDEO STREAMING ROVER: hej efter min LINUX TERMINAL CONTROLLED ROVER og WIFI DTMF PC CONTROLLED ROBOT dette er min tredje robot. og ligesom andre to her brugte jeg heller ikke nogen mikrokontroller eller programmering til at holde det enkelt og let at lave. det streamer også live video over wifi
Sådan laver du en simpel DTMF (tone) telefonliniedekoder: 3 trin
Sådan laves en simpel DTMF (tone) telefonliniedekoder: Dette er et simpelt projekt, der lader dig afkode DTMF -signaler på stort set enhver telefonlinje. I denne vejledning bruger vi dekoderen MT8870D. Vi bruger en forudbygget tonedekoder, fordi tro mig, det er en smerte bagpå at prøve at gøre det med
WIFI DTMF ROBOT: 5 trin
WIFI DTMF ROBOT: hej i denne vejledning, jeg vil vise dig, hvordan du kan lave en pc -styret rover uden at bruge mikrocontroller, dette betyder i dette projekt, at ingen kode på højt niveau er involveret, du har bare brug for grundlæggende viden om html -sidelavning, det er det. Du kan se fuld
Sådan laver du en mobilstyret robot - DTMF -baseret - Uden mikrokontroller og programmering - Kontrol fra hvor som helst i verden - RoboGeeks: 15 trin
Sådan laver du en mobilstyret robot | DTMF -baseret | Uden mikrokontroller og programmering | Kontrol fra hvor som helst i verden | RoboGeeks: Vil du lave en robot, der kan styres overalt i verden, lad os gøre det
DTMF og gestusstyret robotkørestol: 7 trin (med billeder)
DTMF og gestusstyret robotkørestol: I denne verden er en række mennesker handicappede. Deres liv kredser om hjul. Dette projekt præsenterer en tilgang til styring af kørestolsbevægelser ved hjælp af håndbevægelsesgenkendelse og DTMF fra en smartphone