Simple Digital Band-Stop Filter by using Arduino UNO [LEP]

ในตอนสุดท้ายของบทความเกี่ยวกับกรองความถี่แบบดิจิตอลด้วยบอร์ดประมวลผล Arduino UNO จะเป็นการกรองช่วงความถี่ที่ไม่ต้องการออก (Band-Stop Filter) โดยแนวความคิดจะมาจากการกรองความถี่แบบให้ช่วงความถี่ที่ต้องการผ่าน (Band-Pass Filter) โดยเมื่อโปรแกรมคำสั่งคำนวณการกรองแบบช่วงความถี่ผ่านและได้ค่าเอาต์พุตเป็นตัวแปรนั้นแล้ว (การกรองแบบให้ช่วงความถี่ผ่านดูเพิ่มเติมในบทความที่ผ่านมา EP3 หรือ คลิกที่นี่) จากนั้นจะนำมาหาผลต่างกับสัญญาณอินพุตที่เข้ามา ซึ่งจะได้เป็นการกรองช่วงความถี่ที่ไม่ต้องการออกนั้นเอง

ดังนั้นจึงสรุปได้ว่า โปรแกรมส่วนใหญ่ของการกรองช่วงความถี่ที่ไม่ต้องการออก (Band-Stop Filter) จะเป็นโปรแกรมคำสั่งของการกรองความถี่แบบให้ช่วงความถี่ที่ต้องการผ่าน (Band-Pass Filter) ซึ่งในบทความนี้จะของยกโปรแกรมทั้งหมดมาจากบทความในตอนที่ 3 (EP3) แต่จะเพิ่มสมการคำนวณในส่วนของผลต่างระหว่างสัญญาณอินพุตที่เข้ามากับการกรองความถี่แบบให้ช่วงความถี่ผ่านเท่านั้น (float filteredBS = rawValue – filteredBP;) เพื่อให้เข้าใจโปรแกรมทั้งหมดได้ง่ายยิ่งขึ้น
/* Arduino UNO Code By : https://gemini.google.com/ Key word prompt : Digital Band-Pass Filter by using Arduino and Exsample code */ const float EMA_ALPHA_LOW = 0.09; // 0.02 กรองความถี่สูงออกไปมาก, เหลือแต่ความถี่ต่ำมากๆ const float EMA_ALPHA_HIGH = 0.4; // 0.1 กรองความถี่สูงออกไปน้อยลง, ยอมให้ความถี่สูงขึ้นมาหน่อยผ่านได้ float ema_lp_low = 0; float ema_lp_high = 0; void setup() { Serial.begin(9600); pinMode(A0, INPUT); } void loop() { // int rawValue = analogRead(A0); int rawValue = random(1,1023); // Adj Amplitude Signal Analog input int fdelay = random(1,300); // Adj Frequency Signal Analog input delay(fdelay); //------- Calc Lower Cutoff for Band-Pass ------- ema_lp_low = EMA_ALPHA_LOW * rawValue + (1 - EMA_ALPHA_LOW) * ema_lp_low; //------- Calc Upper Cutoff for Band-Pass ------- ema_lp_high = EMA_ALPHA_HIGH * rawValue + (1 - EMA_ALPHA_HIGH) * ema_lp_high; //------- Calc Band-Pass Filter ----------------- float filteredBP = ema_lp_high - ema_lp_low; //------- Calc Band-stop Filter OUT PUT --------- float filteredBS = rawValue - filteredBP; Serial.print("Raw Value: "); Serial.print(rawValue); Serial.print("\tfilteredBP: "); Serial.print(filteredBP); Serial.print("\tFiltered BS: "); Serial.println(filteredBS); }
สำหรับโปรแกรมกรองช่วงความถี่ผ่านไม่ให้ผ่าน (Band-Stop Filter) ที่แสดงข้างบน จะแบ่งออกเป็น 7 กลุ่ม ดังนี้
กลุ่มแรก จะเป็นการประกาศค่าตัวแปรต่างๆ สำหรับใช้การคำนวณในช่วงต้นๆ ของโปรแกรม โดยจะรวมทั้งการกำหนดอัตราการสื่อสารพอร์ตอนุกรม (Serial.begin(9600);) และการกำหนดฟังก์ชั่นการใช้งานขา (pinMode(A0, INPUT))
กลุ่มที่สอง จะเป็นคำสั่งสร้างสัญญาณอะนาลอกด้วยการสุ่มขึ้นมาจากการใช้คำสั่ง int rawValue = random(1,1023); ซึ่งในส่วนนี้จะกำหนดขนาดแอมปริจูดและที่คำสั่ง int fdelay = random(1,300); และ delay(fdelay); จะทำหน้าที่กำหนดความถี่ที่แตกต่างกัน ทั้งนี้เพื่อนำค่าที่สุ่มขึ้นมาได้ใช้ในการทดสอบการทำงานของโปรแกรมกรองความถี่ครั้งนี้
กลุ่มที่สาม จะเป็นโปรแกรมสมการเพื่อกรองสัญญาณความถี่ต่ำ สำหรับความถี่คัตออฟช่วงล่าง (Lower Cutoff)หรือความถี่ที่ต่ำกว่าความถี่คัตออฟนี้ให้ผ่านน้อย
กลุ่มที่สี่ จะเป็นโปรแกรมสมการเพื่อกรองสัญญาณความถี่ต่ำเช่นกัน (แต่จะกรองความถี่ที่สูงกว่า Lower Cutoff) โดยความถี่คัตออฟช่วงนี้จะเป็น (Upper Cutoff) ซึ่งความถี่ที่ต่ำกว่าความถี่คัตออฟนี้ให้ผ่านน้อยเช่นกัน
กลุ่มที่ห้า จะเป็นโปรแกรมสมการเพื่อหาผลต่างของ Upper Cutoff และ Lower Cutoff ซึ่งผลลัพธ์ที่ได้จะเป็นช่วงความถี่ที่ต้องการ (Band-Pass Filter)
กลุ่มที่หก จะเป็นโปรแกรมสมการเพื่อหาผลต่างระหว่างสัญญาณอินพุตกับผลของการกรองช่วงความถี่ผ่าน(Band-Pass Filter) ซึ่งจะเป็นผลลัพธ์ของการกรองความถี่แบบช่วงความถี่ที่ไม่ต้องการออกทางด้านเอาต์พุต (float filteredBS = rawValue – filteredBP;)
กลุ่มที่เจ็ด จะเป็นคำสั่งสำหรับแสดงผลการทำงานของโปรแกรมที่ได้จากการสมการต่างๆ โดยจะสามารถดูผลที่เกิดขึ้นที่เมนู Serial Plotter โดยจะแสดงในส่วนของสัญญาณอินพุต, สัญญาณความถี่คัตออฟช่วง (Upper Cutoff) เทียบกับสัญญาณเอาต์พุตช่วงความถี่ผ่านให้เข้าใจง่าย



