אחרי שעברנו איכשהו את תלאות ההתקנה וההגדרות הראשוניות והצלחנו להבהב בלד, הגיע הזמן לעשות משהו שימושי עם ה-PIC12F675: בואו נבנה "מנעול אלקטרוני" עם קוד סודי, ונלמד על הדרך איך מבצעים קלט ופלט בסיסיים עם הג'וק שלנו.
תיאור המערכת
פרט למיקרו-בקר עצמו, החומרה הדרושה עבור המנעול האלקטרוני שלנו היא שלושה לחצנים פשוטים, שני לדים (אחד אדום ואחד ירוק), נגד או שניים (בהתאם לסידור) של כ-220R עבור הלדים, וכן מטריצה וכמה חוטים כדי לחבר את הכל.
כל אחד מהלחצנים ייצג מספר אחר – נניח 1, 2 ו-4 (למה דילגתי על 3? כדי לקבל את הערכים הבינאריים ה"נקיים" 001, 010 ו-100 שתואמים את הביטים של פיני הקלט השונים, כפי שתראו מיד). נגדיר בתוכנה שלנו "קוד סודי", רצף כלשהו שמורכב משלושת המספרים הללו. כל עוד הרצף הזה לא הוקש במלואו, הלד האדום ידלוק; עם השלמת הרצף, הלד האדום יכבה והלד הירוק ידלוק למשך שניה אחת, ושוב מהתחלה.
למען הסדר והנוחות, נחבר את הקלט משלושת הלחצנים לפינים GP0-GP2 (פינים מס' 7, 6 ו-5 בג'וק, בהתאמה), את הלד האדום ל-GP4 (פין 3) ואת הירוק ל-GP5 (פין 2).
הרגיסטרים
את הרגיסטר הראשון שניעזר בו הכרנו כבר בפרויקט ה-Blink: הוא נקרא GPIO, והוא זה שמאפשר לנו לכתוב ערכים לפינים או לקרוא אותם מהם. ששת הביטים הנמוכים (0-5) של הרגיסטר הזה "מחוברים" לפינים GP0-GP5 של המיקרו-בקר, אם כי פין GP3 הוא גם פין האתחול (MCLR) ולכן לא ניגע בו בינתיים.
הרגיסטר החשוב השני הוא TRISIO, קיצור של Tri-State I/O. לכל פין יש 3 מצבים אפשריים: פלט גבוה, פלט נמוך, או קלט. סידור הביטים ב-TRISIO זהה לזה שב-GPIO; כאשר ביט מסוים הוא 0, הפין התואם פועל כפין פלט, וכאשר הביט הוא 1, הפין הוא קלט (שימו לב, זה ההיפך מהמוסכמה שקיימת במיקרו-בקרים ממשפחת AVR, כמו ה-ATtiny85). את פין GP3 יוצא הדופן, אגב, אי אפשר להגדיר כפין פלט.
הרגיסטר השלישי לא באמת חיוני למערכת שלנו, אך הוא יכול לחסוך לנו רכיבי חומרה: זהו הרגיסטר WPU (ראשי תיבות של Weak Pull-Up), שמאפשר לנו להגדיר נגד pull-up פנימי לפינים GP0, GP1, GP2, GP4 ו-GP5. כשהקלט מלחצן מסוים "צף", כלומר כשהלחצן אינו לחוץ ואינו מחבר את הפין לשום דבר, הנגד הפנימי יבטיח לנו קריאה של מתח "גבוה". כשהמשתמש ילחץ על הלחצן, יווצר חיבור של הפין לאדמה (ראו בשרטוט), ומכיוון שההתנגדות של הנתיב הזה נמוכה הרבה יותר מההתנגדות של הנגד הפנימי, הפין ירגיש מתח "נמוך" ("לוגיקה הפוכה").
עוד נקודה אחת קריטית: ברגיסטר OPTION_REG יש ביט בשם GPPU (הביט השביעי, העליון, השמאלי או MSB – איך שלא תקראו לזה 🙂 ) שמאפשר או מונע את השימוש בנגדי pull-up פנימיים. כדי שהעסק יעבוד כמו שצריך, עלינו לוודא שערך הביט הזה הוא 0.
הנה הגדרות האתחול של הרגיסטרים האלה עבור המערכת:
OPTION_REG &= 127; TRISIO = 7; WPU = 7; GPIO = 16;
המספר 127 בבינארי הוא 01111111; פעולת AND איתו על הרגיסטר OPTION תהפוך ל-0 את הביט הגבוה (GPPU) ותאפשר לנו לעבוד עם נגדי ה-pull-up הפנימיים.
המספר 7 בבינארי הוא 111, כלומר שלושת הביטים הנמוכים ב-TRISIO וב-WPU יהפכו ל-1 (ויגרמו לפינים GP0-GP2 להפוך לפיני קלט עם נגד pull-up מופעל). הערך 16, שהוא 10000 בבינארי, יגרום לביט הרביעי – מתחילים מאפס, זוכרים? – ב-GPIO להיות 1, וכך הלד האדום יידלק. זהו, עכשיו אפשר לגשת ל-
הלוגיקה של המנעול
הקוד הסודי נשמר כמערך קבוע (const) של משתנים מטיפוס char. ניתן להגדיר מערך כזה בלי לציין במפורש את האורך שלו: למידע הזה אפשר יהיה להגיע אחר-כך בקוד עם הפונקציה sizeof. נשמור גם משתנה אינדקס, שיזכור באיזה מקום במערך אנחנו נמצאים בכל רגע נתון.
בלולאה הראשית, אחרי אתחול הרגיסטרים והמשתנים והדלקת הלד האדום, נבצע במחזוריות את הפעולות הבאות:
- נמתין שהמשתמש ילחץ על משהו (לא לשכוח debounce!)
- אם הלחיצה שלו תואמת את הספרה הנוכחית בקוד, נגדיל את האינדקס באחד.
- אם האינדקס שווה לאורך הקוד הסודי, סימן שהקוד כולו הוקש כהלכה – נדליק לרגע את הלד הירוק ולאחר מכן נתחיל הכל מהתחלה.
- לעומת זאת, אם הלחיצה לא תואמת את הספרה הנוכחית בקוד, נחזיר את האינדקס לאחור.
- נחכה שהמשתמש יעזוב את הלחצנים (גם כאן, debounce!).
והנה מלכודת קטנה: בשלב 4, כשכתבתי "נחזיר את האינדקס לאחור", אני לא מתכוון בהכרח שנאפס אותו, כי הדבר ייצור בעיה בתפקוד המנעול! מי רוצה לעצור עכשיו ולחשוב למה?
נניח שהקוד הסודי הוא אחת-שתיים. אם לחצתי 1, זה תואם והאינדקס עולה למספר הבא (2). אם לחצתי שוב 1, זה כבר לא תואם – אבל אם אחזיר את האינדקס לאפס, הלחיצה האחרונה שלחצתי על 1 "תלך לאיבוד", ואם אמשיך עם 2 זה לא ייקלט כקוד שלם. לכן צריך לבדוק אם הלחיצה השגויה זהה למספר הראשון בקוד או לא. אם לא, נחזיר את האינדקס למיקום אפס – אבל אם כן, צריך להחזיר אותו למיקום מס' אחד.
הקוד המלא
הנה הקוד המלא של תוכנת המנעול, ואחריו וידאו של העסק בפעולה.
// For MPLAB X with the XC8 Compiler // by Ido Gendel (info AT idogendel.com) // Connections : Red LED to GP4, Green LED to GP5 // Three momentary buttons from GND to GP0-GP2 #define _XTAL_FREQ 4000000 #include #pragma config FOSC = INTRCIO #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = OFF #pragma config BOREN = OFF #pragma config CP = OFF #pragma config CPD = OFF #define redLedIO 4 #define greenLedIO 5 char buttonInput() { // Reversed logic reversed... return 7 - (GPIO & 7); } int main() { const char secretCode[] = {1, 2, 4 ,2 ,1}; char codeIndex; ANSEL = 0; CMCON = 7; ADCON0 = 0; TRISIO = 7; OPTION_REG &= 127; WPU = 7; while (1) { GPIO = 1 << redLedIO; // Red LED pin High codeIndex = 0; while (codeIndex < sizeof(secretCode)) { // Wait for any input, then debounce while (!buttonInput()) ; __delay_ms(10); // Check input if (buttonInput() == secretCode[codeIndex]) codeIndex++; else codeIndex = (buttonInput() == secretCode[0]) ? 1 : 0; // Wait for button release, then debounce while (buttonInput()) ; __delay_ms(10); } // while // Correct combination sequence GPIO = 1 << greenLedIO; // Green LED pin High __delay_ms(1000); } // while return 0; } // main
האם קיים מכשיר כלשהו שפשוט לא מכיל יותר ממקשים וניתן לנשיאה כדי לכתוב טקסטים בכל זמן וכשרוצים להוריד את החומר פשוט לחבר למחשב ולהזין אוטומטית
תודה – ישראל
למיטב ידיעתי לא קיים – הדבר הכי קרוב הוא אולי טלפרינטר, וזו טכנולוגיה שמיצתה את עצמה עם הופעת המחשבים האישיים… 🙂
תודה רבה
שכחתי להוסיף שקיים משהו דומה של דב מורן -מקלדת עם מסך חיווי -והבנתי שהפרויקט לא ממש הצליח ומעניין אותי אם קיים חיקוי כלשהו
המקלדת ההיא בין הגאדג'טים התמוהים ביותר שראיתי 😀 בכל אופן לא ידוע לי על מוצר דומה וקשה לי לדמיין שוק שיצדיק פיתוח שלו…
בניתי הכל וזה עובד מצוין !!
רק לא הבנתי בקוד איפה הגדרתה כל כפתור איך הוא נקרא …אני רוצה לחבר 9 לחצנים כדי שהקוד יהיה משמעותי
בשיטה שמוצגת כאן אי אפשר לחבר יותר משלושה לחצנים, כי יש למיקרו-בקר הזה רק 5 פיני קלט/פלט, ושניים מהם תפוסים על ידי הלדים.
כדי לממש מנעול עם יותר לחצנים צריך לעבור לשיטות קלט מורכבות ומתקדמות יותר, כגון מערכי נגדים שימירו לחיצות שונות למתחים חשמליים שונים. מצד שני, אם אתה רוצה קוד קשה יותר לפיצוח, אתה תמיד יכול להגדיל את האורך שלו במקום להוסיף לחצנים… 🙂
נכון אבל אני יגיד לך מה אני די חדש במיקרו בקרים ואני מנסה דרך הקוד הזה ללמוד כמה שיותר על קלט ופלט כי חיברתי וצרבתי והכל עובד אבל הבנתי בקוד הכל חוץ מאיפה ההגדרה של הלחצנים
אני לא רואה פה איזה השמה של הערכים כמו ששמתה במערך
לא הגדרתי את הלחצנים במפורש בשום מקום. אני פשוט יודע שהם מחוברים לפינים מסוימים ברגיסטר GPIO, אז אני קורא את הביטים הרלוונטים מהרגיסטר הזה כדי לדעת מי לחוץ ומי לא. זה מה שנעשה באמצעות החישוב הקטן בפונקציה buttonInput .
אה הבנתי , תודה רבה רבה אחלה מדריך !!!