שְׁאֵלָה:
האם ניתן לקרוא לפונקציה באופן אוטומטי כאשר קלט משתנה?
Peter Bloomfield
2014-02-20 06:42:53 UTC
view on stackexchange narkive permalink

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

  int pinValue = LOW; void pinChanged () {//...} בטל התקנה () {pinMode (2, INPUT);} loop loop () {// קרא את הקלט הנוכחי int newValue = digitalRead (2); // האם הקלט השתנה? אם (newValue! = pinValue) {pinValue = newValue; pinChanged (); }}  

למרבה הצער, זה לא תמיד עובד כראוי עבור שינויים קצרים מאוד בקלט (למשל פולסים קצרים), במיוחד אם loop () מריץ קצת לאט.

האם יש דרך לגרום לארדואינו לזהות את שינוי הקלט ולהתקשר אוטומטית לפונקציה שלי?

מה שאתה מחפש זה הפרעה חיצונית
שְׁלוֹשָׁה תשובות:
#1
+26
Peter Bloomfield
2014-02-20 06:42:53 UTC
view on stackexchange narkive permalink

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

בהנחה שאתה משתמש ב- Uno, אתה יכול לעשות זאת כך:

  pin pinChanged () {//...} בטל התקנה () {pinMode (2, INPUT); attachInterrupt (0, pinChanged, CHANGE);} loop loop () {}  

פעולה זו תקרא ל pinChanged () בכל פעם שמתגלה שינוי בהפרעה חיצונית 0. ב- Uno, זה תואם לסיכת GPIO 2. מספור ההפרעה החיצוני שונה בלוחות אחרים, לכן חשוב לבדוק את התיעוד הרלוונטי.

גישה זו אמנם מוגבלת. הפונקציה המותאמת אישית pinChanged () משמשת כשגרה לשבירת שירות (ISR). כלומר שאר הקוד (הכל ב loop () ) נעצר זמנית בזמן ביצוע השיחה. על מנת למנוע הפרעה של תזמון חשוב כלשהו, ​​עליך לשאוף להפוך את ה- ISR למהיר ככל האפשר.

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

לבסוף, אם ה- ISR שלך צריך לשנות משתנים גלובליים בסקיצה, בדרך כלל יש להכריז עליהם כ- נדיפים , למשל:

  נדיפים int someNumber;  

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

לגבי "הפולסים הקצרים" המוזכרים בשאלה, האם יש זמן מינימלי שהסיכה חייבת להיות במצב כדי שהיא תגרום להפרעה? (ברור שזה יהיה הרבה פחות מסקרים, וזה תלוי מה עוד קורה בלולאה)
@sachleen זה יעבוד כל עוד זה לא יקרה במהלך ביצוע פונקציית ISR (כפי שהוסבר בתשובה); לכן 'pinChanged ()' צריך להיות קצר ככל האפשר. מכאן שבדרך כלל הזמן המינימלי צריך להיות הזמן לביצוע הפונקציה `pinChanged () 'עצמה.
+1 לתשובה מפורטת מאוד זו הכוללת את כל הדברים החשובים שיש לדאוג להם בעת שימוש בהפרעות!
בנוסף להכריז על גלובלים משותפים כ"נדיפים ", אם המשתנה הגלובלי רחב יותר מבת אחד, כפי שהוא someNumber, עליך להגן מפני הפרעת שינוי הסיכה המתרחשת בין גישות בתים על ידי התוכנית. אמירה כמו 'someNumber + = 5;' כוללת הוספת בתים נמוכים והוספת בתים גבוהים עם נשיאה כלולה. אסור לחלק את שני אלה (יותר, עבור משתנים רחבים יותר) על ידי הפסקה. כיבוי ההפרעות ושחזורם לפני ואחרי הניתוח (בהתאמה) מספיקים.
@sachleen - לגבי גודל הדופק המינימלי. קשה למצוא תשובה מוגדרת בגיליון הנתונים, אך אם לשפוט לפי העיתוי להפסקות החלפת סיכה, הם נצמדים בתוך חצי מחזור שעון. ברגע שה"הפרעה "נזכרת" היא נותרת זכורה עד שה- ISR יתחיל ויתמודד איתה.
#2
+5
mpflaga
2014-02-24 20:36:06 UTC
view on stackexchange narkive permalink

כל מצב של שינוי בכל סיכה שמוגדרת כקלט דיגיטלי יכול ליצור הפרעה. שלא כמו הווקטורים הייחודיים להפרעות הגורמים על ידי INT1 או INT2, התכונה PinChangeInt משתמשת בווקטור משותף ואז שגרת השירות של Interrupt (aka ISR) עבור הווקטור הזה צריכה לקבוע איזו סיכה התחלפה.

למרבה המזל, ספריית PinChangeInt מקלה על זה.

  PCintPort :: attachInterrupt (PIN, burpcount, RISING); // צרף PinChange Interrupt לסיכה שלנו בקצה העולה // (RISING, FALLING and CHANGGE עובדים עם הספרייה הזו) // ומבצעים את burpcount הפונקציה כאשר סיכה זו משתנה  
#3
  0
Nick Gammon
2015-07-01 07:27:55 UTC
view on stackexchange narkive permalink

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

  בוליאני נדיף מופעל; ISR (ANALOG_COMP_vect) {triggered = true; } הגדרת חלל () {Serial.begin (115200); Serial.println ("התחיל."); ADCSRB = 0; // (השבת) ACME: Analog Comparator Multiplexer הפעל ACSR = bit (ACI) // (Clear) Analog Comparator Interrupt Flag | bit (ACIE) // הפסקת השוואה אנלוגית הפעלה | סיבית (ACIS1); // ACIS1, ACIS0: בחר בחירת מצב הפסקה אנלוגית (טריגר בקצה נופל)} // סוף לולאה setupvoid () {if (מופעלת) {Serial.println ("טריגרד!"); מופעל = שקר; }} // סוף לולאה  

זה יכול להיות שימושי לדברים כמו גלאי אור, שם ייתכן שתצטרך לזהות שינוי מ (למשל) 1V ל -2 V בקלט.

מעגל לדוגמא:

enter image description here

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

עבור יישומים קריטיים לתזמון, זה יכול לתת דיוק מוגבר במקצת.

יישום לדוגמא: הפוך את Arduino לבודק קבלים



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