สารบัญ:

ตัวนับความถี่ความละเอียดสูง: 5 ขั้นตอน (พร้อมรูปภาพ)
ตัวนับความถี่ความละเอียดสูง: 5 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: ตัวนับความถี่ความละเอียดสูง: 5 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: ตัวนับความถี่ความละเอียดสูง: 5 ขั้นตอน (พร้อมรูปภาพ)
วีดีโอ: [การวิเคราะห์ข้อมูลเบื้องต้น] ตอนที่ 1 ส่วนประกอบของตารางแจกแจงความถี่ 2024, พฤศจิกายน
Anonim

คำแนะนำนี้แสดงตัวนับความถี่ซึ่งกันและกันที่สามารถวัดความถี่ได้อย่างรวดเร็วและแม่นยำ มันทำด้วยส่วนประกอบมาตรฐานและสามารถทำได้ในช่วงสุดสัปดาห์ (ฉันใช้เวลานานกว่านี้เล็กน้อย:-))

แก้ไข: ตอนนี้รหัสมีอยู่ใน GitLab:

gitlab.com/WilkoL/high-resolution-frequency-counter

ขั้นตอนที่ 1: การนับความถี่ของโรงเรียนเก่า

การนับความถี่ของโรงเรียนเก่า
การนับความถี่ของโรงเรียนเก่า
การนับความถี่ของโรงเรียนเก่า
การนับความถี่ของโรงเรียนเก่า

วิธีวัดความถี่ของสัญญาณแบบเก่าคือการใช้ลอจิก AND-gate ป้อนสัญญาณที่จะวัดเป็นพอร์ตเดียวและสัญญาณที่มีเวลาสูง 1 วินาทีถึงพอร์ตอื่นและนับเอาต์พุต วิธีนี้ใช้ได้ผลดีกับสัญญาณไม่กี่ kHz ที่เข้าสู่ GHz แต่ถ้าคุณต้องการวัดสัญญาณความถี่ต่ำที่มีความละเอียดดีล่ะ? สมมติว่าคุณต้องการวัดความถี่ของแหล่งจ่ายไฟหลัก (ที่นี่ 50 Hz) ด้วยวิธีการแบบโรงเรียนเก่า คุณจะเห็นค่าคงที่ 50 บนจอแสดงผลหากคุณโชคดี แต่มีแนวโน้มมากขึ้นที่คุณจะเห็นการเปลี่ยนการแสดงผลจาก 49 เป็น 50 หรือ 50 เป็น 51 ความละเอียดคือ 1 Hz และเท่านั้น คุณจะไม่เห็น 50.002 Hz เว้นแต่คุณต้องการเพิ่มเวลาเกทเป็น 1,000 วินาที นั่นมากกว่า 16 นาทีสำหรับการวัดครั้งเดียว!

วิธีที่ดีกว่าในการวัดสัญญาณความถี่ต่ำคือการวัดระยะเวลาของมัน ยกตัวอย่างไฟหลักอีกครั้ง มีระยะเวลา 20 มิลลิวินาที ใช้ตรรกะ AND-gate เดียวกัน ป้อนด้วย พูดว่า 10 MHz (0.1 us พัลส์) และสัญญาณของคุณบนพอร์ตอื่นและเอาท์พุตออกมา 200,000 พัลส์ ดังนั้นระยะเวลาคือ 2,0000.0 uS และนั่นแปลกลับเป็น 50Hz เมื่อคุณวัดพัลส์ในปี 199650 ความถี่คือ 50.087 Hz นั่นดีกว่ามาก และมันอยู่ในเวลาวัดเพียงหนึ่งวินาที น่าเสียดายที่วิธีนี้ใช้ไม่ได้ผลกับความถี่ที่สูงขึ้น ตัวอย่างเช่น ตอนนี้เราต้องการวัด 40 kHz ด้วยความถี่อินพุต 10 MHz เดียวกันกับข้อมูลอ้างอิง ขณะนี้เราวัดได้เพียง 250 พัลส์ เมื่อเรานับเพียง 249 พัลส์ การคำนวณจะให้ 40161 Hz และ 251 ผลลัพธ์คือ 39840 Hz นั่นไม่ใช่วิธีแก้ปัญหาที่ยอมรับได้ แน่นอนว่าการเพิ่มความถี่อ้างอิงจะช่วยปรับปรุงผลลัพธ์ แต่มีข้อ จำกัด เกี่ยวกับสิ่งที่คุณสามารถใช้ได้ในไมโครคอนโทรลเลอร์

