สารบัญ:

การวิ่งโดยเฉลี่ยสำหรับโปรเจ็กต์ไมโครคอนโทรลเลอร์ของคุณ: 6 ขั้นตอน
การวิ่งโดยเฉลี่ยสำหรับโปรเจ็กต์ไมโครคอนโทรลเลอร์ของคุณ: 6 ขั้นตอน

วีดีโอ: การวิ่งโดยเฉลี่ยสำหรับโปรเจ็กต์ไมโครคอนโทรลเลอร์ของคุณ: 6 ขั้นตอน

วีดีโอ: การวิ่งโดยเฉลี่ยสำหรับโปรเจ็กต์ไมโครคอนโทรลเลอร์ของคุณ: 6 ขั้นตอน
วีดีโอ: EP 27. Arduino ฉบับไวจนไฟลุก !! - สาระเดฟ ใน 3 นาที 2024, พฤศจิกายน
Anonim
วิ่งเฉลี่ยสำหรับโครงการไมโครคอนโทรลเลอร์ของคุณ
วิ่งเฉลี่ยสำหรับโครงการไมโครคอนโทรลเลอร์ของคุณ

ในคำแนะนำนี้ ฉันจะอธิบายว่าค่าเฉลี่ยวิ่งคืออะไรและทำไมคุณควรสนใจมัน รวมทั้งแสดงให้คุณเห็นว่ามันควรจะนำไปใช้อย่างไรเพื่อประสิทธิภาพในการคำนวณสูงสุด (ไม่ต้องกังวลกับความซับซ้อน มันง่ายมากที่จะเข้าใจและฉันจะ ให้ห้องสมุดที่ใช้งานง่ายสำหรับโครงการ Arduino ของคุณเช่นกัน:)

ค่าเฉลี่ยเคลื่อนที่ หรือที่เรียกกันทั่วไปว่าค่าเฉลี่ยเคลื่อนที่ ค่าเฉลี่ยเคลื่อนที่ หรือค่าเฉลี่ยเคลื่อนที่ เป็นคำที่ใช้อธิบายค่าเฉลี่ยของค่า N สุดท้ายในชุดข้อมูล สามารถคำนวณได้เช่นเดียวกับค่าเฉลี่ยปกติหรือคุณสามารถใช้เคล็ดลับเพื่อให้มีผลกระทบต่อประสิทธิภาพของโค้ดน้อยที่สุด

ขั้นตอนที่ 1: ใช้กรณี: ทำให้การวัด ADC ราบรื่นขึ้น

กรณีใช้งาน: การปรับการวัด ADC ให้ราบรื่น
กรณีใช้งาน: การปรับการวัด ADC ให้ราบรื่น

Arduino มี ADC 10 บิตที่เหมาะสมและมีสัญญาณรบกวนน้อยมาก เมื่อทำการวัดค่าบนเซ็นเซอร์ เช่น โพเทนชิออมิเตอร์ โฟโตรีซีสเตอร์ หรือส่วนประกอบที่มีสัญญาณรบกวนสูงอื่นๆ เป็นเรื่องยากที่จะเชื่อว่าการวัดนั้นถูกต้อง

ทางออกหนึ่งคือทำการวัดหลายครั้งทุกครั้งที่คุณต้องการอ่านเซ็นเซอร์และหาค่าเฉลี่ย ในบางกรณี วิธีนี้เป็นวิธีที่ใช้ได้แต่ไม่เสมอไป หากคุณต้องการอ่าน ADC 1,000 ครั้งต่อวินาที คุณจะต้องอ่าน 10,000 ครั้งหากคุณใช้การวัดเฉลี่ย 10 ครั้ง เสียเวลาในการคำนวณอย่างมาก

วิธีแก้ปัญหาที่ฉันเสนอคือทำการวัด 1,000 ครั้งต่อวินาที อัปเดตค่าเฉลี่ยการทำงานในแต่ละครั้ง และใช้เป็นค่าปัจจุบัน วิธีนี้จะแนะนำเวลาแฝง แต่ลดความซับซ้อนในการคำนวณของแอปพลิเคชันของคุณ ทำให้คุณมีเวลามากขึ้นสำหรับการประมวลผลเพิ่มเติม

