עד כמה millis מדויקת?

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

לאחרונה הובא לידיעתי דיון שעלה בפורום מסוים, בו מישהו דיווח שהארדואינו שלו סטה מספר שניות מהזמן האמתי כעבור שעות ספורות בלבד. כפי שהזכרתי למעלה, כמה מגיבים הפנו אותו אוטומטית ל-RTC, ואחרים האשימו את הקוד שלו. כמובן, ברמת העיקרון, כשמשהו לא עובד – לא משנה מה – יש סיכוי טוב מאוד שהקוד שלנו אשם, אבל במקרה הספציפי הזה הביקורת לא נראתה לי סבירה.

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

איך מודדים כזה דבר? אפשר להוציא אות מחזורי מהארדואינו (למשל ישירות על בסיס טיימר, או אפילו על סמך millis) ולמדוד את המשך האמתי שלו בעזרת סקופ או לוג'יק אנלייזר. ליחידי סגולה יש מכשיר ייעודי ויקר שנקרא Frequency counter, ובהנחה שהוא ראוי לשמו, אפשר להגיע איתו לתוצאות סופר-מדויקות.

אני בחרתי בשיטה אחרת: כדי להתאמן על תכנות ב-Python, שהזנחתי כבר הרבה זמן, כתבתי תוכנה קטנה ששולחת לארדואינו תו דרך ה-Serial כל שנייה (לפי זמן המחשב, שאמור להיות מדויק מאוד), וקולטת מהארדואינו בחזרה את ערך ה-millis הנוכחי שהוא שולח כתשובה. בשני הצדדים חייבים להיזהר מאוד עם הקוד, כי הוא מוסיף עיכובים משלו, ואנחנו גם יודעים שההעברה של מידע ב-UART על פני USB היא לא ממש בזמן-אמתי. אף על פי כן, אם לא עושים שטויות, לאורך זמן ההשפעה היחסית של ה"הפרעות" הקטנות מצטמצמת, ואפשר לראות את המגמה ארוכת-הטווח. הנחתי שתוך שעה-שעתיים יצטברו הפרשים מספיק גדולים כדי להבחין בסטייה של הארדואינו עצמו, אם יש כזו.

צילום מסך של הרצת התוכנה בסביבת הפיתוח pyCharm
צילום מסך של הרצת התוכנה (בסביבת הפיתוח pyCharm, לחצו להגדלה)

לוח הארדואינו הראשון שבדקתי היה חיקוי סיני, ולא הייתי צריך לחכות איתו שעות. למעשה, תוך שניות ספורות כבר הבחנתי במגמה: כל שנייה של זמן אמתי נראתה לו כמו 993 אלפיות השנייה. כלומר השעון שלו היה איטי מדי ב-0.7% – כעשרים וחמש שניות בשעה!

"טוב," חשבתי לעצמי, "סינים" ולקחתי לוח ארדואינו אונו מקורי וגם חדש יחסית. מייד ראיתי שהסטייה צנחה ל… אלפית שנייה כל שנייה! אמנם טוב פי שבעה מהסיני, אבל עדיין, עשירית אחוז – 3.6 שניות בשעה! מה לכל הרוחות קורה כאן? אפילו הגבישים הזולים ביותר אמורים להיות מדויקים פי עשרה מזה, אם לא יותר. הסתכלתי שוב על הלוח…

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

מהודים (resonators) בלוח ארדואינו אונו מקורי מימין וסיני
מהודים (resonators) בלוח ארדואינו אונו מקורי (מימין) וסיני (לחצו להגדלה)

אוקיי, זה מסביר את מה שהופיע בדיון ההוא, ולמעשה השואל אמור להגיד תודה שהארדואינו שלו לא זייף הרבה, יחסית. אבל עכשיו עולה שאלה אחרת: למה היה לי רושם שלוחות הארדואינו הם עם גביש ומדויקים יותר?

חיפוש קצר הוכיח שזו לא סניליות: בכל הלוחות הישנים שאצלי, דגמי Duemilanove וגם Uno סיניים, כן היו גבישים ליד המיקרו-בקר. והדיוק שלהם היה בהתאם: הלוח הכי פחות מדויק מאלה שבדקתי נתן סדר גודל של כ-150 מילישניות בלבד אחרי שעה, שאם נעקוב מספיק זמן זה ייצא 3.6 שניות ביממה. רחוק ממושלם כמובן, אך הרבה-הרבה יותר טוב מלוחות הארדואינו הקמצניים המודרניים.

גבישים בלוחות ארדואינו ישנים יותר
גבישים (crystals) בלוחות ארדואינו ישנים יותר (לחצו להגדלה)

בשביל הקטע, שלפתי מהבוידעם גם את הלוח תואם ה-Arduino Leonardo שקניתי לפני שש שנים במסגרת קמפיין ב-Indiegogo. היוצר של הלוח הזה התקין בו, בדומה ללאונרדו הרשמיים, לא גביש ולא מהוד אלא מה שנראה כמו מתנד (Oscillator), שאמור לתת תוצאות יותר טובות משני האחרים. כעבור 10 דקות, התוכנה שלי הראתה סטייה של 5 אלפיות השנייה בלבד – כ-0.7 שניות ליממה. ארדואינו Nano Every חדש, לעומת זאת, שמסתמך על המתנד הפנימי של המיקרו-בקר, סטה בכ-2.5 אלפיות השנייה כל שנייה.

מתנד אקטיבי (oscillator) בלוח תואם ארדואינו לאונרדו
מתנד (oscillator) בלוח תואם ארדואינו לאונרדו (לחצו להגדלה)

עריכה: בבדיקה נוספת, הסתבר שמה שיש על הלאונרדו הוא גם כן גביש, ברמת דיוק של 30ppm (כלומר סטיה של 30 חלקים למיליון, או עד 2.6 שניות ליממה, לכל היותר – לא כולל וריאציות שמקורן בטמפרטורה או בהתיישנות.)

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

האירוניה הגדולה, או לפחות המעצבנת, היא שאם תסתכלו על כל לוח ארדואינו אונו מודרני, תראו שדווקא כן יש עליו גביש – לא בשביל המיקרו-בקר הראשי, אלא בשביל השבב/מיקרו-בקר שאחראי לתקשורת ה-USB עם המחשב. שם, אי-עמידה בזמנים תגרום לשיבושים שאי אפשר להסוות ולהעלים מהם עין, אז אין ברירה אלא לשים רכיב נורמלי…

להרשמה
הודע לי על
4 תגובות
מהכי חדשה
מהכי ישנה לפי הצבעות
Inline Feedbacks
הראה את כל התגובות

תודה על הפוסט. אגב, כנראה שכשאתה אומר שמישהו העלה בפורום מסויים פוסט על סטייה של כמה שניות אחרי כמה שעות – כנראה שזה הפוסט שאני העליתי לא מזמן;) אז באמת אחרי בערך שלוש שעות הייתה סטייה של בערך 4 שניות, אבל אני חייב לציין שהצלחתי להפוך את זה לסטייה של חצי שנייה(!) בעזרת שינוי קטן בקוד. בהתחלה פשוט בדקתי אם מיליס עלה בשנייה מאז העדכון של המשתנה שמייצג את הערך הקודם של המיליס, כשהעדכון נעשה על ידי השוואה בין המשתנה למיליס הנוכחי. הדרך הזאת בעייתית לטווח הארוך כי: 1)אם בבדיקה נניח שמיליס היה גדול מהמשתנה ב1017, אז בעצם כשמעדכנים את… לקרוא עוד »

תודה על הפוסט.
תוכל להסביר מה ההבדל בין גביש, מהוד ומתנד?