ขั้นตอนที่ 2: วิธีซึ่งกันและกัน

วิธีซึ่งกันและกัน
วิธีซึ่งกันและกัน
วิธีซึ่งกันและกัน
วิธีซึ่งกันและกัน

โซลูชันที่ทำงานได้ทั้งความถี่ต่ำและความถี่สูงคือตัวนับความถี่ส่วนกลับ ฉันจะพยายามอธิบายหลักการของมัน คุณเริ่มต้นด้วยเวลาในการวัดที่ประมาณ 1 วินาที ไม่จำเป็นต้องแม่นยำมาก แต่เป็นเวลาที่เหมาะสมสำหรับการวัด ป้อนสัญญาณ 1 Hz นี้ลงใน D-flipflop บน D-input ยังไม่มีอะไรเกิดขึ้นในเอาต์พุต เชื่อมต่อสัญญาณที่คุณต้องการวัดกับอินพุต CLOCK ของ D-flipflop

ทันทีที่สัญญาณนี้เปลี่ยนจาก LOW เป็น HIGH เอาต์พุตของ D-flipflop จะถ่ายโอนสถานะของ D-input ไปยังเอาต์พุต (Q) สัญญาณที่เพิ่มขึ้นนี้ใช้เพื่อเริ่มนับสัญญาณอินพุตและสัญญาณนาฬิกาอ้างอิง

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

หลังจากเวลาผ่านไป พูดสักสองสามมิลลิวินาที คุณทำให้อินพุต D ของ D-flipflop ต่ำอีกครั้ง ที่อินพุต CLOCK ถัดไป เอาต์พุต Q จะตามสถานะของอินพุต แต่ไม่มีอะไรเกิดขึ้นอีกเนื่องจากไมโครคอนโทรลเลอร์ถูกตั้งค่าให้ตอบสนองต่อสัญญาณ RISING เท่านั้น จากนั้น หลังจากหมดเวลาการวัด (ประมาณ 1 วินาที) คุณจะตั้งค่า D-input สูง

อีกครั้งที่อินพุต CLOCK ถัดไป เอาต์พุต Q จะตามมา และสัญญาณ RISING นี้จะทริกเกอร์ไมโครคอนโทรลเลอร์ คราวนี้จะสิ้นสุดการนับของตัวนับทั้งสอง

ผลลัพธ์คือตัวเลขสองตัว ตัวเลขแรกคือจำนวนพัลส์ที่นับจากการอ้างอิง เนื่องจากเราทราบความถี่อ้างอิง เราจึงทราบเวลาที่ใช้ในการนับพัลส์เหล่านั้นด้วย

ตัวเลขที่สองคือจำนวนพัลส์จากสัญญาณอินพุตที่เรากำลังวัด เมื่อเราเริ่มต้นตรงขอบ RISING ของสัญญาณนี้ เรามั่นใจมากเกี่ยวกับจำนวนพัลส์ของสัญญาณอินพุตนี้

ตอนนี้เป็นเพียงการคำนวณเพื่อกำหนดความถี่ของสัญญาณอินพุต

ตัวอย่างเช่น สมมติว่าเรามีสัญญาณเหล่านี้และเราต้องการวัดค่า f-input การอ้างอิงคือ 10 MHz ซึ่งสร้างโดยออสซิลเลเตอร์คริสตัลควอตซ์ f_input = 31.416 Hz f_reference = 10000000 Hz (10 MHz) เวลาในการวัดประมาณ 1 วินาที

