מה נלמד כאן
- איך מערכת יודעת מי לחץ ראשון כששניים לחצו כמעט יחד
- מה זה דגל (flag) — משתנה שזוכר ״כבר קרה״
- הבלוק repeat until — לולאה שיודעת מתי לעצור
- לסרוק ארבעה כפתורים ולתת עדיפות לראשון
- להדליק נורית ולהפעיל זמזם לפי מי שניצח
מי לחץ ראשון?
ראיתם פעם תוכנית חידונים בטלוויזיה? המנחה שואל שאלה, וארבעה מתחרים מנסים ללחוץ על הכפתור שלהם. הכי מהיר מקבל את הזכות לענות — צליל מצלצל ונורית נדלקת מעליו.

וכאן מתחבאת שאלה מעניינת: מה קורה כששני מתחרים לוחצים כמעט באותו רגע? ההפרש ביניהם עשוי להיות אלפית שנייה. העין של המנחה לא תראה את זה לעולם — אבל הלוח כן, כי הוא בודק את הכפתורים אלפי פעמים בשנייה.
בשיעור הזה אתם בונים לחצן חידון לארבעה שחקנים. הרכיבים מוכרים — כפתורים משיעור 4, נוריות משיעור 1 וזמזם פעיל משיעור 8 — אבל הרעיון החדש הוא נעילה: איך גורמים לכך שרק הלחיצה הראשונה תיחשב, וכל השאר ייזרקו.
הרכיבים
ארבעה כפתורים
כל כפתור מחובר כמו שאתם כבר מכירים: צד אחד ל-GND, הצד השני לפין ולנגד 10kΩ שמוביל ל-5V. לחוץ = 0, משוחרר = 1.
- שחקן 1 — פין 5
- שחקן 2 — פין 16
- שחקן 3 — פין 17
- שחקן 4 — פין 18
ארבע נוריות
לכל שחקן נורית משלו, כל אחת דרך נגד 220Ω:
- שחקן 1 — פין 19
- שחקן 2 — פין 23
- שחקן 3 — פין 12
- שחקן 4 — פין 13
הזמזם הפעיל
זמזם שמצפצף ברגע שמגיע אליו מתח — לא צריך לנגן לו שום מנגינה. כאן הוא מחובר דרך טרנזיסטור S8050, רכיב קטן שמתפקד כמו ברז: הלוח נותן אות חלש לפין 14, והטרנזיסטור פותח בשבילו את הזרם החזק מ-5V שהזמזם צריך.

החיבור

צריכים: לוח ESP32, שני לוחות ניסוי, ארבעה כפתורים, ארבע נוריות, זמזם פעיל, נגד 10kΩ ונגדי 220Ω.
- חברו את פסי החשמל של שני לוחות הניסוי זה לזה — אדום לאדום, כחול לכחול. אחרת החצי השני של המעגל פשוט לא יקבל חשמל.
- כפתורים — כל אחד לפין שלו (5, 16, 17, 18) עם נגד מעלה ל-5V.
- נוריות — הרגל הארוכה דרך נגד אל הפין שלה (19, 23, 12, 13), הרגל הקצרה ל-GND.
- זמזם — דרך הטרנזיסטור אל פין 14.
זה הפרויקט הגדול ביותר בפרק. סדרו את הכפתורים בשורה, ואת הנורית של כל שחקן ממש מעל הכפתור שלו — כך יהיה ברור מי ניצח.
הבלוקים

