ฉันจะได้รับเวลาที่แม่นยำได้อย่างไร


16

ฉันทำนาฬิกาโดยใช้ Arduino แต่เวลาดูเหมือนจะล่องลอย ฉันตระหนักถึงปัญหาการหมุนเวียน ดูเหมือนว่านาฬิกาจะลอยประมาณ 15 นาทีในช่วงเวลาหนึ่งสัปดาห์

ฉันกำลังใช้ PCB แบบกำหนดเองกับตัวเปลี่ยนแสงนี้จาก Digi-key รหัสจะอ่านฟังก์ชัน millis () ที่จุดเริ่มต้นของแต่ละลูปและทำงานจากค่านั้น

คำถามของฉันคือ: ฉันจะวัดเวลาด้วย Arduino ได้อย่างถูกต้องมากพอที่จะทำให้นาฬิกาตั้งโต๊ะทำงานได้หรือไม่?


3
ฟังก์ชันมิลลิวินาทีมาพร้อมกับข้อมูลจากการขัดจังหวะซึ่งใช้เวลาสองรอบนาฬิกาในการทำงาน สิ่งนี้จะเพิ่มเวลาจำนวนเล็กน้อยในแต่ละขีด
TheDoctor

3
@TheDoctor: นี่ไม่ถูกต้อง millis()ขัดจังหวะไม่ชะลอตัวลงจับเวลาฮาร์ดแวร์ที่ไดรฟ์
Edgar Bonet

คำตอบ:


15

หมายเหตุ: แม้ว่าคำตอบของฉันจะได้รับการยอมรับและมีคะแนนโหวตสูงกว่า แต่ให้แน่ใจว่าคุณอ่านคำตอบที่ยอดเยี่ยมของ Edgar Bonetเกี่ยวกับวิธีทำให้ Arduino ของคุณรักษาเวลาโดยไม่ใช้ RTC

ฉันประสบความสำเร็จในการใช้นาฬิกาเรียลไทม์ DS1307 นี่คือการเชื่อมโยงไปของแผ่นข้อมูล

ด้านล่างนี้เป็นคุณสมบัติบางส่วน:

  • ใช้อินเทอร์เฟซ IC สำหรับการสื่อสารกับ Arduino ทำให้ง่ายต่อการตั้งโปรแกรมโดยใช้ไลบรารีที่ถูกต้อง (มีอยู่ในเน็ต)

  • มันเชื่อมต่อกับ Arduino ผ่านขา SCL และ SDA (อะนาล็อก A4 และ A5 ตามลำดับ) ดังนั้นใช้เพียง 2 ขาเท่านั้น

  • มันต้องใช้ส่วนประกอบภายนอกน้อยมากในการทำงาน

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

  • มันลอยน้อยมาก (ในกรณีของฉันมันลอยเพียงไม่กี่วินาทีต่อสัปดาห์)

  • มันไม่แพงมาก

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

รูปภาพออสซิลเลเตอร์คริสตัล รูปภาพออสซิลเลเตอร์คริสตัล รูปภาพออสซิลเลเตอร์คริสตัล

ทั้งสองโมดูลดังกล่าวมีความคลาดเคลื่อน 50 ppm และทำงานที่ 5V

อีกครั้งเพื่อให้ชัดเจนโมดูล oscillator คริสตัลเหล่านี้จะไม่ต้องสับสนกับคริสตัล 2 ขาปกติเช่นนี้ด้านล่าง สิ่งเหล่านี้เป็นส่วนหนึ่งของวงจรของนาฬิกาภายนอกสำหรับ MCU เช่น

คริสตัลออสซิลเลเตอร์


DS1302 ดีพอหรือฉันควรจะย้ายไปที่ DS1307 หรือไม่?
Kelly S. ชาวฝรั่งเศส

14

คุณไม่จำเป็นต้องมี RTC เพื่อสร้างนาฬิกา: ชิป ATmega มีฮาร์ดแวร์ทั้งหมดที่จำเป็นในการปฏิบัติหน้าที่ของ RTC เอง นี่คือวิธี:

  1. รับคริสตัลนาฬิกา 32768 Hz: ซื้อหรือแยกนาฬิกาเก่า ผลึกเหล่านี้ได้รับการออกแบบมาโดยเฉพาะสำหรับการรักษาเวลามีมากลอยอุณหภูมิขนาดเล็ก คุณจะต้องมีหนึ่งในนั้นหากคุณต้องการใช้ชิป RTC

  2. กำหนดค่าฟิวส์ของ ATmega ของคุณเพื่อให้หลุดออกจาก 8 MHz RC oscillator สิ่งนี้จะทำให้millis()ฟังก์ชั่นของคุณไม่ถูกต้องอย่างน่ากลัวและยังเพิ่มหมุด XTAL1 และ XTAL2

  3. เชื่อมต่อคริสตัลนาฬิกากับพิน TOSC1 และ TOSC2 เหล่านี้เป็นพินเดียวกับ XTAL1 และ XTAL2 (9 และ 10 ใน 328P) ชื่อที่แตกต่างกันใช้เพื่อหมายถึงฟังก์ชั่นต่าง ๆ

  4. กำหนดค่า Timer / Counter 2 สำหรับการทำงานแบบอะซิงโครนัสโหมดนับปกติ prescaler ตั้งไว้ที่ 128 และเปิดใช้งานการขัดจังหวะตัวตั้งเวลาล้น

ตอนนี้คุณจะได้รับการขัดจังหวะโดย TIMER2_OVF ในอัตราที่คงที่มาก ๆ หนึ่งครั้งต่อวินาที คุณจะต้องเลื่อนการแสดงผลนาฬิกาล่วงหน้าไปหนึ่งวินาทีใน ISR ในระหว่างการขัดจังหวะคุณสามารถทำให้ MCU อยู่ในโหมดสลีปที่ลึกมาก (โหมดประหยัดพลังงาน: ไม่มีอะไรทำงานนอกจากตัวจับเวลา / ตัวนับ 2) และทำงานเป็นเวลาหลายปีในเซลล์ AA สองเซลล์ เว้นเสียแต่ว่าจอแสดงผลจะเต็มไปด้วยกำลัง

ผมทำตรงนี้ในการสร้างของฉันตลอด 24 ชั่วโมงนาฬิกาผนังด้านหนึ่งมือ ลิงค์นี้ชี้ไปที่การแปลภาษาอังกฤษของเอกสารต้นฉบับเป็นภาษาฝรั่งเศส

การสอบเทียบควอตซ์

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

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

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

#define ONE_SECOND    1000000000  // in nanoseconds
#define ONE_INTERRUPT  999993482  // for example

ISR(TIMER2_OVF_vect)
{
    static uint32_t unaccounted_time;

    unaccounted_time += ONE_INTERRUPT;
    while (unaccounted_time >= ONE_SECOND) {
        advance_display_by_one_second();
        unaccounted_time -= ONE_SECOND;
    }
}

ในตัวอย่างด้านบนควอทซ์นั้นเร็วเกินไปเล็กน้อยและซอฟต์แวร์ชดเชยด้วยการทำเครื่องหมาย“ หายไป” ทุกสองสามวัน หากควอตซ์ช้าเกินไปรหัสเดียวกันจะแทนการทำเครื่องหมายสองครั้งทุกๆสองสามวัน

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


ว้าวนั่นเป็นดีไซน์ที่ลื่นจริงๆ! ฉันชอบวิธีที่คุณใส่ภาพถ่ายมากพอที่จะทำให้การออกแบบชัดเจนแม้สำหรับคนอเมริกัน monoglot ที่โง่เง่า :) ฉันชอบที่จะเห็นเอกสารโครงการที่ชัดเจนเช่นนี้!
John Walthour

2
@ JohnWalthour: ขอบคุณ! ตอนนี้คุณสนับสนุนให้ฉันเขียนคำแปล :-)
Edgar Bonet

2
@JohnWalthour: เสร็จแล้ว! ลิงค์นี้ชี้ไปที่การแปลภาษาอังกฤษ
Edgar Bonet

เพียงเพื่อให้ชัดเจนเมื่อคุณพูดว่า "ชิป ATmega มีฮาร์ดแวร์ที่จำเป็นทั้งหมด" นั่นไม่เป็นความจริงเลยเมื่อคุณต้องได้คริสตัลใหม่ ฉันคิดว่าวิธีการแก้ปัญหาของคุณลื่นและไม่ได้แทนที่คริสตัล แต่ฉันก็สับสนเล็กน้อยเมื่อคุณบอกว่าฉันไม่ต้องการฮาร์ดแวร์แล้วหันหลังกลับและบอกว่าฉันต้องเปลี่ยนฮาร์ดแวร์สักชิ้น
Kelly S. French

@ KellyS.French: ประโยคของฉันคือ“ ชิป ATmega มีฮาร์ดแวร์ทั้งหมดที่จำเป็นในการปฏิบัติหน้าที่ของ RTCเอง” (เน้นที่เพิ่ม) แต่สิ่งสำคัญคือต้องสังเกตว่า RTC ส่วนใหญ่รวมถึง DS1307 ที่แพร่หลายต้องใช้คริสตัลภายนอกในการทำงาน ATmega นั้นไม่แตกต่างกัน: มันมีทุกอย่างที่จำเป็นในการแทนที่RTCแต่ไม่ต้องแทนที่คริสตัลที่คุณจะต้องเชื่อมต่อกับ RTC ต่อไป โปรดทราบว่า RTC โมดูลเป็นมากขึ้นกว่าเพียง RTC ขณะที่มันไม่รวมถึงคริสตัล
Edgar Bonet

6

แร่ที่คุณระบุมีความเสถียร 0.3% โดยที่ crystal หรือ oscillator คริสตัล (ดังที่ Ricardo กล่าวไว้) คือ 50ppm มีความเสถียรมากกว่าเดิมหลายเท่า ไม่ต้องพูดถึงอุณหภูมิของแร่ที่น่ากลัว ความร้อนจากแสงแดดจะเปลี่ยน ดังนั้นจึงไม่ควรใช้แร่ในการเก็บเวลาเป็นเวลานาน

ดังนั้นการใช้คริสตัลหรือออสซิลเลเตอร์คริสตัลจะได้รับสิ่งที่คุณต้องการ ไม่ว่าจะใช้มันบน ATmega และตั้งฟิวส์ตามลำดับหรือให้เราเชื่อมต่อกับ RTC


ความเสถียร 50ppm อยู่ที่ 0.005%
Matthew G.

ฉันพูดคุยกับสเป็คนั้นเพื่อให้คำตอบสั้น ๆ หมายเหตุเสถียรภาพกัน Res มีความอดทนมากขึ้นและสามารถปิดค่อนข้าง อย่างที่ John W กำลังประสบ "ส่วนที่เหมาะสมสำหรับงานที่ถูกต้อง"
mpflaga

โอ้ฉันแค่อยากรู้เกี่ยวกับคำศัพท์ @mpflaga ... ใหม่สำหรับฉัน
Matthew G.

4

หากคุณไม่ต้องการใช้ฮาร์ดแวร์เพิ่มเติมเช่นนาฬิกาเรียลไทม์ (เช่น DSDS1307) คุณสามารถปรับปรุงความแม่นยำของเวลาได้อย่างมีนัยสำคัญโดยการปิดการใช้งานอินเตอร์รัปต์ที่ไม่ได้ใช้ทั้งหมด โดยค่าเริ่มต้นร่าง Arduino มาพร้อมกับการขัดจังหวะการเปิดใช้งานต่างๆและบ่อยครั้งที่พวกเขาไม่ได้ใช้จริงร่างของคุณ วิธีที่รวดเร็วที่สุดในการตรวจสอบว่าคุณสามารถทำได้โดยไม่ลองและปิดการใช้งานโดยการออกnoInterrupts();


3
−1 (แม้ว่าสิ่งนี้สมควรได้รับ −4) เพราะ: 1. ยกเว้นว่าคุณต้องการใช้งานจริงการขัดจังหวะทั้งหมดจะถูกปิดใช้งานโดยค่าเริ่มต้นยกเว้น TIMER0_OVF แต่เพียงผู้เดียวซึ่งจำเป็นสำหรับการรักษาเวลา 2. ความแม่นยำในการจับเวลาของ Arduinos นั้นถูก จำกัด ด้วยคุณภาพของตัวสะท้อนความร้อน 3. การขัดจังหวะจะไม่ส่งผลกระทบต่อความแม่นยำของmillis()เว้นแต่คุณจัดการที่จะใช้เวลามากกว่าหนึ่งมิลลิวินาทีในการให้บริการพวกเขาซึ่งในกรณีที่คุณมีปัญหาอื่น ๆ ... 4. การปิดnoInterrupts()กั้นการขัดจังหวะด้วยจะป้องกันไม่ให้millis()เวลาเลย!
Edgar Bonet

2

ฉันเข้าใจว่าวิญญาณจำนวนมากด้วย Arduino กำลังประหยัดและบางครั้งก็ทำให้เกิดปัญหา ฉันใช้ Arduino (และตอนนี้ chipKIT เนื่องจากมี RAM 10 เท่าและความเร็วนาฬิกา 10 เท่า) สำหรับที่ทำงานของฉันและฉันต้องการ "ฟังก์ชั่นอุปกรณ์ต่อพ่วง" เพื่อเพิ่มความเร็วและทำงานให้เร็วที่สุดเท่าที่จะทำได้

ฉันใช้นาฬิกาเรียลไทม์ sparkfun แบบเรียลไทม์ในหนึ่งในโครงการของฉันและฉันมีความสุขมากกับมัน พวกเขายังมี"ตายที่" แตกต่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.