Სარჩევი:
ვიდეო: DTMF დეტექტორი: 4 ნაბიჯი
2024 ავტორი: John Day | [email protected]. ბოლოს შეცვლილი: 2024-01-30 10:19
მიმოხილვა
მე შთაგონებული ვიყავი ამ მოწყობილობის ასაშენებლად ციფრული სიგნალის დამუშავების ონლაინ კურსზე საშინაო დავალებით. ეს არის DTMF დეკოდი, რომელიც განხორციელებულია Arduino UNO– სთან ერთად, ის ამოიცნობს ტელეფონის კლავიატურაზე დაჭერილ ციფრს ტონის რეჟიმში მისი წარმოქმნილი ხმით.
ნაბიჯი 1: ალგორითმის გაგება
DTMF– ში თითოეული სიმბოლო დაშიფრულია ორი სიხშირით სურათის ცხრილის მიხედვით.
მოწყობილობა იღებს მიკროფონიდან შეყვანას და ითვლის რვა სიხშირის ამპლიტუდას. ორი სიხშირე მაქსიმალური ამპლიტუდით იძლევა დაშიფრული სიმბოლოს მწკრივსა და სვეტს.
მონაცემთა მოპოვება
სპექტრის ანალიზის შესასრულებლად ნიმუშები უნდა იქნას აღებული გარკვეული პროგნოზირებადი სიხშირით. ამის მისაღწევად მე გამოვიყენე ADC რეჟიმი თავისუფალი სიზუსტით მაქსიმალური სიზუსტით (prescaler 128), რაც იძლევა შერჩევის სიჩქარეს 9615 Hz. ქვემოთ მოყვანილი კოდი გვიჩვენებს, თუ როგორ უნდა მოხდეს Arduino– ს ADC კონფიგურაცია.
void initADC () {
// ინიცირება ADC; f = (16MHz/prescaler)/13 ციკლი/კონვერტაცია ADMUX = 0; // არხი sel, right-adj, use AREF pin ADCSRA = _BV (ADEN) | // ADC ჩართვა _BV (ADSC) | // ADC დაწყება _BV (ADATE) | // ავტომატური გამშვები _BV (ADIE) | // შეწყვეტის ჩართვა _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 ჰც ADCSRB = 0; // თავისუფალი გაშვების რეჟიმი DIDR0 = _BV (0); // გამორთეთ ციფრული შეყვანა ADC pin TIMSK0 = 0; // ტაიმერი 0 გამორთულია} და შეფერხების დამმუშავებელი ასე გამოიყურება ISR (ADC_vect) {uint16_t ნიმუში = ADC; ნიმუშები [samplePos ++] = ნიმუში - 400; თუ (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // ბუფერი სავსეა, შეწყვეტა გამორთულია}}
სპექტრის ანალიზი
ნიმუშების შეგროვების შემდეგ ვიანგარიშებ სიმბოლოების კოდირების 8 სიხშირის ამპლიტუდას. მე არ მჭირდება ამის სრული FFT გაშვება, ამიტომ გამოვიყენე გოერცელის ალგორითმი.
void goertzel (uint8_t *ნიმუშები, float *სპექტრი) {
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) (ნიმუშები ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); სპექტრი [k] = გამაძლიერებელი; }}
ნაბიჯი 2: კოდი
ზემოთ მოყვანილი სურათი გვიჩვენებს ციფრის კოდირების მაგალითს, სადაც მაქსიმალური ამპლიტუდა შეესაბამება სიხშირეებს 697Hz და 1477Hz.
სრული ესკიზი შემდეგნაირად გამოიყურება
/** * კავშირები: * [Mic to Arduino] * - Out -> A0 * - Vcc -> 3.3V * - Gnd -> Gnd * - Arduino: AREF -> 3.3V * [ჩვენება Arduino] * - Vcc - > 5V * - Gnd -> Gnd * - DIN -> D11 * - CLK -> D13 * - CS -> D9 */ #მოიცავს #მოიცავს
#ჩართეთ
#განსაზღვრეთ CS_PIN 9
#განსაზღვრეთ N 256
#განსაზღვრეთ IX_LEN 8 #განსაზღვრეთ THRESHOLD 20
LEDMatrixDriver lmd (1, CS_PIN);
uint8_t ნიმუშები [N];
არასტაბილური uint16_t samplePos = 0;
მცურავი სპექტრი [IX_LEN];
// სიხშირეები [697.0, 770.0, 852.0, 941.0, 1209.0, 1336.0, 1477.0, 1633.0]
// გამოითვლება 9615Hz 256 ნიმუშზე const float cos_t [IX_LEN] PROGMEM = {0.8932243011955153, 0.8700869911087115, 0.8448535652497071, 0.8032075314806449, 0.6895405447370669, 0.6343963985, 0.6343963985, 0.6343963985, 0.63439639885, 0.63439.396393, 0.6343 çawa const float sin_t [IX_LEN] PROGMEM = {0,44961132965460654, 0,49289819222978404, 0,5349976198870972, 0,5956993044924334, 0,7242470829514669, 0,7730104533627369, 0,8314696123025451, 0,8819212643483549}
typedef სტრუქტურა {
char სიმბოლო; uint8_t ინდექსი; } ციფრი_ტი;
ციფრი_ აღმოჩენილი_დიგი;
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} };
ბაიტის შრიფტი [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, 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 () {
// ინიცირება ADC; f = (16MHz/prescaler)/13 ციკლი/კონვერტაცია ADMUX = 0; // არხი sel, right-adj, use AREF pin ADCSRA = _BV (ADEN) | // ADC ჩართვა _BV (ADSC) | // ADC დაწყება _BV (ADATE) | // ავტომატური გამშვები _BV (ADIE) | // შეწყვეტის ჩართვა _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0); // 128: 1 /13 = 9615 ჰც ADCSRB = 0; // თავისუფალი გაშვების რეჟიმი DIDR0 = _BV (0); // გამორთეთ ციფრული შეყვანა ADC pin TIMSK0 = 0; // ტაიმერი 0 გამორთულია}
void goertzel (uint8_t *ნიმუშები, float *სპექტრი) {
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) (ნიმუშები ) + a * v_1 - v_0; } re = c * v_2 - v_1; im = s * v_2; amp = sqrt (re * re + im * im); სპექტრი [k] = გამაძლიერებელი; }}
float avg (float *a, uint16_t len) {
float შედეგი =.0; for (uint16_t i = 0; i <len; i ++) {result+= a ; } დაბრუნების შედეგი / len; }
int8_t get_single_index_above_threshold (float *a, uint16_t len, float threshold) {
თუ (ბარიერი <THRESHOLD) {დაბრუნება -1; } int8_t ix = -1; for (uint16_t i = 0; i ბარიერი) {if (ix == -1) {ix = i; } else {დაბრუნება -1; }}} დაბრუნება ix; }
void dete_digit (float *spectrum) {
float avg_row = avg (სპექტრი, 4); float avg_col = avg (& სპექტრი [4], 4); int8_t row = get_single_index_above_threshold (სპექტრი, 4, avg_row); int8_t col = get_single_index_above_threshold (& spectrum [4], 4, avg_col); if (row! = -1 && col! = -1 && avg_col> 200) {dete_digit.digit = pgm_read_byte (& (მაგიდა [რიგი] [col])); აღმოჩენილი_დიგიტი.ინდექსი = pgm_read_byte (& (char_indexes [row] [col])); } else {detect_digit.digit = 0; }}
void drawSprite (ბაიტი* Sprite) {
// ნიღაბი გამოიყენება სვეტის ბიტის მისაღებად 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));
// გადაიტანეთ ნიღაბი ერთი პიქსელით მარჯვნივ
ნიღაბი = ნიღაბი >> 1; }
// სვეტის ნიღბის გადატვირთვა
ნიღაბი = B10000000; }}
void setup () {
cli (); initADC (); სეი ();
Serial.begin (115200);
lmd.setEnabled (ჭეშმარიტი); lmd.setIntensity (2); lmd. წმინდა (); lmd. ჩვენება ();
აღმოჩენილი_დიგიტი.დიგიტი = 0;
}
ხელმოუწერელი გრძელი z = 0;
ბათილი მარყუჟი () {
ხოლო (ADCSRA & _BV (ADIE)); // დაელოდეთ აუდიო შერჩევის დასრულებას goertzel (ნიმუშები, სპექტრი); detective_digit (სპექტრი);
თუ (აღმოჩენილი_დიგიტი.დიგიტი! = 0) {
drawSprite (შრიფტი [აღმოჩენილი_დიგიტი.ინდექსი]); lmd. ჩვენება (); } if (z % 5 == 0) {for (int i = 0; i <IX_LEN; i ++) {Serial.print (სპექტრი ); Serial.print ("\ t"); } Serial.println (); Serial.println ((int) found_digit.digit); } z ++;
samplePos = 0;
ADCSRA | = _BV (ADIE); // შერჩევის შეწყვეტის განახლება
}
ISR (ADC_vect) {
uint16_t ნიმუში = ADC;
ნიმუშები [samplePos ++] = ნიმუში - 400;
თუ (samplePos> = N) {ADCSRA & = ~ _BV (ADIE); // ბუფერი სავსეა, შეწყვეტა გამორთულია}}
ნაბიჯი 3: სქემა
შემდეგი კავშირები უნდა შეიქმნას:
მიკროფონი არდუინოსთან
გარეთ -> A0
Vcc -> 3.3V Gnd -> Gnd
მნიშვნელოვანია AREF- ის დაკავშირება 3.3V– თან
არდუინოს ჩვენება
Vcc -> 5V
Gnd -> Gnd DIN -> D11 CLK -> D13 CS -> D9
ნაბიჯი 4: დასკვნა
რა შეიძლება გაუმჯობესდეს აქ? მე გამოვიყენე N = 256 ნიმუში 9615Hz სიჩქარით, რომელსაც აქვს სპექტრის გაჟონვა, თუ N = 205 და მაჩვენებელი 8000Hz მაშინ სასურველი სიხშირეები ემთხვევა დისკრეტიზაციის ქსელს. ამისათვის ADC უნდა იქნას გამოყენებული ტაიმერის გადატვირთვის რეჟიმში.
გირჩევთ:
Raspberry Pi - TMD26721 ინფრაწითელი ციფრული სიახლოვის დეტექტორი Java სამეურვეო პროგრამა: 4 ნაბიჯი
Raspberry Pi-TMD26721 ინფრაწითელი ციფრული სიახლოვის დეტექტორი Java Tutorial: TMD26721 არის ინფრაწითელი ციფრული სიახლოვის დეტექტორი, რომელიც უზრუნველყოფს სიახლოვის გამოვლენის სრულ სისტემას და ციფრულ ინტერფეისის ლოგიკას ერთ 8 პინზე ზედაპირის სამონტაჟო მოდულში. სიახლოვის გამოვლენა მოიცავს სიგნალ-ხმაურის გაუმჯობესებას და სიზუსტე. პრო
წყლის დონის დეტექტორი: 7 ნაბიჯი
წყლის დონის დეტექტორი: ულტრაბგერითი სენსორი მუშაობს იმავე პრინციპებით, როგორც სარადარო სისტემა. ულტრაბგერითი სენსორი შეუძლია ელექტრო ენერგიის აკუსტიკურ ტალღებად გარდაქმნას და პირიქით. ცნობილი HC SR04 ულტრაბგერითი სენსორი წარმოქმნის ულტრაბგერითი ტალღებს 40kHz სიხშირით. ტიპიური
ზიგბის საწოლის არსებობის დეტექტორი: 8 ნაბიჯი
ზიგბის საწოლის არსებობის დეტექტორი: გარკვეული დროის განმავლობაში ვეძებდი გზას იმის დასადგენად, თუ როდის ვართ საწოლში. ეს არის ის, რომ გამოიყენოთ ეს ინფორმაცია Homeassistant– ში. ამ ინფორმაციის საშუალებით შემიძლია ავტომატიზირება ღამით შუქის ჩაქრობის მიზნით, ან მაგალითად განგაშის სისტემის გააქტიურება ჩემს სახლში
კვამლის დეტექტორი: 13 ნაბიჯი
კვამლის დეტექტორი: გამარჯობა მეგობრებო, მოდი ვნახოთ კვამლის დეტექტორის შესახებ ბევრი თქვენგანი დადიოდა სავაჭრო ცენტრებში ძირითადად თქვენ ხედავთ ამ მოწყობილობას, რომელსაც ეწოდება კვამლის დეტექტორი, ის აღმოაჩენს კვამლს და ჩართავს სპრინკლერს და ცეცხლს შეაჩერებს. მაგრამ ამ პროექტში ეს არის უმნიშვნელო ცვლილება სამაგიეროდ
IOT კვამლის დეტექტორი: განაახლეთ არსებული კვამლის დეტექტორი IOT– ით: 6 ნაბიჯი (სურათებით)
IOT კვამლის დეტექტორი: განაახლეთ არსებული კვამლის დეტექტორი IOT– ით: ავტორების სია, გამომგონებელი: Tan Siew Chin, Tan Yit Peng, Tan Wee Heng მეთვალყურე: დოქტორი ჩია კიმ სენგი მექანიკური და რობოტული ინჟინერიის განყოფილება, ელექტრო და ელექტრონული ინჟინერიის ფაკულტეტი, Universiti Tun ჰუსეინ ონნი მალაიზია. განაწილება