ในภาพด้านบนฉันใช้ค่าเฉลี่ยการวิ่งของการวัด 32 ครั้งล่าสุด คุณจะเห็นว่าวิธีนี้ไม่ได้ป้องกันการล้มเหลว 100% แต่ช่วยเพิ่มความแม่นยำได้อย่างมาก (ไม่ได้แย่ไปกว่าการสุ่มตัวอย่าง 32 ตัวอย่างในแต่ละครั้ง) หากคุณต้องการคำนวณค่าเฉลี่ย 32 การวัดในแต่ละครั้ง จะใช้เวลามากกว่า 0.25 ms บน Arduino UNO สำหรับการวัดเพียงอย่างเดียว!

ขั้นตอนที่ 2: กรณีใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน

กรณีการใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน
กรณีการใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน
กรณีการใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน
กรณีการใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน
กรณีการใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน
กรณีการใช้งาน: การวัดส่วนประกอบ DC ของสัญญาณไมโครโฟน

Arduino สามารถวัดแรงดันไฟฟ้าระหว่าง 0 ถึง Vcc (ปกติ 5 V) สัญญาณเสียงเป็น AC อย่างสมบูรณ์ และหากคุณต้องการวัดบนไมโครคอนโทรลเลอร์ คุณต้องให้อคติประมาณ 1/2 Vcc ในโครงการ Arduino UNO ที่จะหมายถึงประมาณ 2.5 V (DC) + สัญญาณเสียง (AC) เมื่อใช้แหล่งจ่ายไฟ 10 บิต ADC และ 5 V ความเอนเอียง 2.5 V ควรเท่ากับ 512 ดังนั้นเพื่อให้ได้ค่าสัญญาณ AC ควรลบ 512 ออกจากการวัด ADC เท่านั้น ใช่ไหม

ในโลกอุดมคติ นั่นย่อมเป็นความจริง น่าเสียดายที่ชีวิตจริงนั้นซับซ้อนกว่าและอคติของสัญญาณของเรามีแนวโน้มที่จะล่องลอยไป โดยทั่วไปคือสัญญาณรบกวน 50 Hz (60 Hz หากคุณอาศัยอยู่ในสหรัฐอเมริกา) จากเครือข่ายไฟฟ้า โดยปกติแล้วจะไม่เป็นปัญหามากนัก แต่เป็นการดีที่จะรู้ว่ามีอยู่จริง ปัญหาที่มากกว่าคือการเลื่อนเชิงเส้นจากการให้ความร้อนของส่วนประกอบ คุณตั้งค่าการแก้ไข DC offset อย่างระมัดระวังในตอนเริ่มต้น และมันจะค่อยๆ หายไปในขณะที่แอปพลิเคชันของคุณกำลังทำงาน

ฉันจะอธิบายปัญหานี้ด้วยเครื่องตรวจจับจังหวะ (เพลง) คุณตั้งค่าการกำจัดอคติและจังหวะของคุณชัดเจน (ภาพที่ 2) หลังจากผ่านไประยะหนึ่ง ไมโครคอนโทรลเลอร์ DC อคติจะเคลื่อนที่และบีตแทบไม่สังเกตเห็น (ภาพที่ 3) อัลกอริธึมการตรวจจับบีตจะถูกสำรวจในเชิงลึกในอนาคตที่สามารถแนะนำได้ เนื่องจากเกินขอบเขตของบทความนี้

โชคดีที่มีวิธีคำนวณ DC offset ของเสียงอย่างต่อเนื่อง จะไม่แปลกใจเลยที่การรันค่าเฉลี่ย หัวข้อของคำแนะนำนี้ ให้โซลูชัน

