כשהמפגש הראשון של קהילת החובבים החל לרקום עור וגידים, ניסיתי לחשוב על פרויקטים שאוכל להביא ולדבר עליהם. מכיוון שגם ככה כבר התחלתי לשחק עם ה-ATTiny85, החלטתי לעשות איתו משהו רלוונטי – טיימר למרצים, שיקצוב את זמן ההרצאה שלהם וייתן אינדיקציה בולטת לסיום. הנה הסרטון עם התוצאה הסופית – ובהמשך, התהליך שבו כל זה תוכנן ונבנה…
מההתחלה היה לי ברור שבשביל הרושם החזותי, אשתמש בשורת נוריות LED. המחשבה הראשונית היתה שכל אחת מהן תייצג דקה אחת, מעין "פס אור" שיילך ויתקצר עם חלוף הזמן, אך ממדי ה-Stripboard (הלוח שאליו יולחמו הרכיבים) הגבילו אותי למספר קטן מדי של נוריות LED ושל דקות, ועל כן עברתי לייצוג בינארי. השליטה באורות מתבצעת באמצעות רכיב Serial-to-Parallel מדגם SN74LS164N, בעל שמונה פיני לפלט – כלומר שמונה נוריות LED.
מחשבה נוספת היתה שלקראת סיום הזמן המוקצב, האורות יהפכו מירוקים לצהובים ואז לאדומים. מימוש מושלם של זה היה מחייב נוריות מרובות-צבעים ויותר פינים של ה-ATTiny85 ממה שיכולתי להרשות לעצמי. לכן, הסתפקתי בשתי נוריות LED אדומות עבור שלוש הדקות האחרונות. את הפרטים המדויקים אתאר בהמשך.
"ממשק המשתמש" לכוונון מספר הדקות דרש קצת מחשבה. בעיקרון, לחצן אחד בלבד יכול להספיק – למשל, לחיצה קצרה להוספת דקה, ולחיצה ממושכת להוספה אוטומטית של עוד ועוד דקות, בדומה ללחיצה ממושכת על מקש במקלדת המחשב. מכיוון שהמספר כולל שמונה ביטים בלבד, איפוס יתרחש מעצמו אחרי הדקה ה-255. אבל אם ההוספה האוטומטית בזמן לחיצה ממושכת תהיה מהירה מדי, יהיו הרבה פספוסים – ולעומת זאת, אם היא תהיה בקצב נוח למשתמש, ההגעה למספרים גבוהים (או חזרה לנמוכים) תצריך יותר מדי זמן. לכן החלטתי לשלב לחצן נוסף, שיכפיל את המספר הנוכחי ב-2. בבסיס הבינארי, הכפלה כזו היא בעצם הזחה של כל הביטים מקום אחד שמאלה. גם ללחצן זה יש חזרה אוטומטית, ובשילוב עם לחצן ההוספה אפשר להגיע לכל מספר בדיוק ובמהירות. עם זאת, זה בוודאי לא הפתרון היחיד. האם יש לכם רעיון יותר טוב?
קיצוצים הכרחיים
כאשר התכנון הושלם, הוא הצריך שישה פינים של המיקרו-בקר:
- 2 לרכיב ה-Serial-to-Parallel – אחת ל-data (הביט החדש שנכנס לשמיניה) ואחת ל-clock, שאומר לרכיב מתי לקרוא את מה שיש ב-data.
- 1 לרמקול ה"באזר"
- 1 להחלפה בין נוריות ה-LED האדומות והירוקות
- 2 לקריאת שני הלחצנים
כאשר התחלתי לבצע ניסויים בפועל על מטריצה, גיליתי בדרך הקשה של-ATTiny85 יש בעצם רק חמישה פינים שימושיים לקלט/פלט. הסתבר שעבודה עם השישי, זה שמתפקד ביומיום כפין ה-Reset של המיקרו-בקר, קשה ומוגבלת. כדי להשלים את הפרויקט בזמן, הייתי חייב לקצץ – אז איפה אפשר לקצץ?
אפשרות אחת, שלא חשבתי עליה בעצמי ושהועלתה במפגש על ידי אחד המשתתפים, היא לנצל את פין ה-data שהוזכר קודם לשימוש נוסף. הרי כל עוד ה-clock לא מופעל, לרכיב לא אכפת מה יש ב-data ואפשר לשים שם מתח, אפס או אפילו להפוך אותו לפין קלט של המיקרו-בקר. פרקי הזמן הדרושים לשימוש המקורי של data כל כך קצרים, שההשפעה שלהם תהיה זניחה. למשל, אם ננצל את הפין הזה גם לשליטה ברמקול, סביר להניח שתופעות הלוואי יסתכמו בצרצור עדין פעם בדקה.
הפתרון שאני חשבתי עליו היה אחר. אנחנו רגילים לחשוב על לחצנים במונחים של קלט דיגיטלי, יש/אין מתח, וגישה כזו מחייבת פין קלט דיגיטלי אחד לכל לחצן*. אבל אפשר גם לחשוב במונחים של קלט אנלוגי – כמה מתח. אם היישום מאפשר לנו להתעלם באלגנטיות מהאפשרות של לחיצה בו-זמנית על מספר לחצנים, אנחנו יכולים – בעזרת מחלקי מתח – לדאוג לכך שכל לחצן יעביר מתח שונה, ולאסוף את היציאות של כל הלחצנים לתוך פין קלט אנלוגי אחד ויחיד במיקרו-בקר!
* כמובן, אפשר בתיאוריה לעבוד עם רכיבים מתווכים כמו Multiplexer ולאסוף קלט ממספר רב מאד של לחצנים, אם כי הרכיבים האלה עצמם יתפסו מספר פינים.
הירוק והאדום
כזכור, רציתי שלקראת סיום הספירה-לאחור, האורות יהפכו לאדומים. בחרתי להתרכז בשתי נוריות ה-LED שמסמלות את הביטים הפחות-חשובים (LSB), או את שלוש הדקות האחרונות. מעל כל אחת מהן התקנתי נורית LED אדומה בחיבור "הפוך", וחיברתי את כל הארבע למיקרו-בקר ולרכיב ה-Serial-to-Parallel לפי הסכמה הבאה:
החוט C יוצא מאחד הפינים של המיקרו-בקר והוא משותף לכל ארבע הנוריות – לרגלי הפלוס של הנוריות הירוקות ולרגלי המינוס של האדומות. החוטים B1 ו-B2 מגיעים מהיציאות של רכיב ה-Serial-to-Parallel. כאשר C הוא LOW, הנוריות הירוקות מושבתות, ואילו האדומות מאירות בהתאם למה שיש ב-B1 וב-B2. כאשר C הוא HIGH, האדומות מושבתות והירוקות מאירות – בצורה הפוכה. זאת אומרת, אם למשל B1 הוא LOW, הנורית הירוקה הימנית דווקא תדלוק. קוד התוכנה מטפל, בהתאם לערך שצריך להציג, גם ב-C וגם בהיפוך הביטים B1 ו-B2 בעת הצורך.
חדי העין מביניכם הבחינו בוודאי בדיודה על הלוח. היא הוצבה שם כדי להחליש קצת את עוצמת נוריות ה-LED: רכיב ה-Serial-to-Parallel מוציא כפלט את אותו המתח שהוא מקבל, ודיודה מסוג זה מפילה את המתח ב-0.7 וולט כך שכל נורית מקבלת, בעצם, 4.3 וולט במקום 5. לא משהו חיוני – אפשר היה בהחלט לוותר על זה.
הקוד
קוד התוכנה, שנכתב בסביבת הפיתוח של הארדואינו, נצרב על ה-ATTiny85 בתיווך לוח ארדואינו כמוסבר כאן. אין בו משהו מיוחד, למעט קטע אחד ששווה להתעכב עליו.
אם תפתחו את פנקס הרשימות או יישום דומה ותלחצו ברציפות על מקש מסוים במקלדת, נניח "א", תראו קודם כל את האות א' מופיעה מיד. כעבור כחצי שניה תופיע עוד אחת, ואחריה – ברווחים של רבע שניה, בערך – עוד ועוד א'. את ההתנהגות הזו בדיוק רציתי לשחזר עבור הלחצנים שלי, אז איך מפרקים לחיצה רציפה ל"קליקים" ברווחי זמן משתנים?
התשובה היא מונה, שסופר (בעזרת הפונקציה millis) את אלפיות השניה שעוברות כל עוד לחצן מסוים לחוץ, ומתאפס כאשר הוא לא. בכל פעם שהמונה הזה מגיע למספר שהוגדר מראש – 10 עבור לחיצה ראשונה (בשביל ה-debouncing של הלחצן), 500+ ללחיצה השניה או 250+ לכל לחיצה נוספת, התוכנה מתייחסת לכך כ"קליק". אבל איך היא יודעת באיזו לחיצה מדובר? בעזרת משתנה נוסף, "מצב לחצן", שמתקדם ב-1 עם כל קליק. בתחילת המחזור, ערכו של משתנה המצב 0. כאשר מתקבל מתח דרך הפין האנלוגי, הקוד מקפיץ אותו ל-1 ומתחילה הספירה. בכל פעם שמספר אלפיות השניה הגיע לגבול שהוגדר עבור המצב הספציפי, הקוד מציין קליק ומקפיץ את המצב לבא בתור.
כמובן, אם הקלט מהפין האנלוגי מפסיק, מתבצע איפוס גם של מונה אלפיות השניה וגם של משתנה המצב של הלחצן.
סיכום
בסופו של דבר לא השתמשתי בטיימר כדי להקציב למרצים זמן: הוא פשוט מלחיץ מדי. מפאת קוצר זמן גם לא הכנתי שרטוט הולם למעגל, והוא יצא מאולתר למדי. גם לקוד טרם הספקתי להוסיף הערות, אך הוא בכל זאת מסודר דיו כדי ללמוד ממנו משהו. מי שרוצה לעשות זאת מוזמן להוריד אותו מכאן.
מתי המפגשים? איך מקבלים מידע עליהם?
בעיקרון, בקבוצת הפייסבוק שלנו – http://www.facebook.com/groups/246767148755072/ , או בקבוצת ה-meetup כאן – http://www.meetup.com/Arduino-and-Microcontrollers-in-Israel/ , או בקומונה http://www.tapuz.co.il/communa/userCommuna.asp?communaID=40673&r=1
מגניב, מקורי וגאוני.
נהניתי מאוד במפגש, מקווה לנוסף בקרוב!
בהחלט היה כיף, ואני חושב שגם הפורמט היה בסך הכל טוב – אנחנו פשוט נצטרך, לקראת הפעם הבאה, לחשוב קצת יותר מראש על התכנים ועל אופן ההצגה ביחס לאופי הקהל.
אין לי כרגע זמן לקרוא אני ייקרא מחר אבל אני רואה שאימצת את הרעיון שלי עם הסיכות 🙂
דווקא לא – אלה לא סיכות שם מקדימה, אלא שאריות מהרגליים של הלדים 🙂