ในรูปที่ 1 ถึงรูปที่ 3 แสดงผลการทดลองโปรแกรม Digital Band-Stop Filter โดยทำการเปลี่ยนค่าตัวแปร EMA_ALPHA_LOW ให้เป็น 0.01, 0.05 และ 0.08 และ EMA_ALPHA_HIGH ให้เป็น 0.1, 0.2 และ 0.3 ตามลำดับ เพื่อสังเกตผลการทดลองที่ได้ จากในรูปที่ 1 ถึงรูปที่ 3 จะเห็นรูปสัญญาณอินพุตเดิม (rawValue) จะเป็นสีเขียว, สัญญาณกรองช่วงความถี่ผ่าน (filteredBP)จะเป็นสีม่วง และสัญญาณกรองช่วงความถี่ไม่ให้ผ่าน (filteredBS) จะเป็นสีดำ โดยจะสังเกตเห็นว่าที่ค่า EMA_ALPHA_LOW เท่ากับ 0.01 สัญญาณอินพุตเมื่อเทียบกับสัญญาณเอาต์พุตจะให้การตอบสนองความถี่ในช่วงที่แคบ แต่เมื่อปรับค่า EMA_ALPHA_LOW ให้กับค่า 0.05 และ 0.08 พร้อมกับ EMA_ALPHA_HIGH เท่ากับ 0.1,0.2 และ 0.3 ตามลำดับ จะทำให้การตอบสนองช่วงความถี่ที่กว้างขึ้น ซึ่งเราสามารถปรับค่า EMA_ALPHA_LOW และ EMA_ALPHA_HIGH ให้มากหรือน้อย ตามความเหมาะสมกับการนำไปใช้งาน

ในบทความเกี่ยวกับกรองความถี่แบบดิจิตอลด้วยบอร์ดประมวลผล Arduino UNO ที่นำเสนอมาทั้ง 4 ตอนนี้ เป็นเนื้อหาในรูปแบบหนึ่งของวิธีการกรองความถี่แบบดิจิตอล (Exponentially Weighted Moving Average : EWMA) ที่ใช้ความสามารถของบอร์ดประมวลผลไม่มากนัก รวมทั้งต้องการให้เนื้อหาที่นำเสนอเป็นแนวทางเบื้องต้น ของการนำไปประยุกต์ใช้งาน นอกจากนี้ยังมีวิธีการกรองความถี่ในรูปแบบต่างๆ สำหรับผู้อ่านที่ต้องการศึกษาเพิ่มเติม (ลองใช้คำค้นหา “Type of digital filter for Arduino”) โดยแนะนำให้ใช้บอร์ดประมวลผลที่มีความสามารถที่สูงขึ้น
Reference
- https://gemini.google.com/
- https://www.norwegiancreations.com/2016/03/arduino-tutorial-simple-high-pass-band-pass-and-band-stop-filtering/
- https://github.com/MartinBloedorn/libFilter
- https://docs.simplefoc.com/low_pass_filter
- https://www.instructables.com/FIR-Filtering-for-More-Reliable-Frequency-Detectio/