התוכנית מחולקת לשלושה חלקים, ובתמונה הם זה לצד זה: ראשי (שמאל), checkWinner (אמצע) ו-win (ימין).
שני המשתנים
לפני הכל צריך להכיר שתי קופסאות:
winner — מספר השחקן שניצח. 0 אומר ״עדיין אף אחד״.
flag — הדגל. משתנה שכל תפקידו לזכור תשובה אחת: האם כבר מישהו לחץ? 0 = עוד לא, 1 = כן, נעול.
דגל הוא רעיון שחוזר בכל התכנות. תחשבו על שלט ״תפוס״ על דלת שירותים: הוא לא עושה כלום בעצמו, אבל כל מי שמסתכל עליו יודע מיד אם להיכנס.
התוכנית הראשית
set [winner] to (0) ו-set [flag] to (0) — מתחילים נקי.
set digital pin [19] to [low], וכך גם 23, 12 ו-13 — מכבים את ארבע הנוריות, כדי שלא יישאר אור מהסיבוב הקודם.
repeat until (flag = 1) — בלוק עוטף חדש. הוא דומה ל-forever, אבל יש לו חריץ משושה לתנאי, והוא חוזר על עצמו רק כל עוד התנאי לא מתקיים. ברגע שהדגל עולה ל-1, הלולאה נגמרת, והמערכת נעולה עד שילחצו Reset על הלוח.
בתוך הלולאה שני בלוקים בלבד:
- checkWinner — בלוק ורוד שאתם הגדרתם. הוא בודק את כל ארבעת הכפתורים.
- if (winner != [0]) then → win — אם מישהו ניצח, מפעילים את בלוק ה-win.
הסימן != אומר ״לא שווה״. כלומר: ״אם winner הוא כבר לא אפס״.
define checkWinner
באמצע התמונה. ארבעה בלוקי if כמעט זהים, אחד לכל כפתור. הנה הראשון:
if (read digital pin [5] = [0]) then
ובתוכו:
- wait (200) milliseconds — נותנים למגע להתייצב
- wait until (read digital pin [5] = [1]) — מחכים שהאצבע תתרומם
- if (flag = [0]) then — וזה הלב של השיעור! רק אם הדגל עדיין למטה:
- set [flag] to (1) — מרימים את הדגל
- set [winner] to (1) — רושמים שזה שחקן 1
הבדיקה הפנימית if (flag = 0) היא הנעילה. השחקן הראשון שמגיע לכאן מוצא דגל מורד, כותב את המספר שלו, ומרים את הדגל. כל מי שיגיע אחריו ימצא דגל מורם — והתנאי יהיה ״לא נכון״, אז שמו לא ייכתב. הראשון מנצח, והשאר לא יכולים לדרוס אותו.
שלושת הבלוקים הבאים זהים לגמרי, רק עם פין 16 ו-winner 2, פין 17 ו-winner 3, פין 18 ו-winner 4.
define win
בצד ימין. ארבעה בלוקי if, אחד לכל שחקן:
if (winner = [1]) then
- set digital pin [19] to [high] — נורית שחקן 1 נדלקת
- set digital pin [14] to [high] — הזמזם מתחיל לצפצף
- wait (200) milliseconds — חמישית שנייה של צליל
- set digital pin [14] to [low] — הזמזם משתתק
שימו לב מה לא קורה כאן: אף אחד לא מכבה את הנורית. היא נשארת דולקת — היא התוצאה. הזמזם, לעומת זאת, מצפצף רגע ומפסיק, כי צליל אינסופי יהיה מעצבן מאוד.
שלושת ה-if הנוספים עושים בדיוק אותו דבר עם פינים 23, 12 ו-13.
מריצים
⬇ להורדת הקובץ Quiz_Buzzer.sb3 — גוררים אותו לתוך ACECode ולוחצים Upload.
ההסבר המלא על צריבה נמצא בשיעור ההתקנה.

לחצו על הכפתור הראשון. ביפ — והנורית הראשונה נדלקת. עכשיו לחצו על כל השאר: שום דבר לא קורה. המערכת נעולה.
כדי להתחיל סיבוב חדש, לחצו על כפתור ה-RST שעל הלוח עצמו. הכל מתאפס והמשחק מתחיל מחדש.
עכשיו הביאו חבר ונסו ברצינות: שניכם לוחצים ״עכשיו!״ באותו רגע. תראו שתמיד יש מנצח אחד בלבד — גם כשאתם בטוחים שלחצתם יחד.
מה קרה כאן
בניתם מערכת שפותרת בעיה שלא נתקלתם בה עד היום: מה קורה כששני דברים מתחרים על אותו משאב.
הפתרון הוא בשלושה חלקים:
- סריקה — checkWinner עובר על ארבעת הכפתורים בזה אחר זה, אלפי פעמים בשנייה. כל כך מהר שזה נראה כאילו הוא בודק את כולם בו-זמנית.
- דגל — flag הופך את התוצאה לסופית. הבדיקה if (flag = 0) היא שער שנסגר אחרי שעוברים בו פעם אחת.
- עצירה — repeat until (flag = 1) מפסיקה את הלולאה, כך שגם לחיצות מאוחרות לא ייקלטו בכלל.
התבנית הזאת נמצאת בכל מקום: בהזמנת כרטיסים להופעה, בהרשמה לחוג, בכל מקום שבו יש מקום אחד והרבה מבקשים אותו.
תרגילים
צפצוף ארוך יותר. שנו את wait (200) milliseconds בתוך בלוק win ל-(1000). עכשיו הצליל נמשך שנייה שלמה — הרבה יותר דרמטי.
צפצוף כפול למנצח. הוסיפו בתוך אחד מה-if של win עוד רצף: set digital pin [14] to [high], wait (150) milliseconds, set digital pin [14] to [low]. קיבלתם ״ביפ-ביפ״.
שחקן חמישי. חברו כפתור נוסף לפין פנוי ונורית נוספת. הוסיפו בלוק if חמישי ב-checkWinner (עם winner 5) ובלוק if חמישי ב-win. שימו לב כמה קל להרחיב כשהתוכנית מסודרת בבלוקים נפרדים.
הסירו את הנעילה — ותראו למה היא הכרחית. גררו החוצה את הבלוק if (flag = 0) ב-checkWinner והשאירו רק את שני בלוקי ה-set. העלו והריצו. עכשיו כל לחיצה דורסת את הקודמת, והאחרון מנצח במקום הראשון. תחזירו אותו למקום — ותבינו בדיוק מה עשתה שורה אחת.