คราวนี้เรานับได้ 32 พัลส์ ตอนนี้ ช่วงเวลาหนึ่งของสัญญาณนี้ใช้เวลา 1 / 31.416 = 31830.9 uS ดังนั้น 32 คาบใช้เวลา 1.0185892 วินาที ซึ่งเท่ากับ 1 วินาทีเท่านั้น

ใน 1.0186 วินาทีนี้ เราจะนับ 1,0185892 พัลส์ของสัญญาณอ้างอิง

สิ่งนี้ให้ข้อมูลต่อไปนี้แก่เรา: input_count = 32 reference_count = 10185892 f_reference = 10000000 Hz

สูตรคำนวณความถี่ผลลัพธ์คือ: freq = (input_count * f_reference) / ref_count

ในตัวอย่างของเราคือ: f-input = (32 * 10000000) / 10185892 = 31.416 Hz

และวิธีนี้ใช้ได้ดีกับความถี่ต่ำและความถี่สูง เฉพาะเมื่อสัญญาณอินพุตเข้าใกล้ (หรือสูงกว่า) กับความถี่อ้างอิงเท่านั้น ควรใช้วิธีการวัดแบบ "รั้วรอบขอบชิด" มาตรฐาน แต่จากนั้นเราก็สามารถเพิ่มตัวแบ่งความถี่ให้กับสัญญาณอินพุตได้ เนื่องจากวิธีการส่วนกลับนี้มีความละเอียดเท่ากันสำหรับความถี่ใดๆ (ขึ้นอยู่กับการอ้างอิงอีกครั้ง) ดังนั้นไม่ว่าคุณจะวัด 100 kHz โดยตรงโดยหารด้วยตัวแบ่ง 1000x ภายนอก ความละเอียดจะเท่ากัน

ขั้นตอนที่ 3: ฮาร์ดแวร์และแผนผัง

ฮาร์ดแวร์และแผนผังของมัน
ฮาร์ดแวร์และแผนผังของมัน
ฮาร์ดแวร์และแผนผังของมัน
ฮาร์ดแวร์และแผนผังของมัน

ฉันได้สร้างตัวนับความถี่ประเภทนี้มาสองสามตัวแล้ว นานมาแล้วฉันสร้างมันขึ้นมาด้วย ATMEGA328 (ตัวควบคุมเดียวกับใน Arduino) ต่อมาด้วยตัวควบคุมไมโคร ARM จาก ST ล่าสุดสร้างด้วย STM32F407 โอเวอร์คล็อกที่ 168 MHz แต่ตอนนี้ฉันสงสัยว่าถ้าฉันทำเช่นเดียวกันกับอันที่เล็กกว่า * มาก * ฉันเลือก ATTINY2313 ที่มีหน่วยความจำ FLASH เพียง 2kbyte และ RAM 128 ไบต์ จอแสดงผลที่ฉันมีคือ MAX7219 ที่มีจอแสดงผลเจ็ดส่วน 8 ส่วน จอแสดงผลเหล่านี้มีจำหน่ายบนอีเบย์ในราคาเพียง 2 ยูโร ATTINY2313 สามารถซื้อได้ประมาณ 1.5 ยูโร ส่วนอื่นๆ ที่ฉันใช้มีราคาเพียงเซ็นต์ต่อชิ้น ราคาแพงที่สุดน่าจะเป็นกล่องโครงการพลาสติก ต่อมาฉันตัดสินใจที่จะทำให้มันทำงานโดยใช้แบตเตอรี่ลิเธียมไอออน ดังนั้นฉันจึงจำเป็นต้องเพิ่มตัวควบคุมแรงดันไฟฟ้า 3.3V (LDO) ให้กับโมดูลชาร์จแบตเตอรี่และตัวแบตเตอรี่เอง สิ่งนี้จะเพิ่มราคาขึ้นบ้าง แต่ฉันเดาว่ามันสามารถสร้างได้น้อยกว่า 20 ยูโร

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

รหัส
รหัส
รหัส
รหัส

