תוכן עניינים:

תפריט בארדואינו ואיך להשתמש בלחצנים: 10 שלבים (עם תמונות)
תפריט בארדואינו ואיך להשתמש בלחצנים: 10 שלבים (עם תמונות)

וִידֵאוֹ: תפריט בארדואינו ואיך להשתמש בלחצנים: 10 שלבים (עם תמונות)

וִידֵאוֹ: תפריט בארדואינו ואיך להשתמש בלחצנים: 10 שלבים (עם תמונות)
וִידֵאוֹ: Control 10 output pins or relay using 10 push button switch with 1 Arduino input pin ANPB-V2 2024, נוֹבֶמבֶּר
Anonim
תפריט בארדואינו ואיך להשתמש בלחצנים
תפריט בארדואינו ואיך להשתמש בלחצנים

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

במדריך זה נלמד על כפתורים! אנו צריכים לדעת:

  • איך לחבר אותם
  • קריאת הערך שלהם
  • דחה, ולמה זה חשוב
  • יישום מעשי (יצירת תפריט)

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

מוּכָן? בואו נתחיל!

שלב 1: הגדרת הלוח

הגדר את הלוח
הגדר את הלוח
הגדר את הלוח
הגדר את הלוח

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

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

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

שלב 2: הוסף את הכפתור והנגד

הוסף את הכפתור והנגד
הוסף את הכפתור והנגד
הוסף את הכפתור והנגד
הוסף את הכפתור והנגד
הוסף את הכפתור והנגד
הוסף את הכפתור והנגד

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

מניחים את הרכיב באמצע לוח הלחם. אופן הפעולה של כפתור הוא:

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

זו הסיבה שאנו שמים את הרכיב על פני החלל באמצע. הוא מוודא שהפינות אינן מחוברות מתחת לסיכות בלוח.

השלב הבא מספק כמה תמונות הממחישות נקודות אלה.

מקם את הנגד מהסיכה הימנית התחתונה על פני העמודים, כך שהוא יושב אופקית.

שלב 3: חיבורי לחצנים

חיבורי כפתורים
חיבורי כפתורים
חיבורי כפתורים
חיבורי כפתורים

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

עכשיו, נוסיף את החוטים.

  • הצב מוביל אדום מסיכת חשמל חיובית לאותה העמודה כמו הסיכה הימנית התחתונה בכפתור
  • מקם עופרת שחורה מסיכת חשמל שלילית לאותה העמודה של הנגד.
  • הנח חוט צבעוני (לא אדום/שחור) מהסיכה השמאלית העליונה אל פין דיגיטלי 2 על הארדואינו

בדוק את התמונות שלמעלה כדי לוודא שהחיווט שלך תקין.

שלב 4: הקוד …

הקוד…
הקוד…
הקוד…
הקוד…

בואו נסתכל על הקוד לכפתור בסיסי.

פתח את עורך הקוד ושנה מחסימות לטקסט. נקה את האזהרה שעולה. אנו מרוצים מהטקסט!

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

הכנסתי כמה הערות נוספות לקוד למטה, כך שקל יותר לקרוא אותו מאשר התמונה.

// הגדר קבועים

כפתור הגדרת #2 הגדרת חלל () {pinMode (כפתור, קלט); Serial.begin (9600); } לולאת void () {// קראו את הסיכה הדיגיטלית כדי לבדוק את מצב הכפתור int לחוץ = digitalRead (כפתור); // הלחצן מחזיר HIGH אם לוחצים עליו, LOW אם לא אם (לחץ == HIGH) {Serial.println ("לחצו!"); }}

אוקי, זה עובד!

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

תכונה אחת שתראה בקוד למעלה היא הערכת מצב אם (). כל מה שהקוד עושה הוא לשאול שאלה ולהעריך אם היא נכונה, במקרה הזה. אנו משתמשים בסימן שווה (סימני שוויון כפולים, כך: ==) כדי לבדוק אם ערך המשתנה שווה לערך מסוים. A DigitalRead () מחזירה HIGH או LOW.

באמצעות if () else if / else נוכל לבדוק תנאים רבים או את כל התנאים, ואם תחזור ליסודות Arduino, תראה כמה מההשוואות שתוכל לבצע.