เรารู้ว่าค่าเฉลี่ยของสัญญาณ AC ใดๆ เป็น 0 การใช้ความรู้นี้ เราสามารถหักค่าเฉลี่ยของสัญญาณ AC+DC ได้ นั่นคือค่า DC bias ในการลบออก เราสามารถหาค่าเฉลี่ยของค่าสองสามค่าล่าสุดและลบออกจากค่าที่อ่านได้ของ ADC ปัจจุบัน โปรดทราบว่าคุณต้องใช้ค่าเฉลี่ยการวิ่งที่ยาวเพียงพอ สำหรับเสียง หนึ่งในสิบของวินาที (จำนวนตัวอย่างขึ้นอยู่กับอัตราการสุ่มตัวอย่างของคุณ) น่าจะเพียงพอ แต่รู้ว่าค่าเฉลี่ยที่ยาวขึ้นทำงานได้ดีกว่า ในภาพแรก คุณสามารถดูตัวอย่างการคำนวณอคติ DC จริงด้วยค่าเฉลี่ยการทำงาน 64 องค์ประกอบที่อัตราการสุ่มตัวอย่าง 1 kHz (น้อยกว่าที่ฉันแนะนำ แต่ก็ยังใช้งานได้)

ขั้นตอนที่ 3: การคำนวณ

การคำนวณ
การคำนวณ

คุณสามารถจินตนาการว่าค่าเฉลี่ยการวิ่งเป็นน้ำหนักเฉลี่ยของคนในห้องรอหมอ หมอตรวจคนไข้เสร็จหนึ่งราย และคนไข้รายใหม่เดินเข้ามาในห้องรอพร้อมกัน

ในการหาน้ำหนักเฉลี่ยของผู้ป่วยรอทั้งหมดในห้องรอ พยาบาลสามารถถามผู้ป่วยแต่ละรายเกี่ยวกับน้ำหนักของพวกเขา บวกตัวเลขเหล่านั้นขึ้นแล้วหารด้วยจำนวนผู้ป่วย ทุกครั้งที่แพทย์รับผู้ป่วยรายใหม่ พยาบาลจะทำซ้ำขั้นตอนทั้งหมด

คุณอาจกำลังคิดว่า: "ฟังดูไม่มีประสิทธิภาพเกินไป… ต้องมีวิธีที่ดีกว่าในการทำเช่นนี้" และคุณจะถูกต้อง

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

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

ขั้นตอนที่ 4: รหัส

รหัส
รหัส

ในการคำนวณค่าเฉลี่ยวิ่ง คุณต้องมีวิธีเก็บค่า N สุดท้ายก่อน คุณสามารถมีอาร์เรย์ที่มีองค์ประกอบ N และย้ายเนื้อหาทั้งหมดได้ในที่เดียวในแต่ละครั้งที่คุณเพิ่มองค์ประกอบ (โปรดอย่าทำเช่นนี้) หรือคุณสามารถเขียนทับองค์ประกอบเก่าหนึ่งรายการและปรับตัวชี้ไปยังองค์ประกอบถัดไปที่จะถูกโยนทิ้ง (โปรดทำเช่นนี้:)

ตัวสะสมควรเริ่มต้นที่ 0 เช่นเดียวกันสำหรับองค์ประกอบทั้งหมดในบรรทัดการหน่วงเวลา ในกรณีอื่น ๆ ค่าเฉลี่ยการวิ่งของคุณจะผิดเสมอ คุณจะเห็นว่า delayLine_init ดูแลการเริ่มต้นสายการหน่วงเวลา คุณควรดูแลตัวสะสมด้วยตัวเอง

การเพิ่มองค์ประกอบไปยังเส้นการหน่วงเวลานั้นง่ายพอๆ กับการลดดัชนีขององค์ประกอบใหม่ล่าสุดทีละ 1 ตรวจสอบให้แน่ใจว่าไม่ได้ชี้ให้เห็นถึงด้านข้างของอาร์เรย์สายการหน่วงเวลา หลังจากลดค่าดัชนีเมื่อเป็น 0 มันจะวนรอบเป็น 255 (เพราะเป็นจำนวนเต็ม 8 บิตที่ไม่ได้ลงนาม) โมดูโลโอเปอเรเตอร์ (%) ที่มีขนาดของ line array ที่หน่วงเวลาจะทำให้มั่นใจว่าดัชนีจะชี้ไปที่องค์ประกอบที่ถูกต้อง

