สารบัญ:
- ขั้นตอนที่ 1: การนับความถี่ของโรงเรียนเก่า
- ขั้นตอนที่ 2: วิธีซึ่งกันและกัน
- ขั้นตอนที่ 3: ฮาร์ดแวร์และแผนผัง
- ขั้นตอนที่ 4: รหัส
- ขั้นตอนที่ 5: ความแม่นยำและความแม่นยำ
วีดีโอ: ตัวนับความถี่ความละเอียดสูง: 5 ขั้นตอน (พร้อมรูปภาพ)
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:02
คำแนะนำนี้แสดงตัวนับความถี่ซึ่งกันและกันที่สามารถวัดความถี่ได้อย่างรวดเร็วและแม่นยำ มันทำด้วยส่วนประกอบมาตรฐานและสามารถทำได้ในช่วงสุดสัปดาห์ (ฉันใช้เวลานานกว่านี้เล็กน้อย:-))
แก้ไข: ตอนนี้รหัสมีอยู่ใน 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 ไม่มีการสร้างลอจิกการดักจับ และฟังก์ชันขัดจังหวะทั้งหมดต้องใช้เวลาพอสมควรในการทำงาน ฉันคิดว่าเจ็ดหลักก็ยังดีพออยู่ดี
แนะนำ:
DIY 37 Leds เกมรูเล็ต Arduino: 3 ขั้นตอน (พร้อมรูปภาพ)
DIY 37 Leds เกมรูเล็ต Arduino: รูเล็ตเป็นเกมคาสิโนที่ตั้งชื่อตามคำภาษาฝรั่งเศสหมายถึงวงล้อเล็ก
หมวกนิรภัย Covid ส่วนที่ 1: บทนำสู่ Tinkercad Circuits!: 20 ขั้นตอน (พร้อมรูปภาพ)
Covid Safety Helmet ตอนที่ 1: บทนำสู่ Tinkercad Circuits!: สวัสดีเพื่อน ๆ ในชุดสองตอนนี้ เราจะเรียนรู้วิธีใช้วงจรของ Tinkercad - เครื่องมือที่สนุก ทรงพลัง และให้ความรู้สำหรับการเรียนรู้เกี่ยวกับวิธีการทำงานของวงจร! หนึ่งในวิธีที่ดีที่สุดในการเรียนรู้คือการทำ ดังนั้น อันดับแรก เราจะออกแบบโครงการของเราเอง: th
Bolt - DIY Wireless Charging Night Clock (6 ขั้นตอน): 6 ขั้นตอน (พร้อมรูปภาพ)
Bolt - DIY Wireless Charging Night Clock (6 ขั้นตอน): การชาร์จแบบเหนี่ยวนำ (เรียกอีกอย่างว่าการชาร์จแบบไร้สายหรือการชาร์จแบบไร้สาย) เป็นการถ่ายโอนพลังงานแบบไร้สาย ใช้การเหนี่ยวนำแม่เหล็กไฟฟ้าเพื่อจ่ายกระแสไฟฟ้าให้กับอุปกรณ์พกพา แอปพลิเคชั่นที่พบบ่อยที่สุดคือ Qi Wireless Charging st
4 ขั้นตอน Digital Sequencer: 19 ขั้นตอน (พร้อมรูปภาพ)
4 ขั้นตอน Digital Sequencer: CPE 133, Cal Poly San Luis Obispo ผู้สร้างโปรเจ็กต์: Jayson Johnston และ Bjorn Nelson ในอุตสาหกรรมเพลงในปัจจุบัน ซึ่งเป็นหนึ่งใน “instruments” เป็นเครื่องสังเคราะห์เสียงดิจิตอล ดนตรีทุกประเภท ตั้งแต่ฮิปฮอป ป๊อป และอีฟ
ป้ายโฆษณาแบบพกพาราคาถูกเพียง 10 ขั้นตอน!!: 13 ขั้นตอน (พร้อมรูปภาพ)
ป้ายโฆษณาแบบพกพาราคาถูกเพียง 10 ขั้นตอน!!: ทำป้ายโฆษณาแบบพกพาราคาถูกด้วยตัวเอง ด้วยป้ายนี้ คุณสามารถแสดงข้อความหรือโลโก้ของคุณได้ทุกที่ทั่วทั้งเมือง คำแนะนำนี้เป็นการตอบสนองต่อ/ปรับปรุง/เปลี่ยนแปลงของ: https://www.instructables.com/id/Low-Cost-Illuminated-