รหัสถูกเขียนด้วยภาษา C ด้วย Atmel (Microchip) Studio 7 และตั้งโปรแกรมไว้ใน ATTINY2313 โดยใช้ OLIMEX AVR_ISP (โคลน?) เปิด (main.c) ในไฟล์ zip ด้านล่าง หากคุณต้องการทำตามคำอธิบายที่นี่

การเริ่มต้น

ก่อนอื่น ATTINY2313 ถูกตั้งค่าให้ใช้คริสตัลภายนอกเนื่องจาก RC-oscillator ภายในไม่มีประโยชน์สำหรับการวัดสิ่งใด ฉันใช้คริสตัล 10 MHz ที่ฉันปรับให้เป็นความถี่ 10 000 000 Hz ที่ถูกต้องด้วยตัวเก็บประจุแบบแปรผันขนาดเล็ก การเริ่มต้นจะดูแลการตั้งค่าพอร์ตเป็นอินพุตและเอาต์พุต การตั้งค่าตัวจับเวลา และเปิดใช้งานการขัดจังหวะและการเริ่มต้นของ MAX7219 TIMER0 ถูกตั้งค่าให้นับนาฬิกาภายนอก TIMER1 นาฬิกาภายใน และยังจับค่าของตัวนับที่ขอบที่เพิ่มขึ้นของ ICP ที่มาจาก D-flipflop

ฉันจะพูดถึงโปรแกรมหลักก่อน ต่อไปคือรูทีนการขัดจังหวะ

TIMER0_OVF

เนื่องจาก TIMER0 นับได้ถึง 255 (8 บิต) จากนั้นจึงหมุนไปที่ 0 เราจำเป็นต้องมีการขัดจังหวะเพื่อนับจำนวนโอเวอร์โฟลว์ นั่นคือทั้งหมดที่ TIMER0_OVF ทำ แค่นับจำนวนโอเวอร์โฟลว์ ต่อมาตัวเลขนี้จะรวมกับค่าของตัวนับเอง

TIMER1_OVF

TIMER1 สามารถนับได้ถึง 65536 (16 บิต) ดังนั้นการขัดจังหวะ TIMER1_OVF จะนับจำนวนโอเวอร์โฟลว์ด้วย แต่มันทำมากกว่า นอกจากนี้ยังลดลงจาก 152 เป็น 0 ซึ่งใช้เวลาประมาณ 1 วินาที จากนั้นจึงตั้งค่าพินเอาต์พุต ไปที่อินพุต D ของฟลิปฟล็อป และสิ่งสุดท้ายที่ทำในรูทีนการขัดจังหวะนี้คือการลดตัวนับการหมดเวลา จาก 765 เป็น 0 ซึ่งใช้เวลาประมาณ 5 วินาที

TIMER1_CAPT

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

ถัดมาเป็นสองฟังก์ชั่นในการควบคุม MAX7219

SPI

ในขณะที่มี Universal Serial Interface (USI) อยู่ในชิป ฉันเลือกที่จะไม่ใช้มัน จอแสดงผล MAX7219 จำเป็นต้องควบคุมผ่าน SPI และเป็นไปได้ด้วย USI แต่ bitbanging SPI นั้นง่ายมาก ฉันไม่ได้ใช้เวลาทำกับ USI

MAX7219

โปรโตคอลในการตั้งค่า MAX7219 นั้นค่อนข้างง่ายเมื่อคุณอ่านคู่มือของมันแล้ว ต้องการค่า 16 บิตสำหรับทุกหลักที่ประกอบด้วย 8 บิตสำหรับตัวเลขหลัก (1 ถึง 8) ตามด้วย 8 บิตสำหรับตัวเลขที่ต้องการแสดง

MAIN-PROG

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

สิ่งแรกที่ต้องทำเมื่อตั้งค่าข้อความตัวแปรเป็นหนึ่ง คือการรีเซ็ตตัวนับการหมดเวลา หลังจากที่เรารู้ว่ามีสัญญาณอยู่ D-flipflop ถูกรีเซ็ตเพื่อให้พร้อมสำหรับทริกเกอร์ถัดไปที่จะเกิดขึ้นหลังจากเวลาวัด (รอสักครู่)

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

ต่อไปเป็นการคำนวณหาความถี่จริง ฉันไม่ต้องการใช้ตัวเลขลอยตัวบนไมโครคอนโทรลเลอร์ที่มีแฟลชเพียง 2kbytes และ RAM เพียง 128 ไบต์เท่านั้นที่ฉันใช้จำนวนเต็ม แต่ความถี่อาจเท่ากับ 314.159 Hz โดยมีทศนิยมหลายตำแหน่ง ดังนั้นฉันจึงคูณความถี่อินพุตไม่เฉพาะกับความถี่อ้างอิงเท่านั้นแต่ยังรวมถึงตัวคูณด้วย แล้วจึงบวกตัวเลขไปยังตำแหน่งที่จุดทศนิยมควรไป ตัวเลขเหล่านี้จะเพิ่มขึ้นอย่างมากเมื่อคุณทำเช่นนั้น เช่น. ด้วยอินพุต 500 kHz การอ้างอิง 10 MHz และตัวคูณ 100 สิ่งนี้ให้ 5 x 10^14 ที่ใหญ่มาก! พวกมันจะไม่พอดีกับหมายเลข 32 บิตดังนั้นฉันจึงใช้ตัวเลข 64 บิตที่จะไปถึง 1.8 x 10^19 (ใช้งานได้ดีกับ ATTINY2313)

และสิ่งสุดท้ายที่ต้องทำคือการส่งผลไปยังจอแสดงผล MAX7219

โค้ดนี้คอมไพล์เป็น 1600 ไบต์ ดังนั้นมันจึงพอดีกับแฟลช 2048 ไบต์ที่มีอยู่ใน ATTINY2313

ฟิวส์รีจิสเตอร์ควรอ่านดังนี้:

ขยาย 0xFF

สูง 0xDF

ต่ำ 0xBF

ขั้นตอนที่ 5: ความแม่นยำและความแม่นยำ

ความแม่นยำและความแม่นยำ
ความแม่นยำและความแม่นยำ
ความแม่นยำและความแม่นยำ
ความแม่นยำและความแม่นยำ
ความแม่นยำและความแม่นยำ
ความแม่นยำและความแม่นยำ

ความแม่นยำและความแม่นยำเป็นสัตว์สองตัวที่แยกจากกัน ความแม่นยำที่นี่คือเจ็ดหลัก ความแม่นยำที่แท้จริงนั้นขึ้นอยู่กับฮาร์ดแวร์และการสอบเทียบ ฉันปรับเทียบ 10 MHz (5 MHz บนจุดทดสอบ) ด้วยตัวนับความถี่อื่นที่มีออสซิลเลเตอร์ที่มีระเบียบวินัย GPS

และใช้งานได้ค่อนข้างดี ความถี่ต่ำสุดที่ฉันลองคือ 0.2 Hz สูงสุด 2 MHz มันตรงจุด ที่สูงกว่า 2 MHz ตัวควบคุมจะเริ่มขาดการขัดจังหวะ ไม่น่าแปลกใจจริงๆ เมื่อคุณรู้ว่าที่สัญญาณอินพุต 2 MHz TIMER0 สร้างการขัดจังหวะมากกว่า 7800 ครั้งต่อวินาที และ ATTINY2313 ต้องทำอย่างอื่นเช่นกัน การขัดจังหวะจาก TIMER1 ที่อีก 150 อินเตอร์รัปต์ต่อวินาที และแน่นอนว่าทำการคำนวณ ควบคุมการแสดงผลและ D-flipflop เมื่อคุณดูที่อุปกรณ์จริง คุณจะเห็นว่าฉันใช้จอแสดงผลเพียงเจ็ดหลักจากแปดหลัก ฉันทำเช่นนี้ด้วยเหตุผลหลายประการ

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

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

แนะนำ: