กำหนดเวลาความแม่นยำสูงบน Arduino สำหรับการสื่อสารแบบอนุกรม


11

ฉันใช้ Arduino Uno เพื่อส่งข้อมูลเวลาและแรงดันไฟฟ้าผ่านพอร์ตอนุกรมไปยัง Python เพื่อลงจุด อย่างไรก็ตามการกำหนดช่วงเวลาระหว่างการประทับเวลาต่อเนื่องจะเพิ่มขึ้นเมื่อเวลาผ่านไปส่งผลต่อการวางแผนของฉัน นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งเมื่อตั้งค่าอัตรารับส่งข้อมูลเป็น 9600 ซึ่งความแตกต่างของเวลาเริ่มต้นของฉันอาจเป็น 1320 และเพิ่มขึ้นเป็น 16400 หลังจากช่วงเวลาสั้น ๆ เมื่ออัตรานี้เพิ่มสูงสุดถึง 1,150,200 bps การเปลี่ยนแปลงจะช้าลงและสังเกตได้น้อยลงจากประมาณ 1,340 เป็น 1,500 แม้หลังจากการส่งในระยะยาว เวลาทั้งหมดถูกกำหนดในหน่วยไมโครวินาที

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

  1. ฉันจะได้รับความแม่นยำมากขึ้นในเวลา?
  2. ทำให้การเปลี่ยนแปลงในเวลานี้คืออะไร?

นี่คือสิ่งที่ฉันมีอยู่ในปัจจุบัน:

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;    

byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

คุณหมายถึงอะไร "แม่นยำ" เวลาที่ได้รับจากตัวนับจะแม่นยำแม่นยำถูกต้องและมีความละเอียดที่ดี คุณต้องการเวลาที่จะกำหนด (เช่นเดียวกันเสมอ)?
Cybergibbons

ขอโทษใช่ฉันเดาว่านั่นคือสิ่งที่ฉันหมายถึงเพื่อให้ความแตกต่างระหว่างพวกเขาสอดคล้องกันและหากไม่ใช่เหตุผลที่พวกเขาไม่ใช่
user3284376

เพิ่มการประทับเวลาที่ปลาย PC มากกว่า Arduino end หรือใช้โมดูล RTC (นาฬิกาเรียลไทม์) โมดูล RTC นั้นหาซื้อได้ง่ายในเว็บสโตร์ที่หลากหลายเพียงแค่ให้แน่ใจว่าร้านค้าเชื่อมโยงไปยังแผ่นข้อมูล อีกวิธีคือตั้งโปรแกรมตัวจับเวลาและใช้รูทีนการบริการขัดจังหวะเพื่อให้ได้เวลาที่ถูกต้องอย่างสมเหตุสมผล
jippie

อะไรeHealth.getECG()ทำอย่างไร การโทรนั้นจะใช้เวลาเท่ากันตลอดเวลาหรือไม่?
jfpoilpret

คุณสามารถระบุระยะเวลา "ช่วงเวลาที่ค่อนข้างสั้น" ได้นานแค่ไหน? มันเหมือนเดิมเสมอหลังจากรีสตาร์ท Arduino หรือไม่
jfpoilpret

คำตอบ:


4

ใช้ตัวจับเวลาและ ISR (รูทีนการบริการขัดจังหวะ) เพื่อทำให้การจับเวลาแม่นยำยิ่งขึ้น

ลองดูที่ของฉัน1 มิลลิวินาทีหมดเวลาพิสูจน์การขัดจังหวะของแนวคิด ความคิดคือการมี 'การเต้นของหัวใจ' 1ms อย่างสมเหตุสมผลในระบบที่สามารถใช้เรียกกิจกรรมอื่น ๆ ใน PoC นั้นใช้เพื่อกระพริบไฟ LED ที่½Hz แต่มีการเข้าถึงตัวแปรใหม่millisecondCounterและsecondCounterช่วยให้คุณสามารถเรียกเหตุการณ์ในลูปหลักในช่วงเวลาใดก็ได้ (ตามเวลาที่กำหนดอย่างถูกต้อง)


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

@jfpoil ตีความจุดที่น่าสนใจที่คุณทำที่นั่นไม่เคยคิดว่าการขัดจังหวะที่เกิดขึ้นครึ่งทางดึงค่าจาก RAM ฉันจะตรวจสอบการถอดชิ้นส่วนในเย็นวันนี้และอัปเดตบทความ อาจเป็นเหตุผลที่ดีที่จะเขียนบทความอื่นด้วย: o)
jippie

ฉันสร้างตัวอย่างจาก PoC ของคุณและสามารถเห็นปัญหาเกิดขึ้นอย่างน้อยหนึ่งครั้งทุกๆ 10 วินาทีใน UNO ของฉัน แต่แน่นอนว่าในความเป็นจริงมันขึ้นอยู่กับสิ่งที่คุณทำloop(): ตัวอย่างของฉันมีค่าเป็นมิลลิวินาทีเปรียบเทียบกับค่าการอ่านก่อนหน้าและหากความแตกต่าง> 0 (นอกเหนือจากตัวนับการรีเซ็ตเป็น 0) แสดงข้อความ
jfpoilpret

@jfpoilpret ไม่เคยสังเกตเห็นมันจริงๆ ฉันใช้มันเป็นหัวใจในการตรวจสอบถังอาหารสำหรับแมวของฉันและสร้างแฟลช LED เมื่อแมวของฉันอาจจะผิดหวัง ... ; o) มันจะเปลี่ยนวิธีการใช้ ISR ในอนาคต
jippie

1
มันแสดงให้เห็นคริสตัลที่เชื่อมต่อกับบล็อก ATMEGA16U2 และแร่เชื่อมต่อกับ ATMEGA328P-PU 16U2 สำหรับอินเตอร์เฟสแบบอนุกรม 328P คือ "The Arduino" น่าสนใจพอที่ 16U2 จะสามารถผลักเข็มนาฬิกาไปยังชิปอื่นเช่น 328P
Udo Klein

3

ฉันสามารถนึกถึงบางสิ่งที่อาจส่งผลต่อ "ความสอดคล้อง" ของการกำหนดเวลาการเขียนแบบอนุกรม:

  • ขนาดของข้อมูลที่จะพิมพ์

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

การแก้ไข: พิมพ์ฟอร์แมทสตริงเป็นความยาวที่รู้จัก

  • ใช้บัฟเฟอร์แบบอนุกรม

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

วิธีแก้ปัญหา: ใช้ซีเรียลนัมเบอร์ที่ไม่มีบัฟเฟอร์ ( เช่น : กับ Darwin / OSX /dev/cu.usbmodemXXXแทนที่จะเป็น/dev/tty.usbmodemXXX)

  • ลำดับความสำคัญของตัวจับเวลา

ดูเหมือนว่าคุณจะใช้การขัดจังหวะ TC และ AVR มีลำดับความสำคัญในการจัดการขัดจังหวะฉันไม่ทราบลำดับความสำคัญสำหรับ Atmega328 และไม่ใช่หนึ่งในคุณลักษณะที่มีการบันทึกไว้มากที่สุดดังนั้นฉันจึงไม่ทราบ TC0 ปลอดภัยแค่ไหนกับการขัดจังหวะโดย UART

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

  • ข้อมูลที่คุณอ่านจะใช้เวลาในการอ่านนานกว่า

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

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

  • หลีกเลี่ยงค่าใช้จ่ายกรอบ arduino

แต่ถ้าคุณจริงๆต้องการเพิ่มประสิทธิภาพการส่งออกอนุกรมจาก Arduino ที่คุณควรหลีกเลี่ยงการใช้ค่าใช้จ่าย Arduino ... แต่มันเป็นวิธีที่น้อยหรูหราและสะดวกสบายในการใช้งาน

ฉันค่อนข้างแน่ใจว่ามีประเด็นอื่น ๆ ที่ฉันขาดไป แต่นั่นคือสิ่งแรกที่ฉันจะตรวจสอบก่อนที่จะขุดต่อไป

HTH


2

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

ปัญหาต่อไปคือ UNO มีช่วงเวลาที่แย่มาก ดูที่นี่สำหรับการเปรียบเทียบ Arduino ชนิดต่างๆกับการอ้างอิงเวลา DCF77

สรุป: หากคุณต้องการเวลาที่แม่นยำไม่ว่าจะเป็น Arduino ด้วยคริสตัลหรือไปหา RTC ฉันขอแนะนำ DS3231 / DS3232 RTCs เนื่องจากสิ่งเหล่านี้มักจะให้ความแม่นยำ 2 ppm นอกกรอบ

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