ดิว.นินจา

ดิว.นินจา

Sunday, December 16, 2018

Topic: เรียนรู้ตัวกรองแบบดิจิทัลบน ESP8266 และ NETPIE

ในปัจจุบันอุปกรณ์ที่เป็นแบบแอนะล็อกทั้งในชีวิตประจำวัน ด้านการแพทย์ ในภาคอุตสาหกรรม และหลายสาขาวิชาเริ่มเหลือน้อยลงเนื่องจากข้อด้อยหลายประการเมื่อเทียบกับระบบดิจิทัลที่มาแทนที่ ตัวกรอง (filters) เป็นตัวอย่างหนึ่งที่ในอดีตสร้างจากอุปกรณ์อิเล็กทรอนิกส์ เช่นตัวต้านทาน ตัวเก็บประจุ ตัวเหนี่ยวนำ ออปแอมป์ ปัญหาหลักที่เกิดขึ้นคือ วงจรจะกินพื้นที่แผ่นวงจรพิมพ์ตามขนาดและจำนวนของอุปกรณ์ หากต้องการเปลี่ยนโครงสร้างต้องออกแบบบอร์ดและลงอุปกรณ์ใหม่ บางครั้งหาค่าอุปกรณ์ที่คำนวณได้ไม่มีขาย อุปกรณ์มีการแปรค่าตามกาลเวลาและอุณหภูมิ การปรับความถี่คัทออฟต้องใช้อุปกรณ์แบบปรับค่าได้ซึ่งมีปัญหาเมื่อหน้าสัมผัสสกปรก แตกต่างจากอัลกอริทึมที่เป็นซอฟต์แวร์รันบนตัวประมวลผลที่มีความยืดหยุ่นมากกว่า และขจัดปัญหาต่างๆ ของระบบแอนะล็อกที่กล่าวถึงมา ในบทความนี้เราจะมาเรียนรู้การสร้างตัวกรองแบบความถี่ต่ำผ่าน (Low Pass Filter) หรือเรียกย่อว่า LPF โดยสามารถปรับความถี่คัทออฟ (cutoff frequency) ได้โดยคำสั่ง และเชื่อมต่อกับ NETPIE เพื่อปรับค่าได้จากระยะไกล นอกจากนั้นยังสร้างสัญญาณรบกวนขึ้นในโปรแกรมเพื่อศึกษาการทำงานของตัวกรอง

หมายเหตุ : เนื้อหาในบทความนี้เริ่มต้นจากการบรรยายหัวข้อ "Case Study: LTI Dynamical System Implementation" ในการฝึกอบรม NETPIE Train the Trainer วันที่ 7 พฤศจิกายน 2561 ณ โรงแรมแลงคาสเตอร์

LPF เป็นตัวกรองที่นิยมใช้ในการขจัดสัญญาณรบกวนที่มีความถี่สูงกว่าแบนด์วิดท์ของระบบ ย่านที่ยอมให้ผ่านและย่านที่ลดทอนกำหนดโดยความถี่คัทออฟ LPF ที่ไม่ต้องการขยายสัญญาณ (passive) สามารถสร้างได้โดยใช้วงจรตัวต้านทานและตัวเก็บประจุดังแสดงในรูปที่ 1

รูปที่ 1 วงจร LPF สร้างโดยอุปกรณ์ RC

ถึงแม้ว่าจะใช้อุปกรณ์จำนวนน้อยและหาได้ง่าย แต่ก็ยังมีข้อเสียดังที่ได้กล่าวข้างต้น ความถี่คัทออฟของ LPF นิยามได้ว่าเป็นความถี่ที่ขนาดของเอาต์พุตลดลงเหลือ 0.707 หรือ -3 dB (รูปที่ 2)

รูปที่ 2 ความถี่คัทออฟของ LPF

จากวงจร RC ในรูปที่ 1 สามารถเลือกความถี่คัทออฟจากค่าอุปกรณ์ตามความสัมพันธ์

(1)

ฟังก์ชันถ่ายโอนในระบบเวลาต่อเนื่องของ LPF เท่ากับ

(2)

รูปที่ 3 ได้จากการจำลองบนซอฟต์แวร์ Scilab แสดงการขจัดสัญญาณรบกวนของ LPF กราฟด้านบนแสดงสัญญาณที่ต้องการย่านความถี่ต่ำถูกรบกวนโดยสัญญาณความถี่สูงกว่า กราฟด้านล่างคือเอาต์พุตของ LPF โดยจะเห็นว่าสัญญาณความถี่สูงถูกลดทอนลงจนเหลือขนาดเล็กมาก

รูปที่ 3 การจำลองการทำงานของ LPF

ขั้นตอนการแปลง LPF เป็นอัลกอริทึมจะไม่แตกต่างจากระบบเชิงเส้นที่ไม่แปรตามเวลา (Linear Time Invariant หรือ LTI) ทั่วไป เริ่มโดยการประมาณค่าฟังก์ชันถ่ายโอนเวลาต่อเนื่องของ LPF โดยฟังก์ชันถ่ายโอนแบบดีสครีต และแปลงเป็นสมการผลต่างเพื่ออิมพลิเมนต์ รูปที่ 4 แสดงการแปลงฟังก์ชันถ่ายโอนของ LPF ตามสมการ (2) เป็นอัลกอริทึมโดยใช้การแปลงเชิงเส้นคู่ (Bilinear transformation) สังเกตว่าการแปลงจะเป็นฟังก์ชันของคาบเวลา T ดังนั้นจะต้องอิมพลิเมนต์ LPF โดยใช้ไทเมอร์เพื่อสามารถกำหนดค่าคาบเวลาการประมวลผลให้ตรงกัน

รูปที่ 4 การแปลงฟังก์ชันถ่ายโอน LPF เป็นอัลกอริทึม

LPF แบบออฟไลน์

เพื่อทดสอบการทำงานของ LPF ขั้นพื้นฐาน ในเบื้องต้นจะอิมพลิเมนต์โดยสั่งงานและแสดงผลผ่านพอร์ตอนุกรม สมมุติว่าสัญญาณที่อ่านจากขาแอนะล็อก A0 คือข้อมูลจากเซนเซอร์ที่ต้องการเก็บ ในการทดลองจะไม่ต้องต่อเซนเซอร์ใดๆ แต่จะแปรค่าแรงดันโดยตัวต้านทาน VR อย่างช้าๆ หรือปล่อยไว้คงที่ ดังนั้นข้อมูลจะเป็นสัญญาณความถี่ต่ำ

สำหรับสัญญาณรบกวนจะสร้างขึ้นเป็นรูปคลื่นไซน์ โดยความถี่สามารถปรับได้ในช่วง 0.1 – 10 Hz และขนาดในช่วง 1-500 วิธีการสร้างจะเขียนเป็นฟังก์ชัน


float gensin(void)   // generate sin wave with magitude=sinmag and frequency = sinfreq
{
  float sinval = sinmag*sin(radangle); 
  radangle+=sinstep;
  if (radangle>=twopi)radangle = 0;
  return sinval;  
}

ที่จะถูกเรียกโดย loop() ตามคาบเวลาที่กำหนดโดย


delay(loopperiod);

ตัวแปร loopperiod สามารถกำหนดได้โดยผู้ใช้ ผลคือสัญญาณรบกวนที่สามารถปรับความถี่ได้ ซึ่งจะถูกรวมเข้ากับข้อมูลที่อ่านจากอินพุตแอนะล็อก


cleanvalue = analogRead(A0);
filterin=cleanvalue + gensin();     // contaminated by sin-wave noise

ตัวแปร filterin จะเป็นอินพุตของตัวกรองที่อิมพลิเมนต์บนไทเมอร์


void dFilter(void *pArg) {   // digital filter algorithm
  if (filtertype == NOFILTER) {  // just passed signal through
    filterout = filterin;
  }
  else if (filtertype == LPF)   {
    y1_LPF = filterout;
    u1_LPF = u0_LPF;
    u0_LPF = filterin;
    filterout = a1_LPF*y1_LPF + b0_LPF*u0_LPF + b1_LPF*u1_LPF;
  }
  // absolute error computation
  for (idx=9; idx<0; idx--)
    e[idx]=e[idx-1];
  e[0] = abs(cleanvalue - filterout);
  abserror = 0;
  for (idx=0; idx<10; idx++) 
    abserror += e[idx];
  abserror/=10;
}

โดยมีตัวแปร filtertype เป็นตัวเลือกว่าจะใช้ตัวกรองหรือไม่ ด้านล่างของฟังก์ชันเป็นการคำนวณค่า absolute error เฉลี่ย 10 ค่าสุดท้าย ตั้งค่าคาบเวลาของตัวกรองไว้ที่ 10 มิลลิวินาที

การคำนวณค่าสัมประสิทธิ์จะเขียนไว้ในฟังก์ชันต่างหาก


void dFilter_init(void)   {   // initialize LPF and NOTCH filters
  // for LPF filter
  RC = 1/(twopi*lpf_cutoff_freq);
  float x = 2*RC+T;
  a1_LPF = (2*RC - T)/x;
  b0_LPF = T/x;
  b1_LPF = T/x;
}

ซึ่งจะถูกเรียกทุกครั้งที่ผู้ใช้เปลี่ยนค่าความถี่คัทออฟ

ค่าความถี่สัญญาณรบกวน ความถี่คัทออฟ สถานะการใช้ตัวกรอง และค่า error จะถูกแสดงผลบน OLED และเพื่อการสังเกตการรบกวนด้วยตาเปล่า จะให้เอาต์พุตของตัวกรองถูกส่งออกที่ขา D5 เพื่อขับ LED เมื่อสัญญาณรบกวนไม่ถูกลดทอน จะเห็นการแปรความสว่างของ LED ตามความถี่ของสัญญาณรบกวนอย่างชัดเจน

สำหรับการรับคำสั่งจะใช้ฟังก์ชัน cmdInt() เหมือนเช่นเคย อิมพลิเมนต์คำสั่งดังนี้

  • sinfreq=x : ปรับความถี่ของสัญญาณรบกวน (0.1 – 10 Hz)
  • sinmag=x : ปรับขนาดสัญญาณรบกวน (1- 500 หน่วย)
  • lpfcutoff=x : ปรับความถี่คัทออฟ (0.01 – 100 Hz)
  • filter=0/1 : เลือกใช้ตัวกรองหรือไม่ใช้ 0 = OFF, 1 = ON
  • dataout=0/1/2 : เลือกการส่งข้อมูลออกพอร์ตอนุกรม
    • 0 : ไม่ส่งค่าใดๆ ออก
    • 1 : ส่งค่าเอาต์พุตของตัวกรอง
    • 2 : ส่งค่า average error (เฉลี่ยค่า absolute error 10 ค่าสุดท้าย)

ฮาร์ดแวร์ที่ใช้ทดสอบ

สามารถใช้ต้นแบบบอร์ด IGR ที่สร้างขึ้นสำหรับฝึกอบรม เพราะมีอุปกรณ์ที่ต้องการครบ คือ VR, LED และ OLED เปิดโปรแกรม dfilter.ino คอมไพล์และโหลดลงบน NodeMCU จะเห็นการแสดงผลบน OLED ดังแสดงในรูปที่ 5 ค่าโดยปริยายกำหนดความถี่สัญญาณรบกวน 5 Hz ความถี่คัทออฟของ LPF 1 Hz และปิดการใช้ตัวกรอง ดังนั้นที่ LED จะเห็นผลกระทบจากสัญญาณรบกวนค่อนข้างชัดเจน โดยแสงจะหรี่และสว่างตามความถี่ของสัญญาณรบกวนรูปคลื่นซายน์