עכשיו … הקוד שלנו עשוי להיראות שלם … אבל יש לנו בעיה.

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

בואו נתקן!

שלב 5: קצת Debounce

דבון קטן
דבון קטן

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

בואו נסתכל על הקוד:

#הגדר כפתור 2#הגדר debounce Timeout 100

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

long int lastDebounceTime;

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

איננו צריכים לשנות דבר בפונקציית הגדרת הריק (). בוא נשאיר את זה.

לולאת void () {// קראו את הסיכה הדיגיטלית כדי לבדוק את מצב הכפתור int לחוץ = digitalRead (כפתור); long int currentTime = millis (); // קוד כפתור}

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

כעת עלינו לוודא שאנו מודעים לזמן מאז נלחץ על הכפתור, כך שנאפס את הטיימר כאשר לא נלחץ עליו. תסתכל:

לולאת void () {// קראו את הסיכה הדיגיטלית כדי לבדוק את מצב הכפתור int לחוץ = digitalRead (כפתור); long int currentTime = millis (); אם (לחוץ == LOW) {// אפס את זמן הספירה בזמן שלא נלחץ על הלחצן lastDebounceTime = currentTime; } // קוד לחצן}

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

לולאת void () {// קראו את הסיכה הדיגיטלית כדי לבדוק את מצב הכפתור int לחוץ = digitalRead (כפתור); long int currentTime = millis (); אם (לחוץ == LOW) {// אפס את זמן הספירה בזמן שלא נלחץ על הלחצן lastDebounceTime = currentTime; } // לחצו על הלחצן במשך זמן נתון אם (((currentTime - lastDebounceTime)> debounceTimeout)) {// אם הגיע הזמן הקצוב, לחץ על הלחצן! Serial.println ("לחץ!"); }}

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

הפעל את הקוד שלך ובדוק אם הוא פועל. אם יש לך שגיאות, בדוק את הקוד שלך!

עכשיו, בואו נסתכל על דוגמא מעשית.

שלב 6: הכנת תפריט

הכנת תפריט
הכנת תפריט

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

לכן, לפרויקט זה אנו צריכים:

  • שלושה כפתורים
  • שלושה נגדים מוגדרים ל- 10kΩ

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

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

חבר את זה, בואו נסתכל על הקוד!

שלב 7: פירוט קוד - גלובלי

אוקיי, זה הולך להיות צעד ארוך, אבל אני אעבור על כל קטע קוד.

ראשית, בואו נסתכל על המשתנים הגלובליים הדרושים.

// הגדר קבועים #הגדר תפריט כפתור 2 #הגדר תפריט בחר 3 #הגדר תפריט שמור 4 #הגדר debounceTimeout 50 // הגדר משתנים int menuButtonPreviousState = LOW; int menuSelectPreviousState = LOW; int menuSavePreviousState = LOW; long int lastDebounceTime; // תפריט אפשרויות char * menuOptions = {"בדיקת טמפ '", "בדוק אור"}; bool featureSetting = {false, false}; bool menuMode = false; bool menuNeedsPrint = false; int optionSelected = 0;

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

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

בלוק אפשרויות התפריט יש כמה תכונות חדשות. ראשית, התו * (כן, כלומר כוכבית מכוונת), שהוא משתנה מילולי של תו/מחרוזת. הוא מצביע לאחסון סטטי בזיכרון. אתה לא יכול לשנות את זה (כמו שאתה יכול ב- Python, למשל). שורת char *menuOptions יוצרת מערך של מילולי מחרוזת. תוכל להוסיף כמה פריטי תפריט שתרצה.

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

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

בואו נסתכל על קבוצת הפונקציות הבאה.

שלב 8: פירוט קוד - הגדרה ופונקציות מותאמות אישית

פונקציית ההתקנה () קלה מספיק, רק שלוש הצהרות קלט:

הגדרת void () {pinMode (menuSelect, INPUT); pinMode (menuSave, INPUT); pinMode (menuSelect, INPUT); Serial.begin (9600); }

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

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

// פונקציה להחזרת האופציה הנוכחית שנבחרה *ReturnOptionSelected () {char *menuOption = menuOptions [optionSelected]; // אפשרות החזרה תפריט החזרה נבחר אופציה; } // פונקציה להחזרת סטטוס האפשרות הנוכחית שנבחרה char *ReturnOptionStatus () {bool optionSetting = featureSetting [optionSelected]; char *optionSettingVal; if (optionSetting == false) {optionSettingVal = "False"; } else {optionSettingVal = "True"; } // אפשרות החזרה הגדרת אופציית החזרהSettingVal; }

הפונקציה char *ReturnOptionSelected () בודקת את האפשרות שנבחרה (אם אתה רואה למעלה, הגדרנו משתנה שיעקוב אחריו), ומושך את המחרוזת מילולית מהמערך שיצרנו קודם לכן. לאחר מכן הוא מחזיר אותו כסוג צ'אר. אנו יודעים זאת מכיוון שהפונקציה מציינת את סוג ההחזרה.

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

// פונקציה להחלפת optionbool הנוכחי ToggleOptionSelected () {featureSetting [optionSelected] =! FeatureSetting [optionSelected]; להחזיר נכון; }

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

שלב 9: הלולאה…

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

לולאת חלל () {

// עשה כאן עבודה <-----}

אוקיי, ראינו את הדברים האלה בעבר:

// קרא את הכפתורים int menuButtonPressed = digitalRead (menuButton); int menuSelectPressed = digitalRead (menuSelect); int menuSavePressed = digitalRead (menuSave); // קבל את הזמן הנוכחי long int currentTime = millis (); if (menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW) {// אפס את זמן הספירה כשלא לוחצים על הלחצן lastDebounceTime = currentTime; menuButtonPreviousState = LOW; menuSelectPreviousState = LOW; menuSavePreviousState = LOW; }

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

הקטע הבא מקנן בתוך הקו

if (((currentTime - lastDebounceTime)> debounceTimeout)) {

// עשה כאן עבודה <----}

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

if ((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)) {if (menuMode == false) {menuMode = true; // הודע למשתמש Serial.println ("התפריט פעיל"); } אחרת אם (menuMode == true && optionSelected = 1) {// אפס option optionSelected = 0; } // הדפס את התפריט menuNeedsPrint = true; // החלף את הכפתור הקודם. ציין להציג רק תפריט // אם הכפתור משוחרר ולוחץ שוב menuButtonPreviousState = menuButtonPressed; // יהיה גבוה}

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

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

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

// menuSelect נלחץ, ספק לוגיפיק ((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)) {if (menuMode) {// שנה את האפשרות שנבחרה // כרגע זה פשוט נכון/שקר // אבל יכול להיות משהו bool toggle = ToggleOptionSelected (); if (toggle) {menuNeedsPrint = true; } else {Serial.println ("משהו השתבש. נסה שוב"); }}} // החלף מצב למעבר רק אם משחררים אותו ולוחצים עליו שוב menuSelectPreviousState = menuSelectPressed; }

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

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

if ((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)) {// צא מהתפריט // כאן תוכל לבצע כל סידור // או לשמור ב- EEPROM menuMode = false; Serial.println ("התפריט יצא"); // החלף מצב כך שהתפריט יוצא רק פעם אחת menuSavePreviousState = menuSavePressed; }}

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

if (menuMode && menuNeedsPrint) {// הדפסנו את התפריט, כך שאם לא יקרה משהו // אין צורך להדפיס אותו שוב menuNeedsPrint = false; char *optionActive = ReturnOptionSelected (); char *optionStatus = ReturnOptionStatus (); Serial.print ("נבחר:"); Serial.print (optionActive); Serial.print (":"); Serial.print (optionStatus); Serial.println (); }

זהו אלגוריתם menuPrint, אשר יורה רק כאשר התפריט פעיל וכאשר המשתנה menuNeedsPrint מוגדר כ- true.

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

ובכן זהו זה! עיין בשלב הבא לכל בלוק הקוד.

שלב 10: בלוק קוד סופי

// הגדר קבועים

#define menuButton 2 #הגדרת תפריט בחר 3 #הגדר תפריט שמור 4 #define debounceTimeout 50 int menuButtonPreviousState = LOW; int menuSelectPreviousState = LOW; int menuSavePreviousState = LOW; // הגדר משתנים long int lastDebounceTime; bool lightSensor = true; bool tempSensor = true; // תפריט אפשרויות char * menuOptions = {"בדיקת טמפ '", "בדוק אור"}; bool featureSetting = {false, false}; bool menuMode = false; bool menuNeedsPrint = false; int optionSelected = 0; // פונקציית התקנה

הגדרת void () {pinMode (menuSelect, INPUT); pinMode (menuSave, INPUT); pinMode (menuSelect, INPUT); Serial.begin (9600); }

// פונקציה להחזרת האפשרות הנוכחית שנבחרה char *ReturnOptionSelected () {char *menuOption = menuOptions [optionSelected]; // אפשרות החזרה תפריט החזרה נבחר אופציה; } // פונקציה להחזרת סטטוס האפשרות הנוכחית שנבחרה char *ReturnOptionStatus () {bool optionSetting = featureSetting [optionSelected]; char *optionSettingVal; if (optionSetting == false) {optionSettingVal = "False"; } else {optionSettingVal = "True"; } // אפשרות החזרה הגדרת אופציית החזרהSettingVal; } // פונקציה להחלפת האפשרות הנוכחית bool ToggleOptionSelected () {featureSetting [optionSelected] =! FeatureSetting [optionSelected]; להחזיר נכון; } // הלולאה הראשית

לולאת void () {// קראו את הכפתורים int menuButtonPressed = digitalRead (menuButton); int menuSelectPressed = digitalRead (menuSelect); int menuSavePressed = digitalRead (menuSave); // קבל את הזמן הנוכחי long int currentTime = millis (); if (menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW) {// אפס את זמן הספירה כשלא לוחצים על הלחצן lastDebounceTime = currentTime; menuButtonPreviousState = LOW; menuSelectPreviousState = LOW; menuSavePreviousState = LOW; } if (((currentTime - lastDebounceTime)> debounceTimeout)) {// אם מגיעים לפסק הזמן, לחצו על הכפתור!

// תפריט הלחיצה נלחץ, ספק לוגיקה

// יורה רק כאשר הכפתור שוחרר בעבר אם ((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)) {if (menuMode == false) {menuMode = true; // הודע למשתמש Serial.println ("התפריט פעיל"); } אחרת אם (menuMode == true && optionSelected = 1) {// אפס option optionSelected = 0; } // הדפס את התפריט menuNeedsPrint = true; // החלף את הכפתור הקודם. ציין להציג רק תפריט // אם הכפתור משוחרר ולוחץ שוב menuButtonPreviousState = menuButtonPressed; // יהיה HIGH} // menuSelect נלחץ, ספק לוגיקה אם ((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)) {if (menuMode) {// שנה את האפשרות שנבחרה // כרגע, פשוט נכון/לא נכון // אבל יכול להיות משהו bool toggle = ToggleOptionSelected (); if (toggle) {menuNeedsPrint = true; } else {Serial.print ("משהו השתבש. נסה שוב"); }}} // החלף מצב למעבר רק אם משחררים אותו ולוחצים עליו שוב menuSelectPreviousState = menuSelectPressed; } אם ((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)) {// צא מהתפריט // כאן תוכל לבצע כל סידור // או לשמור ב- EEPROM menuMode = false; Serial.println ("התפריט יצא"); // החלף מצב כך שהתפריט יוצא רק פעם אחת menuSavePreviousState = menuSavePressed; }} // הדפס את אפשרות התפריט הנוכחית פעילה, אך הדפס אותה רק פעם אחת אם (menuMode && menuNeedsPrint) {// הדפסנו את התפריט, כך שאם לא יקרה משהו // אין צורך להדפיס אותו שוב menuNeedsPrint = false; char *optionActive = ReturnOptionSelected (); char *optionStatus = ReturnOptionStatus (); Serial.print ("נבחר:"); Serial.print (optionActive); Serial.print (":"); Serial.print (optionStatus); Serial.println (); }}}

המעגל זמין באתר Tinkercad. הטמעתי את המעגל למטה, גם לך לראות!

כמו תמיד, אם יש לך שאלות או בעיות, אנא יידע אותי!

מוּמלָץ: