Სარჩევი:

EasyFFT: სწრაფი ფურიეს ტრანსფორმაცია (FFT) არდუინოსთვის: 6 ნაბიჯი
EasyFFT: სწრაფი ფურიეს ტრანსფორმაცია (FFT) არდუინოსთვის: 6 ნაბიჯი

ვიდეო: EasyFFT: სწრაფი ფურიეს ტრანსფორმაცია (FFT) არდუინოსთვის: 6 ნაბიჯი

ვიდეო: EasyFFT: სწრაფი ფურიეს ტრანსფორმაცია (FFT) არდუინოსთვის: 6 ნაბიჯი
ვიდეო: აღმოაჩინეთ, თუ როგორ ახდენს ჯენი ტაილერი რევოლუციას ჯანდაცვის ინდუსტრიაში! 2024, ივნისი
Anonim
Image
Image

დატყვევებული სიგნალიდან სიხშირის გაზომვა შეიძლება იყოს რთული ამოცანა, განსაკუთრებით არდუინოზე, რადგან მას აქვს დაბალი გამოთვლითი ძალა. არსებობს მეთოდები ნულოვანი გადაკვეთის დასაფიქსირებლად, სადაც სიხშირე აღირიცხება რამდენჯერ გადალახავს სიგნალი ნულოვან ხაზებს მოცემულ დროში. ასეთი მეთოდი შეიძლება არ იმუშაოს, როდესაც სიგნალი არის სხვადასხვა სიხშირის კომბინაცია.

ეს რატომღაც ძნელია კოდირება, თუ არ ხარ ასეთი ფონიდან. ვინაიდან მეკარეა, ეს კოდი შეიძლება იყოს ძალიან სასარგებლო მუსიკასთან, სიგნალის ანალიზთან დაკავშირებული სხვადასხვა პროექტებისთვის. ამ პროექტის მოტივი იყო მოემზადებინა კოდი, რომლის განხორციელებაც ადვილია არდუინოზე, მის ფონზე მოხვედრის გარეშე.

ეს პროექტი არ განმარტავს FFT– ს მუშაობას, არამედ განმარტავს FFT ფუნქციის გამოყენებას. იგივე პროცესი ასევე ახსნილია თანდართულ ვიდეოში.

თუ თქვენ დაინტერესებული ხართ მხოლოდ კოდის გამოყენებით და არა მისი ახსნით. შეგიძლიათ პირდაპირ გადახვიდეთ მე –3 საფეხურზე.

ნაბიჯი 1: შესავალი სიხშირის გარდაქმნაში

შესავალი სიხშირის გარდაქმნაში
შესავალი სიხშირის გარდაქმნაში
შესავალი სიხშირის გარდაქმნაში
შესავალი სიხშირის გარდაქმნაში

ნებისმიერი სიგნალი შეიძლება შედგებოდეს სხვადასხვა სინუსოიდული ტალღების კომბინაციისგან. ასე რომ, დროზე დაფუძნებული ნებისმიერი სიგნალი ასევე შეიძლება ნაჩვენები იყოს, როგორც სხვადასხვა ამპლიტუდის სინუსების კომბინაცია.

მე შევეცადე აეხსნა DFT (ფურიეს დისკრეტული გარდაქმნა) მუშაობის ერთ – ერთი წინა ინსტრუქცია (https://www.instructables.com/id/Arduino-Frequency…). ეს მეთოდები ძალიან ნელია ნებისმიერი რეალურ დროში გამოყენებისთვის. რაც მას თითქმის უსარგებლოს ხდის.

სურათზე ნაჩვენებია სიგნალი, რომელიც არის ორი სიხშირის f2 და f5 კომბინაცია. ეს სიგნალი მრავლდება f1– დან f5 მნიშვნელობების საცდელი სინუსური ტალღებით.

მათემატიკურად შეიძლება ნაჩვენები იყოს, რომ განსხვავებული ჰარმონიული მონაცემთა ნაკრების გამრავლების ჯამი სხვადასხვა სიხშირით ნულის ტოლია (მონაცემთა უფრო მეტმა რაოდენობამ შეიძლება გამოიწვიოს ბატარეის შედეგი). ჩვენს შემთხვევაში, თუ ამ ორ გამრავლების სიხშირეს აქვს იგივე (ან ძალიან ახლო) სიხშირე, გამრავლების ჯამი არის არა ნული რიცხვი.

ასე რომ, თუ ჩვენი სიგნალი გამრავლებულია f1- ით, გამრავლება იქნება ნული (რეალურ გამოყენებისთვის ნულთან ახლოს). იგივე ეხება f3, f4. თუმცა, მნიშვნელობისთვის, f2 და f5 გამომავალი არ იქნება ნული, მაგრამ მნიშვნელოვნად უფრო მაღალი ვიდრე დანარჩენი მნიშვნელობები.

აქ სიგნალი შემოწმებულია 5 სიხშირით, ამიტომ სიგნალი უნდა გამრავლდეს ხუთ სიხშირეზე. ასეთი ინტენსიური გაანგარიშება უფრო მეტ დროს მოითხოვს. მათემატიკურად ნაჩვენებია, რომ N რაოდენობის ნიმუშისთვის საჭიროა N*N კომპლექსური გამრავლება.

ნაბიჯი 2: სწრაფი ფურიეს ტრანსფორმაცია

DFT– ის გამოთვლის უფრო სწრაფი შესაქმნელად FFT ალგორითმი შეიმუშავეს ჯეიმს ქულმა და ჯონ ტუკიმ. ეს ალგორითმი ასევე განიხილება, როგორც მე -20 საუკუნის ერთ -ერთი ყველაზე მნიშვნელოვანი ალგორითმი. ის ყოფს სიგნალს უცნაურ და თანმიმდევრულ ნაწილად, რაც ამცირებს საჭირო გამოთვლებს. მისი გამოყენებით მთლიანი საჭირო კომპლექსური გამრავლება შეიძლება შემცირდეს NlogN- მდე. რაც მნიშვნელოვანი გაუმჯობესებაა.

თქვენ შეგიძლიათ მიუთითოთ ქვემოთ მოცემული ცნობები, რომლებიც მე მოვიხსენიე კოდის წერისას FFT მათემატიკის დეტალური გაგებისთვის:

1.

2.

3.

4.

ნაბიჯი 3: კოდის ახსნა

1. სწრაფი სინუსი და კოსინუსი:

გამოთვლა FFT იღებს მნიშვნელობას სხვადასხვა სინუსისა და კოსინუსის მრავალჯერ. Arduino– ს ჩამონტაჟებული ფუნქცია არ არის საკმარისად სწრაფი და საჭირო დროის კარგ მნიშვნელობას ატარებს. რაც კოდს მნიშვნელოვნად ანელებს (აორმაგებს დროს 64 ნიმუშზე). ამ საკითხის საპირისპიროდ სინუსის მნიშვნელობა 0 -დან 90 გრადუსამდე ინახება 255 -ის ჯერადად. ამით აღმოიფხვრება რიცხვების შენახვის აუცილებლობა float– ის სახით და შეგვიძლია მისი შენახვა როგორც ბაიტი, რომელიც არდუინოს 1/4 ადგილს იკავებს. Sine_data საჭიროებს ჩასვას კოდის თავში, რომ გამოცხადდეს გლობალურ ცვლადად.

Sine_data– ს გარდა, მასივი სახელწოდებით f_peaks გამოცხადებულია გლობალურ ცვლადად. FFT ფუნქციის ყოველი გაშვების შემდეგ ეს მასივი განახლდება. სადაც f_peaks [0] არის ყველაზე დომინანტური სიხშირე და შემდგომი მნიშვნელობები კლებადობით.

ბაიტი sine_data [91] = {0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, 223, 225, 227, 229, 239, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255}; float f_peaks [5];

ვინაიდან ჩვენ შენახული გვაქვს სინუსის მნიშვნელობა 0 -დან 90 გრადუსამდე, ნებისმიერი სინუსის ან კოსინუსის ღირებულება შეიძლება გამოითვალოს. ქვემოთ მოცემულია რიცხვის პირველი რაუნდი ნულოვან ათეულამდე და დააბრუნეთ მნიშვნელობა შენახული მონაცემებიდან. ამ მეთოდს სჭირდება მხოლოდ ერთი მცურავი განყოფილება. ეს შეიძლება კიდევ უფრო შემცირდეს სინუსების მნიშვნელობების პირდაპირ შენახვით (არა 255 მრავალჯერადი). მაგრამ ეს ჭამს მეხსიერებას არდუინოზე.

ზემოაღნიშნული პროცედურის გამოყენება ამცირებს სიზუსტეს, მაგრამ აუმჯობესებს სიჩქარეს. 64 ქულისთვის ის იძლევა 8ms უპირატესობას და 128 ქულისთვის უპირატესობას ანიჭებს 20ms.

ნაბიჯი 4: კოდის ახსნა: FFT ფუნქცია

FFT შეიძლება შესრულდეს მხოლოდ 2, 4, 8, 16, 32, 64 და ასე შემდეგ. თუ მნიშვნელობა არ არის 2^n, მაშინ ის მიიღებს ღირებულების ქვედა მხარეს. მაგალითად, თუ ჩვენ ვირჩევთ ნიმუშის ზომას 70, ის მხოლოდ პირველ 64 ნიმუშს განიხილავს და დანარჩენს გამოტოვებს.

ყოველთვის რეკომენდირებულია ნიმუშის ზომა 2^n. რომელიც შეიძლება იყოს:

2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …

ორი მცურავი out_r და out_im მიიღებს დიდი რაოდენობით მეხსიერებას. Arduino– სთვის ნანო არ იმუშავებს 128 – ზე მეტ (და ზოგიერთ შემთხვევაში 128 – ზე) ნიმუშზე არსებული მეხსიერების არარსებობის გამო.

ხელმოუწერელი int მონაცემები [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

int a, c1, f, o, x; a = N; for (int i = 0; i <12; i ++) // დონის გამოთვლა {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // შეყვანის თანმიმდევრობა float out_r [data [o] = {}; // ტრანსფორმაციის რეალური ნაწილი float out_im [data [o] = {}; // გარდასახვის წარმოსახვითი ნაწილი

შემდგომი ნაკადი შემდეგია:

1. კოდი წარმოქმნის ოდნავ შეცვლილ წესრიგს მოცემული ნიმუშის ზომისათვის (დეტალები ბიტის უკუქცევის შესახებ მითითებებზე: ნაბიჯი 2)

2. შეყვანილი მონაცემები შეკვეთილი გენერირებული შეკვეთის მიხედვით, 3. შესრულებულია FFT

4. გამოთვლილი კომპლექსური რიცხვის ამპლიტუდა, 5. მწვერვალები გამოვლენილი და მოწესრიგებულია კლებადობით

6. შედეგებზე წვდომა შესაძლებელია f_peaks– დან.

[სხვა მონაცემებზე წვდომისათვის (გარდა პიკის სიხშირისა) კოდი უნდა შეიცვალოს ისე, რომ ადგილობრივი ცვლადი იყოს გადაწერილი წინასწარ განსაზღვრულ გლობალურ ცვლადზე]

ნაბიჯი 5: კოდის ტესტირება

კოდის ტესტირება
კოდის ტესტირება
კოდის ტესტირება
კოდის ტესტირება

სამკუთხედის ტალღის ნიმუში მოცემულია შეყვანის სახით. ამ ტალღისთვის შერჩევის სიხშირეა 10 ჰც და თავად ტალღის სიხშირე არის 1.25 ჰერცი.

როგორც ნაჩვენებია ნედლეული გამომავალიდან, მნიშვნელობა შეესაბამება Scilab– ის მიერ გამოთვლილ FFT– ს. თუმცა, ეს მნიშვნელობები არ არის ზუსტად იგივე, რაც ჩვენ დაბალი სიზუსტით, მაგრამ უფრო სწრაფი სინუსური ტალღა.

გამომავალი სიხშირის მასივის სიხშირეა 1.25 და 3.75. არ არის აუცილებელი ზუსტი მნიშვნელობის მიღება ყოველ ჯერზე. როგორც წესი, ამ რიცხვებს სიხშირის ურნები ეწოდება. ასე რომ გამომავალი მნიშვნელობა შეიძლება იყოს სადმე განსაზღვრულ ყუთებში.

სიჩქარე:

არდუინო ნანოსთვის საჭიროა:

16 ქულა: 4 ms32 ქულა: 10 ms 64 ქულა: 26 ms 128 ქულა: 53 ms

ნაბიჯი 6: დასკვნა

ეს FFT კოდი შეიძლება გამოყენებულ იქნას რეალურ დროში პროგრამებში. რადგან გაანგარიშების დასრულებას დაახლოებით 30 ms სჭირდება. თუმცა, მისი გარჩევადობა შეზღუდულია რიგი ნიმუშებით. ნიმუშის რაოდენობა შეზღუდულია არდუინოს მეხსიერებით. Arduino Mega– ს ან სხვა უმაღლესი ხარისხის დაფის გამოყენებით შესაძლებელია სიზუსტის გაუმჯობესება.

თუ თქვენ გაქვთ რაიმე შეკითხვა, წინადადება ან შესწორება, მოგერიდებათ კომენტარის გაკეთება.

განახლება (2/5/21)

განახლებები: // ----------------------------- FFT ფუნქცია --------------- ---------------------------------- // float FFT (int in , int N, float Frequency)

N ტიპის მონაცემები შეიცვალა მთელი რიცხვით (არსებული ბაიტი) 255 ნიმუშის ზომის მხარდასაჭერად. თუ ნიმუშის ზომაა <= 128, უნდა იქნას გამოყენებული მონაცემთა ბაიტის ტიპი.

გირჩევთ: