שְׁאֵלָה:
זמן שמירת השימוש ב- Millis () של Arduino אינו מדויק או נכון?
user3284376
2014-03-10 04:28:49 UTC
view on stackexchange narkive permalink

השתמשתי בארדואינו כדי להקליט כמה נתונים. בשרטוט הארדואינו שלי השתמשתי גם בפונקציה מיליס () כדי שאוכל לעקוב אחר הזמן בו לוקחים כל ערך שאני מודד. עם זאת, שמתי לב שהתזמון אינו נכון. לדוגמא 30 שניות בחיים האמיתיים יוצאות רק כ -10 שניות (דוגמה מורכבת).

האם אני צודק בכך שאומר כי פונקציית ההשהיה של Arduino משפיעה על זמן השמירה באמצעות millis () ? במילים אחרות נניח שיש לי עיכוב של 50ms, האם זה אומר שהפונקציה millis () נעצרת גם למשך אותו זמן ואז ממשיכה וכן הלאה למשך החיבור? שמתי לב לכך כשניסיתי לתכנן כמה נתונים ולגלות שתדירות השיאים בנתונים שלי הייתה תכופה מדי בהתחשב בזמן שחלף. אז אני רוצה לדעת אם זו הסיבה לאי התאמה זו של העיתוי ואם כן, כיצד אוכל לתקן זאת כדי שאוכל לשמור על הזמן בו מתרחשת כל דוגמה? :

  #include <eHealth.h> זמן לא חתום; // שגרת ההתקנה פועלת פעם אחת כשלוחצים על reset: void setup () {Serial.begin (9600); } // שגרת הלולאה עוברת שוב ושוב לנצח: loop loop () {float ECG = eHealth.getECG (); זמן = מילי (); Serial.print (זמן); Serial.print (""); Serial.print (ECG, 5); Serial.println (""); עיכוב (50);}  
האם אתה משתמש באחד מלוחות Uno הרשמיים?
התזמון האמיתי במקום הערכים המורכבים (צג סדרתי החותם את הקווים באופן אידיאלי) עשוי כנראה לעזור להבין מה קורה.
החישוב של 'מיליס ()' מונע על ידי הפרעה, ולכן 'עיכוב ()' לא אמור להשפיע עליו.
יש לי את אותה הבעיה אבל רק כשאני משלב אותה (מילי ()) בקוד מורכב. אני מניח שהמורכבות של הקוד משפיעה על הדיוק שלו באופן שהוא יותר ויותר מתעכב עם מורכבות הקוד. האם יש דרך להימנע מכך? אולי באמצעות מודול RTC מופרד?
שְׁלוֹשָׁה תשובות:
#1
+10
Cybergibbons
2014-03-10 14:15:13 UTC
view on stackexchange narkive permalink

מיליס () מונע הפרעה כך ש עיכוב () לא ישפיע עליו, לפחות לא על לוח מבוסס ATmega.

זה זה לא אומר שגם millis () מדויק לחלוטין. כל סמן של הטיימר אינו בדיוק 1ms, אלא 1.024ms. שגיאה זו מצטברת בהדרגה עד לתיקון. ניתן לראות זאת ביישום מטפל ההפרעה TIMER0_OVF (טיימר 0 הצפה).

מקור נוסף של אי דיוק הוא המתנד / קריסטל עצמו, שאינו בדיוק 16 מגה-הרץ. עם זאת, זה די קרוב וכל עוד הטמפרטורה לא משתנה יותר מדי, הוא יחסית יציב.

האמור לעיל אומר שאתה עשוי להיות בערך 1 ms בחוץ כאשר אתה משתמש ב millis () . זה לא נשמע כמו הבעיה שלך.

בעיה פוטנציאלית אחרת תהיה מה ש- getECG () עושה - זה עשוי להיות איטי מאוד.

  צף eHealthClass :: getECG (בטל) {צף אנלוגי 0; // קרא מאנלוגי ב. Analog0 = analogRead (0); // תשואה להמרה בינארית למתח אנלוגית 0 = (float) אנלוגית 0 * 5 / 1023.0; }  

analogRead () הוא איטי, אבל לא כל כך איטי כדי להשפיע על לולאה כזו.

בעיה נוספת שראיתי אנשים יש כאשר הם משנים את מהירות השעון אך אינם מחליפים נכון את לוחות.טקסט. המשמעות היא שהקבועים המשמשים ביישום millis () שגויים והזמנים שגויים.

אם אתה באמת רוצה לקרוא ערכים כל 50ms, דרך טובה בהרבה ליישום זה לעשות את הפעולות הבאות

  static long lastUpdate; אם (millis () - lastUpdate > 50) {lastUpdate = millis (); // עשה דברים}  

אנחנו באמת צריכים לראות את חותמות הזמן שאתה מקבל. אם אתה באמת רואה שנות ה -30 שמוצגות כ -10, אז יש משהו אחר בעבודה.

שימו לב, עבור ה- Uno, השעון אינו מונע גביש, אלא רק משתמש בתהודה קרמית שהיא פחות מדויקת מגביש.
@jfpoilpret אה טוב לדעת. [אם מסתכלים על הסכימה] (http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf), זה יהיה CSTCE16M0V53-R0 [מכשיר Murata CERALOCK] (http://www.mouser.com / ProductDetail / Murata-Electronics / CSTCE16M0V53-R0 /? Qs = HPA2Xx% 252bU0WhPWbRcNuzhZw ==).
לתהודה יש ​​סובלנות ראשונית ירודה (לרוב 0.5-2%) ויציבות טמפרטורה ירודה, אך אם מכיילים לולאות תזמון בעת ​​השימוש בהן, הם יכולים להיות בסדר כל עוד הטמפרטורה לא זזה.
Millis () עדיין עובד על טיימר שמתקתק כל 1.024ms, אך הם הוסיפו פיצוי שגיאות, בצורה של הגדלה בכל פעם שמשתנה של מד השגיאה נהיה גבוה מדי. אני חושב שזה בעצם האלגוריתם של רומן בלק. אז התזמון צריך להיות הרבה יותר קרוב ל -1 ms בדיוק. Https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring.c
למי שעדיין מעוניין, ראה את ההערה שפרסמתי על תשובתו של ג'רוברט, לא רציתי להשיב בתשובה משלי מכיוון שאין לי תגובה, הרגע ניסחתי מחדש את הבעיה.
'GetECG' מותאם יותר: eHealthClass לצוף :: getECG (void) {return analogRead (0) * 5 / 1023.0; } `
#2
+2
JRobert
2014-03-11 21:08:00 UTC
view on stackexchange narkive permalink

אם הפרעות מופסקות עבור שבר משמעותי כלשהו eHealth.getECG () משך השיחה, הספירה של millis () עשויה להישאר מאחור. אחרת, millis () אמור להחזיר זמן מדויק בהרבה משגיאות ה- 3x שתיארת.

אמרת שהאות שנדגם נראה בתדירות גבוהה יותר ממה שציפית, מה שעלול לקרות אם קצב הדגימה שלך נמוך ממה שהתכוונת. האם אתה מניח שקצב דגימה של 20 הרץ? הלולאה שלך עשויה להימשך זמן ממושך יותר מ- 50ms, אשר תראה בזמנים המודפסים, אך אלה עדיין צריכים לעקוב אחר זמן השעון. אם לא התחשבת בכך אך הנחת 50ms / sample, תראה מהירות ניכרת של הנתונים.

אם זה לא הבעיה, השלב הבא יהיה לעבור בין פלט בזמן שאתה נמצא ב loop () , ומודד את תדירות הגל המרובע המתקבל בעזרת מד תדרים (כמה DVM זולים יכולים לעשות זאת) או 'היקף. בצע את אותו הדבר בעזרת לולאה ריקה () . הניסוי הראשון יהיה קצב הדגימה האמיתי או מרווח הזמן שלך; השני יגיד לך אם millis () (כלומר, תדר timer0) הוא מה שציפית.

שיחקתי עם זה עוד יותר והבנתי שהנושא אינו עם הארדואינו, פונקציית ה- millis () לרוב עובדת טוב מאוד, חלק מהערכים אינם בדיוק 8ms (עיכוב) מלבד מה אמרת שזה צפוי. השגיאה 3x שתיארתי נכונה לגבי הצד של פיתון בדברים שבהם אני משתמש כדי לקבל את הנתונים. כל רעיון ממה זה יכול להיות תוצאה, אני משתמש בפיזריאל של פייתון וזה איטי כמו לעזאזל.
אני לא יודע מספיק על היישום שלך כדי לתת לך יותר מ -1 / [email protected]'d, אבל האם הצד של פייתון מספיק איטי כדי להפיל דוגמאות?
#3
  0
user48711
2015-09-04 01:29:18 UTC
view on stackexchange narkive permalink

אותו דבר כאן. אני יכול להוסיף שאם כיבוי ההפרעות, הזמן שנמדד הוא "זמן אמת". בכל מקרה, אני לא מבין מדוע עיכוב זה, מכיוון שאם הלולאה אורכת זמן רב מדי, בכל מקרה המיליס () צריכים להחזיר ערכי זמן אמת (רק עם מרחק רב יותר בין כל ערך)

למה מתייחס "אותו דבר כאן"? התשובות צריכות לעמוד בפני עצמן, מכיוון ש- StackExchange יכול להזמין דברים מחדש (בניגוד לפורום). אז "אותו דבר כאן" יכול להיות כל דבר, תלוי באיזו תשובה / שאלה התשובה שלך מופיעה מתחת.
פוסט זה יהיה מתאים יותר כהערה, אם כי (יש להודות) חסר לך מוניטין מספיק.
מצטער, אם כי כשאתה עונה למשהו, ברור שהוא מתייחס לפוסט הראשי, אחרת זו תהיה תגובה


שאלה ותשובה זו תורגמה אוטומטית מהשפה האנגלית.התוכן המקורי זמין ב- stackexchange, ואנו מודים לו על רישיון cc by-sa 3.0 עליו הוא מופץ.
Loading...