รูปที่ 5 การทดสอบบนบอร์ดต้นแบบ IGR

ค่าโดยปริยายในช่วงเริ่มต้นจะปิดการส่งเอาต์พุตออกพอร์ตอนุกรม ทดลองใช้คำสั่ง


dataout = 1

และเปิด Serial Plotter เพื่อดูสัญญาณที่ถูกรบกวนเมื่อยังไม่ใช้ตัวกรอง ทดลองปรับ VR อย่างช้าๆ จะเห็นกราฟลักษณะดังรูปที่ 6

รูปที่ 6 เอาต์พุตที่ถูกรบกวนอย่างมากเมื่อไม่ใช้ตัวกรอง

หากต้องการดูค่า absolute error เฉลี่ย 10 จุดสุดท้าย ปิด Serial Plotter เปิด Serial Monitor พิมพ์คำสั่ง


dataout = 2

ปิด Serial Monitor เปิด Serial Plotter ใหม่ จะเห็นกราฟของ absolute error ดังในรูปที่ 7 มีระดับสูงสุดประมาณ 10

รูปที่ 7 กราฟ absolute error เมื่อไม่ใช้ตัวกรอง

ต่อมาจะทดลองเปิดการใช้งาน LPF โดยคำสั่ง


filter=1

จะได้กราฟเอาต์พุตและ absolute error ดังในรูปที่ 8 และ 9 ตามลำดับ จะเห็นได้ว่าสัญญาณรบกวนถูกลดทอนลงโดยตัวกรอง เมื่อสังเกตที่ LED จะเห็นว่าการเปลี่ยนแปลงความสว่างจะลดน้อยลงจนแทบสังเกตไม่ได้

รูปที่ 8 เอาต์พุตเมื่อเปิดการใช้งานตัวกรอง
รูปที่ 9 กราฟ absolute error เมื่อใช้ตัวกรอง

การสั่งงานและแสดงผลผ่าน NETPIE

การศึกษาผลจากการใช้ตัวกรอง LPF โดยวิธีที่ผ่านมาค่อนข้างยุ่งยากและไม่เป็นมิตรกับผู้ใช้ เพราะต้องจำคำสั่งได้และพิมพ์คำสั่งใน Serial Monitor นอกจากนั้นเราอยากใช้ตัวกรองนี้ในอุปกรณ์ IoT ที่สามารถปรับความถี่คัทออฟได้ผ่านอินเทอร์เน็ต NETPIE เป็นบริการคลาวด์ในประเทศที่ตอบสนองความต้องการดังกล่าวได้อย่างสมบูรณ์ ถึงแม้ว่าจะไม่สามารถดูข้อมูลเอาต์พุตโดยตรงผ่านอินเทอร์เน็ตเพราะต้องการอัตราการส่งที่สูงกว่าข้อจำกัด แต่ในทางปฏิบัติข้อมูล error เป็นดัชนีที่เพียงพอสำหรับการวิเคราะห์ผลจากตัวกรอง

โปรแกรม dfilter_netpie.ino เป็นการประยุกต์ใช้ LPF ร่วมกับ NETPIE ในบทความนี้จะไม่อธิบายงการเชื่อมต่อ NETPIE และสร้าง Feed, Freeboard ผู้อ่านสามารถดูได้จากโปรแกรมที่ดาวน์โหลดได้ท้ายบทความ เมื่อคอมไพล์และโหลดลงบน NodeMCU เปิด Serial Monitor จะเห็นข้อความแสดงการ publish ข้อมูลและการเขียน Feed ดังแสดงในรูปที่ 10

รูปที่ 10 ข้อความที่แสดงการ publish และเขียน Feed บน Serial Monitor

รูปที่ 11 แสดงการเก็บข้อมูล ความถี่สัญญาณรบกวน ความถี่คัทออฟ สถานะของตัวกรอง และค่า error ขึ้น Feed ซึ่งสามารถนำมาวิเคราะห์ หรือแสดงผลผ่าน FeedView Widget บน Freeboard ที่ออกแบบในรูปที่ 12 โดยมี slider widgets สำหรับปรับค่าความถี่สัญญาณรบกวนและความถี่คัทออฟ และสวิตช์สำหรับเปิด/ปิดการใช้งาน LPF

รูปที่ 11 ข้อมูลที่เขียนขึ้น Feed
รูปที่ 12 หน้า NETPIE Freeboard ที่ออกแบบสำหรับ LPF

จาก FeedView Widget ในรูปที่ 12 ที่เลือกแสดงเฉพาะค่า error เทียบกับสถานะของตัวกรอง จะเห็นได้ชัดเจนว่าค่า error ลดลงเมื่อเปิดใช้ LPF

สรุป

บทความนี้อธิบายการสร้างตัวกรองแบบดิจิทัล โดยยกตัวอย่างการแปลง LPF เป็นอัลกอริทึมที่ทำงานบน ESP8266 ซึ่งสามารถเพิ่มโค้ดส่วนนี้เข้าไปเพื่อกรองสัญญาณจากเซนเซอร์ ตัวอย่างในบทความนี้สร้างสัญญาณรบกวนรูปคลื่นซายน์ขึ้นเพื่อการศึกษา ในทางปฏิบัติสัญญาณรบกวนจะเกิดขึ้นจากภายนอก เช่นคลื่นวิทยุ จากมอเตอร์ แหล่งจ่ายกำลัง

ตัวกรองที่อิมพลิเมนต์โดยซอฟต์แวร์มีข้อดีคือ ไม่เปลืองเนื้อที่วงจร มีความยืดหยุ่นสูง สามารถปรับค่าความถี่คัทออฟได้โดยง่าย ลักษณะสมบัติไม่เปลี่ยนแปลงตามอายุการใช้งาน ส่วนข้อด้อยคือไม่สามารถกำหนดความถี่คัทออฟที่สูงเกินไปได้ โดยทฤษฏีการสุ่มของแชนนอนกล่าวว่าอัตราการสุ่มต้องมีค่าอย่างน้อยสองเท่าของแบนด์วิดท์ระบบ ดังนั้นสมมุติว่าต้องการเลือกความถี่คัทออฟ 500 Hz อัตราการสุ่มต่ำสุดคือ 1 KHz หรือคาบเวลาของไทเมอร์เท่ากับ 1 มิลลิวินาที ซึ่งเป็นคาบเวลาที่สั้นมากและอาจประสบปัญหาด้านเวลา ดังนั้นตัวกรองนี้จะเหมาะสมกับการใช้กับเซนเซอร์ที่ติดตั้งกับอุปกรณ์เชิงกลหรือระบบทางเคมีที่มีแบนด์วิดท์ต่ำ นอกจากนั้นการใช้งานกับสัญญาณที่มีลักษณะเป็นพัลส์ เช่นการแปลงค่าสัญญาณ PWM เป็นสัญญาณต่อเนื่อง ประสิทธิภาพอาจจะด้อยกว่าการใช้วงจร RC

รวมโปรแกรที่ใช้ในบทความ dLPF.zip

No comments:

Post a Comment

แนะนำหนังสือ “ตัวควบคุมป้อนกลับบนอินเทอร์เน็ตโดย ESP8266”

ปัจจุบันเมื่อกล่าวถึงอุปกรณ์ IoT (Internet of Things) คงมีน้อยคนที่จะไม่รู้จัก ในยุคที่การเข้าถึงอินเทอร์เน็ตเป็นกิจวัตรประจำวันของมนุษย์เ...