การคำนวณค่าเฉลี่ยวิ่งควรเข้าใจง่ายหากคุณทำตามการเปรียบเทียบของฉันในขั้นตอนที่แล้ว ลบองค์ประกอบที่เก่าที่สุดออกจากตัวสะสม, เพิ่มค่าใหม่ล่าสุดให้กับตัวสะสม, ผลักค่าใหม่ล่าสุดไปยังเส้นหน่วงเวลา, ส่งคืนตัวสะสมหารด้วยจำนวนองค์ประกอบ

ง่ายใช่มั้ย?

โปรดทดลองโดยใช้โค้ดที่แนบมาเพื่อให้เข้าใจถึงวิธีการทำงานทั้งหมดได้ดีขึ้น ขณะนี้ Arduino อ่านค่าอะนาล็อกบนขาอะนาล็อก A0 และพิมพ์ "[ADC value], [running average]" บนพอร์ตอนุกรมที่อัตรา 115200 baud หากคุณเปิดพล็อตเตอร์อนุกรมของ Arduino ด้วยอัตราบอดที่ถูกต้อง คุณจะเห็นสองบรรทัด: ค่า ADC (สีน้ำเงิน) และค่าที่ปรับให้เรียบ (สีแดง)

ขั้นตอนที่ 5: ความพิเศษ

ความพิเศษ
ความพิเศษ

มีบางสิ่งที่คุณไม่จำเป็นต้องรู้เพื่อใช้ค่าเฉลี่ยในโครงการของคุณโดยที่คุณไม่ต้องรู้

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

กำลังเดินทางไป.

การเริ่มต้น: เมื่อฉันพูดถึงการเริ่มต้นองค์ประกอบสะสมและหน่วงเวลา ฉันบอกว่าคุณควรเริ่มต้นพวกเขาทั้งหมดเป็น 0 หรืออีกวิธีหนึ่งคุณสามารถเริ่มต้นสายการหน่วงเวลาเป็นอะไรก็ได้ที่คุณต้องการ แต่ตัวสะสมควรเริ่มต้นเป็นผลรวมขององค์ประกอบ N ใหม่ล่าสุดในบรรทัดการหน่วงเวลา (โดยที่ N คือจำนวนขององค์ประกอบในค่าเฉลี่ยการวิ่งของคุณ) หากตัวสะสมเริ่มต้นเป็นค่าอื่น ค่าเฉลี่ยที่คำนวณได้จะผิด ไม่ว่าจะต่ำหรือสูงเกินไป โดยใช้จำนวนเงินเท่ากันเสมอ (สมมติว่ามีเงื่อนไขเริ่มต้นเหมือนกัน) ฉันแนะนำให้คุณลองเรียนรู้ว่าเหตุใดจึงเป็นเช่นนี้โดยใช้ "การจำลองด้วยปากกาและกระดาษ"

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

เคล็ดลับ: เส้นหน่วงเวลายาวใช้หน่วยความจำจำนวนมาก ที่สามารถกลายเป็นปัญหาได้อย่างรวดเร็ว หากคุณถูกจำกัดหน่วยความจำมากและไม่สนใจความถูกต้องมากนัก คุณสามารถประมาณค่าเฉลี่ยการวิ่งได้โดยละเว้นการหน่วงเวลาทั้งหมดแล้วทำสิ่งนี้แทน: ลบตัวสะสม 1/N * ออกจากตัวสะสมและเพิ่มค่าใหม่ (ในตัวอย่างของค่าเฉลี่ยระยะยาว 8 รายการ: ตัวสะสม = ตัวสะสม * 7 / 8 + ค่าใหม่) วิธีนี้ให้ผลลัพธ์ที่ไม่ถูกต้อง แต่เป็นวิธีที่ดีในการคำนวณค่าเฉลี่ยการวิ่งเมื่อคุณมีหน่วยความจำเหลือน้อย

ภาษาศาสตร์: โดยทั่วไปจะใช้ "ค่าเฉลี่ย/ค่าเฉลี่ย" เมื่อพูดถึงค่าเฉลี่ยตามเวลาจริง ในขณะที่ "ค่าเฉลี่ยเคลื่อนที่/ค่าเฉลี่ย" มักจะหมายถึงอัลกอริทึมกำลังทำงานบนชุดข้อมูลคงที่ เช่น สเปรดชีต excel

ขั้นตอนที่ 6: บทสรุป

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

แนะนำ: