המעבדה
כל מה שחי וזז
🚗 מכונית אוטונומיתמהרכבה ועד מכונית שעוקבת אחרי קו ועוצרת מול מכשול
📶 ESP32בקר עם Wi-Fi ובלוטות' מובנים
🔌 היכרות עם ארדואינוהבקר, התוכנה, החיבורים והקוד הראשון
⚙️ מנוע סרבוסוגי מנועי סרבו שאנחנו עובדים איתם
📚 מאגר הרובוטיקה
📡 חיישניםמרחק, אור, קול, לייזר, טמפרטורה ועוד
🧱 בסיסבקר, מטריצה, חוטים, לדים ולוח הרחבה
📶 תקשורתBluetooth, שלט IR ו־RF433
🛒 רכיבים לקנייהמה כדאי שיהיה לכל תלמיד בבית
🛠️ פרויקטים
🔌 היכרות עם ארדואינו
כל מה שצריך כדי להתחיל עם ארדואינו: בוחרים נושא, או גוללים למטה ללוח האינטראקטיבי ולהבדל בין דיגיטלי לאנלוגי.
🧱 הכרת הרכיבים
💡 הקוד הראשון
🔍 מכירים את הלוח
לוחצים על כל חלק בלוח כדי לגלות מה הוא עושה.
📍 תרשימי הפינים
לפי צבעים: אדום מתח, שחור אדמה, צהוב אנלוגי, ירוק דיגיטלי
על לוח אמיתי: המספר באדום הוא מה שכותבים בקוד
🧩 לוח ההרחבה (Sensor Shield V4.0)
לוח ההרחבה יושב על הארדואינו ונותן לכל פין שלישייה משלו: S אות (הפין עצמו), V פלוס 5V ו־G אדמה. כך כל חיישן או לד מתחבר בכבל אחד של שלושה חוטים, בלי מטריצה ובלי חיפוש אחרי GND פנוי. השורה העליונה היא הפינים הדיגיטליים 0 עד 13, והשורה למטה היא A0 עד A5.
⚡ דיגיטלי או אנלוגי?
רק שתי אפשרויות: 0 או 1. הגרף נראה כמו מדרגות.
digitalRead(2); // 0 or 1 digitalWrite(13, HIGH); // LED on
1024 אפשרויות, מ־0 ועד 1023. הגרף נראה כמו גבעה חלקה.
analogRead(A0); // 0 ... 1023
ארדואינו לא יודע להוציא "חצי מתח". במקום זה הוא מדליק ומכבה את הלד מהר מאוד, 490 פעם בשנייה. העין לא רואה הבהוב, רק אור חלש יותר. ככל שהלד דלוק יותר זמן מכל מחזור, הוא נראה בהיר יותר. עובד רק בפינים עם הסימן ~: 3, 5, 6, 9, 10, 11.
הקו הירוק = מה שהפין באמת עושה (דלוק/כבוי). הקו הצהוב המקווקו = המתח הממוצע, וזה מה שהלד "מרגיש".
💻 התקנת Arduino IDE
ארבעה צעדים, כרבע שעה, ובסוף הלד על הלוח מהבהב בקוד שאתם העליתם. סמנו כל צעד כשסיימתם.
🧭 מה זה IDE?
IDE היא תוכנה אחת שעושה שלושה דברים: עורך שבו כותבים את הקוד, מתרגם (קומפיילר) שהופך אותו לשפה שהבקר מבין, ומעלה שמעביר אותו בכבל ה־USB ללוח. לחצו על המספרים בחלון כדי להכיר כל כפתור.
6void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(1000); digitalWrite(LED_BUILTIN, LOW); delay(1000); }
🪜 ארבעה צעדים
מורידים
באתר הרשמי בוחרים Windows · Win 10 and newer, 64 bits, קובץ התקנה רגיל.
בוחרים macOS Apple Silicon למחשבי M1 ומעלה, או macOS Intel למחשבים ישנים יותר.
בוחרים Linux AppImage 64 bits, ואחרי ההורדה נותנים לקובץ הרשאת הרצה.
יופיע מסך שמבקש תרומה. לוחצים Just Download ומורידים בחינם.
⬇ לדף ההורדה הרשמימתקינים
מריצים את הקובץ: I Agree → Next → Install. אם קופצת שאלה על התקנת דרייבר (Device software), עונים כן. בלי הדרייבר המחשב לא יראה את הלוח.
פותחים את הקובץ וגוררים את Arduino IDE לתיקיית Applications. אם המק אומר שאי אפשר לפתוח: קליק ימני על התוכנה ואז Open.
מריצים את ה־AppImage. אם אין גישה ללוח, מוסיפים את המשתמש לקבוצה dialout ומתחברים מחדש.
מחברים ובוחרים לוח ופורט
מחברים את הארדואינו בכבל USB, ואז בתפריט Tools:
לא בטוחים איזה פורט? מנתקים את הכבל, מסתכלים ברשימה, מחברים שוב. הפורט שנוסף הוא הלוח.
הבדיקה הראשונה: Blink
File → Examples → 01.Basics → Blink
לוחצים על החץ ➜ (Upload). אחרי כמה שניות כתוב למטה Done uploading, והלד L על הלוח מתחיל להבהב פעם בשנייה.
🛠️ משהו לא עובד?
לא מופיע שום פורט ברשימה
כמעט תמיד זה הכבל: הרבה כבלי USB מעבירים רק חשמל, בלי נתונים. מנסים כבל אחר. בלוחות זולים (שבב CH340) צריך גם להתקין דרייבר: מחפשים בגוגל CH340 driver ומורידים מאתר היצרן WCH.
שגיאה בהעלאה: avrdude … not in sync
נבחר פורט או לוח לא נכון, או שמשהו מחובר לפינים 0 ו־1 (הם משמשים להעלאה). מוודאים את Board ו־Port, מנתקים את מה שיושב על 0 ו־1, ומנסים שוב.
שגיאה: was not declared in this scope
שגיאת כתיב בקוד. ארדואינו מבחין בין אותיות גדולות לקטנות: digitalWrite ולא digitalwrite. בודקים גם שלא חסר ; בסוף השורה שלפני.
ההעלאה הצליחה אבל הלד לא מהבהב
בודקים שנבחר Arduino Uno ולא לוח אחר. אם יש לוח הרחבה מעל, הלד L עלול להיות מוסתר. מסתכלים מהצד.
🚗 מכונית אוטונומית
כל השלבים בבניית המכונית: הרכבה, מנועים, נסיעה וחיישנים.
🔧 הרכבת המכונית10 שלבים, מהפלטה ועד נסיעה
חיבור גלגלים לגשר Hשני מנועים ביציאה אחת
קדימה ואחורהשנייה קדימה, שנייה אחורה
פניותימינה, עצירה, שמאלה
עוקב קומכונית שנוסעת על קו שחור
📡 חיישנים
📶 ESP32-S3
הבקר של החלק השני בקורס. קטן כמו אצבע, אבל חזק פי כמה מהארדואינו, ועם Wi-Fi ובלוטות' בפנים, כך שהפרויקטים יכולים לדבר עם הטלפון, עם האינטרנט ואחד עם השני.
הנושאים
ארדואינו מול ESP32
| ארדואינו אונו | ESP32-S3 | |
|---|---|---|
| מהירות | 16MHz, מעבד אחד | 240MHz, שני מעבדים |
| זיכרון עבודה | 2KB | 512KB (ועוד PSRAM) |
| מתח הפינים | 5V | 3.3V |
| אלחוטי | אין | Wi-Fi ו־BLE |
⚠️ הפינים של ESP32 עובדים ב־3.3V. לא מחברים אליהם ישר חיישן שמוציא 5V (למשל פין Echo של חיישן המרחק): צריך מחלק מתח או מודול שעובד ב־3.3V.
🌈 סטריפ לדים של 5A עם ESP32
🌈 NeoPixel: לדים חכמים
NeoPixel הוא השם המסחרי של חברת Adafruit ללדים "חכמים" מסוג WS2812B (ודומים לו כמו SK6812). בתוך כל לד יש שלושה לדים זעירים, אדום, ירוק וכחול, ועוד שבב קטן שיודע לקרוא הוראות. לכן חוט נתונים אחד בלבד שולט במאות לדים, ולכל אחד מהם צבע משלו.
🔬 נסו בעצמכם: איך הצבעים עוברים בשרשרת
בוחרים צבע, לוחצים על הלדים כדי "לצבוע" אותם בזיכרון של ה־ESP32, ואז "שליחה". הבקר שולח רכבת של 8 חבילות. כל לד תופס את החבילה הראשונה שמגיעה אליו ומעביר את השאר לשכן. רק כשהחוט שותק לרגע (Reset), כולם נדלקים ביחד.
הסדר הוא ירוק, אדום, כחול (GRB), 8 ביטים לכל צבע. כל ביט הוא פולס: 1 = פולס ארוך, 0 = פולס קצר. ביט אחד לוקח 1.25 מיקרו־שניות, אז לד שלם לוקח 30 מיקרו־שניות. לוחצים על לד אחר כדי לראות את הביטים שלו.
הצורות של NeoPixel
החיבור ל־ESP32-S3
| בלד | מה זה | לאן |
|---|---|---|
| 5V | חשמל ללדים | 5V של הלוח (עד בערך 8 לדים בבהירות נמוכה). יותר מזה: ספק נפרד |
| GND | אדמה | GND, תמיד משותף עם הבקר |
| DIN | נתונים נכנסים | GPIO 4 דרך נגד 330Ω |
| DOUT | נתונים יוצאים לשכן | ל־DIN של הלד או הסטריפ הבא, או לא מחברים |
⚠️ לסטריפ יש כיוון! על הסטריפ מודפסים חצים קטנים, ומחברים את הבקר לקצה שהחצים יוצאים ממנו (DIN). חיבור לקצה הלא נכון: שום דבר לא נדלק, ושום דבר גם לא נשרף.
🔋 מחשבון זרם: כמה חשמל זה צורך?
כל לד שולף עד 60mA: 20 לכל צבע. לבן מלא = שלושתם דולקים. ב־30 לדים בלבן מלא זה כבר כמו מטען טלפון שלם.
הקוד
מתקינים קודם ספרייה: Sketch ← Include Library ← Manage Libraries, מחפשים Adafruit NeoPixel ולוחצים Install. הקוד משתמש בצבעים שבחרתם בהדמיה למעלה. משנים שם, והקוד מתעדכן.
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.
הכי חשוב לזכור: setPixelColor רק כותב לזיכרון של הבקר, כמו לצבוע לדים בהדמיה. רק show שולח את הרכבת. רוצים יותר מכמה לדים? ממשיכים לעמוד סטריפ לדים 5A לחיבור עם ספק כוח.
🟩 מטריצת NeoPixel 8×8 עם FastLED
מטריצה היא 64 לדי NeoPixel על לוח אחד, בשמונה שורות של שמונה. מבחינת הבקר זו בדיוק אותה שרשרת כמו בעמוד NeoPixel, מלד 0 ועד לד 63. הטריק הוא לתרגם "שורה וטור" למספר של לד. הפעם עובדים עם ספריית FastLED: מהירה, עם צבעים לפי גוון (HSV) ואפקטים מוכנים.
🎨 ציירו על המטריצה
x=? y=? → leds[?]
🧮 מ־x ו־y למספר לד
כל לד במטריצה יושב בטור x (0 עד 7) ובשורה y (0 עד 7). בשרשרת יש לו מספר אחד בלבד. בחיווט רגיל כל שורה מתחילה משמאל, ולכן:
i = y × 8 + x
בזיג־זג השורות האי־זוגיות רצות הפוך (מימין לשמאל), ושם i = y × 8 + (7 − x). את התרגום הזה עושה בקוד פונקציה קטנה בשם XY. העבירו את העכבר על המטריצה למעלה ותראו אותה עובדת.
FastLED מול Adafruit NeoPixel
| מה עושים | Adafruit NeoPixel | FastLED |
|---|---|---|
| הגדרה | Adafruit_NeoPixel px(64, 5, NEO_GRB) | CRGB leds[64]; FastLED.addLeds<WS2812B, 5, GRB>(leds, 64); |
| לצבוע לד | px.setPixelColor(i, px.Color(255,0,0)) | leds[i] = CRGB::Red; |
| צבע לפי גוון | px.ColorHSV(hue) | leds[i] = CHSV(hue, 255, 255); |
| לשלוח | px.show() | FastLED.show() |
| שמירה על הספק | אין, שומרים לבד | FastLED.setMaxPowerInVoltsAndMilliamps(5, 500) |
ב־FastLED הלדים הם פשוט מערך. משנים את המערך כמו כל משתנה, ו־FastLED.show() שולח את כולו. בנוסף יש בה הרבה אפקטים מוכנים, כמו fill_rainbow, fadeToBlackBy ו־blur2d.
החיבור ללוח ההרחבה של ESP32, פין 5
| במטריצה | בלוח ההרחבה, בשורה של D5 |
|---|---|
| DIN | צהוב ל־S (הפין החיצוני). זה GPIO 5. ליד החץ שנכנס למטריצה, בצד של לד 0 |
| 5V | אדום ל־V (האמצעי). הג'אמפר JUMP חייב להיות על 5V, אחרת השורה V נותנת 3.3V |
| GND | חום ל־G (הפנימי, ליד הבקר). בכבלי סרבו האדמה היא חום או שחור |
| DOUT | לא מחברים, או ממשיכים למטריצה נוספת |
נגד של 330Ω על חוט הנתונים לא חובה, אבל מגן על הלד הראשון. אם הלדים מהבהבים בצבעים אקראיים, בודקים שה־GND משותף ושהג'אמפר על 5V.
⚠️ 64 לדים בלבן מלא מושכים כמעט 4 אמפר, הרבה יותר ממה שה־USB נותן. לכן בקוד יש setMaxPowerInVoltsAndMilliamps(5, 500): FastLED מחשבת לבד כמה זרם התמונה תצרוך, ומעמעמת אוטומטית כדי לא לעבור 500mA. רוצים בהירות מלאה? ספק כוח נפרד, כמו בעמוד סטריפ לדים 5A.
הקוד
מתקינים את הספרייה: Sketch ← Include Library ← Manage Libraries, מחפשים FastLED ומתקינים גרסה עדכנית (3.9 ומעלה תומכת ב־ESP32-S3). הקוד בונה את עצמו מהציור שלכם ומסוג החיווט שבחרתם. "הרצת הקוד" למעלה מראה מה הוא יעשה: הציור, ואז קשת אלכסונית שזזה.
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.
אם הציור יוצא הפוך או משוקף: מסובבים את המטריצה, או הופכים בקוד את הערך של SERPENTINE. אם רק כל שורה שנייה הפוכה, החיווט הוא זיג־זג.
🕹️ ג'ויסטיק אנלוגי
בעצם שני פוטנציומטרים ולחצן אחד בקופסה. כל ציר מוציא מתח שמשתנה לפי כמה דוחפים את המקל, וה־ESP32 הופך אותו למספר מ־0 עד 4095. כשלוחצים על המקל למטה, נסגר לחצן.
גוררים את המקל. לחיצה כפולה = לחיצה על הלחצן
החיבור
| רגל בג'ויסטיק | מה היא עושה | לאן בבקר |
|---|---|---|
| GND | אדמה | GND |
| +5V | חשמל לשני הפוטנציומטרים | 3V3, לא 5V ולא VIN |
| VRx | אנלוגי: שמאל-ימין | |
| VRy | אנלוגי: למעלה-למטה | |
| SW | דיגיטלי: הלחצן |
הקוד
חבילת ESP32 של Espressif בגרסה 3 ומעלה. פותחים Serial Monitor או Serial Plotter על 115200.
המקל במנוחה לא נותן בדיוק 2048, וזה משתנה מג'ויסטיק לג'ויסטיק. לכן הקוד מודד את נקודת האמצע בהדלקה (לא נוגעים במקל ברגע הזה!) ומתעלם מתזוזות קטנות סביבה, "אזור מת".
📶 ESP32 רגיל, 30 פינים
הלוח של הכיתה: ESP-WROOM-32 על לוח הרחבה. אותו Wi-Fi ובלוטות' כמו ב־S3, ולוח ההרחבה נותן לכל פין שלישייה מוכנה לכבל, כך שמחברים רכיבים בלי מטריצה ובלי הלחמות.
הפרויקטים על הלוח הזה
לוח ההרחבה

איזה פין לבחור
| פינים | מצב | למה |
|---|---|---|
| 4, 13, 14, 16 עד 19, 21 עד 23, 25 עד 27, 32, 33 | ✅ חופשיים | כניסה או יציאה, לכל דבר |
| 32 עד 39 (VP=36, VN=39) | 📈 אנלוגי עם Wi-Fi | שאר הפינים האנלוגיים מפסיקים לעבוד כש־Wi-Fi דולק |
| 34, 35, 36, 39 | 👂 קלט בלבד | אי אפשר להוציא מהם מתח, ואין להם pull-up פנימי |
| 0, 2, 5, 12, 15 | ⚠️ בזהירות | הבקר בודק אותם בהדלקה. רכיב שמחזיק אותם HIGH או LOW יכול למנוע עלייה. פין 2 הוא גם הלד הכחול |
| 1, 3 (TX0, RX0) | ⛔ תפוסים | ה־USB וה־Serial Monitor |
⚠️ הפינים עובדים ב־3.3V. רכיב שמוציא 5V לפין (למשל Echo של חיישן המרחק) צריך מחלק מתח.
🖥️ ESP32 + מסך ST7789
המודול שקנינו: מסך צבעוני 2.4 אינץ׳ (ST7789, 240×320), אנקודר סיבובי וכפתור, הכול על לוח אחד עם שורה אחת של 12 פינים. 6 חוטים למסך, 4 לאנקודר ולכפתור, ושניים לחשמל.
🛒 שם הרכיב ואיפה קונים
כך מחפשים אותו (באנגלית):
2.4 inch TFT + EC11 Rotary Encoder Module, SPI, ST7789, 320x240
בעברית: מסך 2.4 אינץ׳ עם אנקודר EC11 וכפתור, ממשק SPI, שבב ST7789. בדף המוצר בוחרים את האפשרות 2.4 inch (יש גם 1.8, עם שבב אחר וקוד אחר).

איך החוטים נכנסים למסך ולאנקודר
בצד של ה־ESP32 כל חוט נכנס לפין S (הסיגנל) בשלישייה של הפין שלו. החשמל מגיע מבלוק החשמל הקבוע למטה: VCC ל־3.3V ו־GND ל־GND. לאנקודר ולכפתור אין חשמל נפרד, הם מקבלים אותו דרך אותם שני פינים. סדר הפינים על המודול יכול להשתנות בין יצרנים, אז תמיד בודקים מה כתוב ליד כל פין.
החוטים: רצף אחד מסרט הג׳מפרים
תולשים מהסרט 12 חוטים צמודים, בסדר שבו הם מגיעים: חום, אדום, כתום, צהוב, ירוק, כחול, סגול, אפור, לבן, שחור, חום, אדום. החוט החום הראשון נכנס ל־GND, הפין המרובע בתחתית, וכל השאר לפי הסדר כלפי מעלה. ששת החוטים מכתום עד אפור הם הרצף של המסך.
| צבע החוט | פין במודול | פין ב־ESP32 |
|---|---|---|
| אדום | K0 | D26 |
| חום | PUSH | D25 |
| שחור | B | D33 |
| לבן | A | D32 |
| אפור | BLK | D19 |
| סגול | CS | D18 |
| כחול | DC | D5 |
| ירוק | RES | D17 |
| צהוב | SDA | D16 |
| כתום | SCL | D4 |
| אדום | VCC | 3.3V |
| חום | GND | GND |
⚠️ המסך עובד ב־3.3V: VCC ל־3V3, לא ל־5V. על המודול כתוב 3.3V/5V, אבל עם ESP32 מחברים ל־3.3V כדי שהסיגנלים יתאימו.
קוד לדוגמה: מד צבעוני שמסובבים
ל־ESP32 הרגיל (לא S3). מסובבים את האנקודר: הקשת מתמלאת מ־0 עד 100. לחיצה על הכפתור של האנקודר מחליפה ערכת צבעים, ו־K0 מאפס. ספריות להתקין ב־Library Manager: Adafruit ST7735 and ST7789 Library ו־Adafruit GFX Library.
הצבעים נראים כמו נגטיב? מורידים את ה־// לפני invertDisplay(false). התמונה הפוכה? setRotation(3). קליק אחד קופץ פעמיים? STEPS_PER_CLICK 2.
בלי ספריות.
// ESP32 (30 pins, not S3) + 2.4" ST7789 screen (240x320) with encoder and button
// Libraries (Library Manager): Adafruit ST7735 and ST7789 Library + Adafruit GFX Library
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
// ---- screen ----
#define TFT_SCL 4
#define TFT_SDA 16
#define TFT_RES 17
#define TFT_DC 5
#define TFT_CS 18
#define TFT_BLK 19
// ---- encoder + button ----
#define ENC_A 32
#define ENC_B 33
#define ENC_PUSH 25
#define BTN_K0 26
#define STEPS_PER_CLICK 4 // one click jumps twice or not at all? change to 2
Adafruit_ST7789 tft(&SPI, TFT_CS, TFT_DC, TFT_RES);
// The gauge is drawn in memory and sent at once: no flicker.
// (A full 320x240 canvas is too big for the ESP32, so only the gauge area.)
#define GW 200
#define GH 184
#define GX ((320 - GW) / 2)
#define GY 32
GFXcanvas16 gauge(GW, GH);
volatile int encRaw = 0;
volatile uint8_t encLast = 0;
void IRAM_ATTR encISR() {
static const int8_t T[16] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};
uint8_t s = (digitalRead(ENC_A) << 1) | digitalRead(ENC_B);
encRaw += T[(encLast << 2) | s];
encLast = s;
}
int value = 40; // 0..100
int theme = 0; // color theme
const char* THEMES[] = {"RAINBOW", "FIRE", "OCEAN", "NEON"};
unsigned long lastDraw = 0;
uint16_t hsv(float h, float s, float v) { // h: 0..360
float c = v * s, x = c * (1 - fabs(fmod(h / 60.0, 2) - 1)), m = v - c;
float r, g, b;
if (h < 60) { r = c; g = x; b = 0; }
else if (h < 120) { r = x; g = c; b = 0; }
else if (h < 180) { r = 0; g = c; b = x; }
else if (h < 240) { r = 0; g = x; b = c; }
else if (h < 300) { r = x; g = 0; b = c; }
else { r = c; g = 0; b = x; }
return tft.color565((r + m) * 255, (g + m) * 255, (b + m) * 255);
}
uint16_t arcColor(float t) { // t: 0..1 along the arc
switch (theme) {
case 0: return hsv(t * 300, 1, 1); // rainbow
case 1: return hsv(t * 55, 1, 1); // fire: red -> yellow
case 2: return hsv(200 - t * 40, 1, 0.6 + t * 0.4); // ocean
default: return hsv(fmod(280 + t * 140, 360), 1, 1); // neon
}
}
void drawFrame() { // the parts that don't move: drawn once
tft.fillScreen(ST77XX_BLACK);
tft.fillRect(0, 0, 320, 26, tft.color565(124, 77, 255));
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.setCursor(8, 5);
tft.print("ROBOTIKA LAB");
tft.setCursor(250, 5);
tft.print("ESP32");
tft.setTextSize(1);
tft.setTextColor(tft.color565(150, 150, 160));
tft.setCursor(70, 226);
tft.print("PUSH: colors K0: reset");
}
void drawGauge() {
float t = millis() / 1000.0;
gauge.fillScreen(ST77XX_BLACK);
// arc: 270 degrees, from 135 to 405
const int cx = GW / 2, cy = 96, r = 80;
int lit = map(value, 0, 100, 0, 270);
for (int a = 0; a <= 270; a += 3) {
float rad = (135 + a) * DEG_TO_RAD;
int x = cx + cos(rad) * r, y = cy + sin(rad) * r;
if (a <= lit) gauge.fillCircle(x, y, 7, arcColor(a / 270.0));
else gauge.fillCircle(x, y, 3, tft.color565(45, 45, 55));
}
// glowing ring at the end of the arc
float er = (135 + lit) * DEG_TO_RAD;
int ex = cx + cos(er) * r, ey = cy + sin(er) * r;
gauge.drawCircle(ex, ey, 10 + 3 * sin(t * 6), ST77XX_WHITE);
// big number in the middle
String num = String(value);
gauge.setTextSize(5);
gauge.setTextColor(ST77XX_WHITE);
gauge.setCursor(cx - num.length() * 15, cy - 22);
gauge.print(num);
String th = THEMES[theme];
gauge.setTextSize(2);
gauge.setTextColor(arcColor(value / 100.0));
gauge.setCursor(cx - th.length() * 6, cy + 30);
gauge.print(th);
// little twinkling stars
for (int i = 0; i < 8; i++) {
int sx = (i * 53 + 17) % GW, sy = (i * 37 + 5) % GH;
if (sin(t * 3 + i) > 0.6) gauge.fillCircle(sx, sy, 1, ST77XX_WHITE);
}
tft.drawRGBBitmap(GX, GY, gauge.getBuffer(), GW, GH);
}
bool pressed(int pin, bool &prev, unsigned long &tLast) {
bool now = digitalRead(pin) == LOW; // INPUT_PULLUP: pressed = LOW
bool fired = now && !prev && millis() - tLast > 150;
if (fired) tLast = millis();
prev = now;
return fired;
}
void setup() {
Serial.begin(115200);
pinMode(TFT_BLK, OUTPUT);
digitalWrite(TFT_BLK, HIGH); // backlight on
SPI.begin(TFT_SCL, -1, TFT_SDA, TFT_CS); // SPI on our pins
tft.init(240, 320); // 2.4" = 240x320
tft.setSPISpeed(40000000);
tft.setRotation(1); // landscape. upside down? use 3
// tft.invertDisplay(false); // colors look like a negative? remove the //
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(ENC_PUSH, INPUT_PULLUP);
pinMode(BTN_K0, INPUT_PULLUP);
encLast = (digitalRead(ENC_A) << 1) | digitalRead(ENC_B);
attachInterrupt(digitalPinToInterrupt(ENC_A), encISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), encISR, CHANGE);
drawFrame();
}
void loop() {
// encoder: one click = one step
noInterrupts();
int steps = encRaw / STEPS_PER_CLICK;
encRaw -= steps * STEPS_PER_CLICK;
interrupts();
if (steps) value = constrain(value + steps * 2, 0, 100);
static bool pPrev = false, kPrev = false;
static unsigned long pT = 0, kT = 0;
if (pressed(ENC_PUSH, pPrev, pT)) theme = (theme + 1) % 4;
if (pressed(BTN_K0, kPrev, kT)) value = 0;
if (millis() - lastDraw > 33) { // about 30 frames per second
lastDraw = millis();
drawGauge();
}
}
🔌 חיבור הנגן ל־ESP32 עם 30 פינים
🎵 חזרה לנגן MP3החיבור הישיר, פין לפין
| פין בנגן | מה הוא עושה | לאן ב־ESP32 |
|---|---|---|
| GND | אדמה | GND |
| VCC | חשמל לנגן ולמגבר | VIN (5V מה־USB) |
| RX | הנגן מקשיב: מקבל פקודות | GPIO 17 (TX2), רצוי דרך נגד 1K |
על לוח ההרחבה של ESP32
ליד כל פין בלוח יש שלישייה: G אדמה, V חשמל, S הסיגנל. הנגן רק מקבל פקודות, אז צריך קו סיגנל אחד בלבד: השלישייה של D17 בצד ימין של הלוח.
| פין בנגן | לאן בלוח ההרחבה |
|---|---|
| RX | S בשורה של D17 |
| VCC | 5V בבלוק החשמל משמאל למטה (העמודה האדומה) |
| GND | GND באותו בלוק, או G בשורה של D17 |
⚠️ למה לא V של השורה? המתח של כל עמודת ה־V נקבע לפי הג׳מפר JUMP (5V או 3.3V), והוא משותף לכל הפינים. אם מעבירים אותו ל־5V בשביל הנגן, גם חיישנים אחרים שמחוברים ללוח (למשל הג׳ויסטיק) יקבלו 5V. בבלוק החשמל ה־5V תמיד 5V, בלי קשר לג׳מפר.

RX של הנגן (מקשיב) הולך ל־TX של ה־ESP32 (מדבר), פין 17. פין TX של הנגן נשאר לא מחובר: הוא רק שולח תשובות, ובשביל לנגן לא צריך אותן.
למה דווקא 17? זה פין השליחה של UART2, יציאה סריאלית שנייה שפנויה לגמרי. UART0 (פינים 1 ו־3) כבר תפוס ע״י ה־USB וה־Serial Monitor. לא לחבר לפינים 0, 2, 5, 12, 15: הבקר בודק אותם בהדלקה, ורכיב שמחובר אליהם יכול למנוע מהלוח לעלות. פינים 6 עד 11 תפוסים לגמרי ע״י הזיכרון. אם 17 תפוס, אפשר 25, 26 או 33, ומשנים את MP3_TX בקוד.
הקוד
בוחר כרטיס, עוצמה 25, ומנגן את 01/001. שומעים שיר = החיבור תקין. אין קול = בודקים שהחוט ב־S של D17 ולא בפין אחר, ושהכרטיס מפורמט FAT32.
🎵 נגן MP3 סריאלי
🔌 החיבור ל־ESP32 עם 30 פיניםכרטיס קטן עם שקע לכרטיס זיכרון, שבב שמפענח MP3, ומגבר שמניע רמקול. ה־ESP32 לא צריך לעבד קול בכלל: הוא רק שולח לנגן "פקודות" קצרות בארבעה חוטים, כמו שלט רחוק. נגן שיר 3, הבא, עוצמה 20.

איך נראית פקודה? לחצו
מתחיל ב־7E ונגמר ב־EF. ירוק = כמה בתים יש באמצע, סגול = מה לעשות, כתום = עם איזה מספר.
הכנת הכרטיס
מפרמטים ל־FAT32, יוצרים תיקיות בשמות 01, 02 וכן הלאה, ובכל תיקייה שמות קבצים שמתחילים במספר של שלוש ספרות: 01/001_hello.mp3, 01/002_beep.mp3. אחרי המספר מותר לכתוב מה שרוצים. FOLDER = 1 ו־SONG = 1 ינגנו את 01/001.
הקוד
חיבור: פין 17 → RX של הנגן, VCC ל־5V, GND.
אם הלוח מתאפס כשהמוזיקה חזקה, המגבר מושך יותר זרם ממה שה־USB נותן ברגע. קבל אלקטרוליטי 100 עד 470µF בין VCC ל־GND צמוד לנגן פותר את זה.
🔍 הכרת הלוח
מה יש על הלוח ESP32-S3-N16R8 שבערכה, ולמה צריך כל חלק.


מה הלוח יודע לעשות
🎤 מיקרופון INMP441
מיקרופון דיגיטלי קטן כמו מטבע. הוא לא שולח "חשמל שרועד" כמו מיקרופון רגיל, אלא מספרים: 16,000 פעמים בשנייה הוא מודד כמה חזק האוויר לוחץ עליו ושולח את התוצאה לבקר. זו האוזן של הצ'טבוט שנבנה.

למה דווקא ESP32 ולא ארדואינו אונו?
קול זה הרבה מידע. 16,000 מדידות בשנייה, כל אחת של 2 בתים, זה 32,000 בתים בכל שנייה. לארדואינו אונו יש בסך הכול 2,000 בתים של זיכרון, כלומר הוא היה מתמלא אחרי שישים אלפיות שנייה של דיבור. ל־ESP32-S3 יש כל מה שחסר לאונו: רכיב I2S מובנה שקורא את המיקרופון לבד ברקע, 8MB של PSRAM שמספיקים לכמה דקות הקלטה, מעבד מהיר מספיק לעבד קול, ו־Wi-Fi כדי לשלוח את ההקלטה לבינה מלאכותית ולקבל תשובה.
החיבור ל־ESP32-S3
| פין במיקרופון | מה הוא עושה | לאן ב־ESP32-S3 |
|---|---|---|
| SCK | השעון: קצב שהבקר מכתיב, "עכשיו ביט, עכשיו ביט" | GPIO 17 |
| WS | בחירת ערוץ: אומר מתי מתחילה מדידה חדשה, שמאל או ימין | GPIO 16 |
| SD | הנתונים: דרכו יוצאים המספרים של הקול | GPIO 18 |
| L/R | קובע אם המיקרופון הוא הערוץ השמאלי או הימני | GPIO 15 (הקוד שם בו LOW, כלומר ערוץ שמאל) |
| VDD | חשמל | 3V3, לא 5V |
| GND | אדמה | GND |
פינים 15 עד 18 יושבים ברצף בצד שמאל של הלוח, כך שכל ארבעת החוטים יוצאים מאותו מקום. במקום פין 15 אפשר לחבר את L/R ישר ל־GND ולמחוק מהקוד את שתי השורות שלו. לא להשתמש בפינים 19, 20, 35 עד 37 או 48 (ראו תרשים הפינים). הרמקול מתחבר לפינים 10 עד 13, ראו מגבר MAX98357A.
נסו בעצמכם: ככה מיקרופון רואה קול
הגל הוא הקול, והמספרים למטה הם בדיוק מה שה־INMP441 שולח: מספר לכל רגע, חיובי כשהאוויר נדחף ושלילי כשהוא נמשך. הפס הצבעוני הוא העוצמה, אותו חישוב שעושה הקוד הראשון.
הקוד
דורש את חבילת ESP32 של Espressif בגרסה 3 ומעלה ב־Arduino IDE. פותחים Tools ואז Serial Plotter על 115200.
שקט מוחלט, רק אפסים? בודקים שהחוטים של SCK ו־WS לא הפוכים, ושה־L/R מחובר לפין 15 (או ל־GND). אם ה־L/R מחובר ל־3V3, צריך לשנות בקוד את I2S_STD_SLOT_LEFT ל־I2S_STD_SLOT_RIGHT.
🤖 היעד: צ'טבוט שמדבר
ה־ESP32 לא מספיק חזק להריץ בינה מלאכותית בעצמו, אבל הוא לא צריך: הוא האוזניים והפה, והמוח נמצא בענן. ככה נראית שיחה אחת:
חשבון קטן: עשר שניות של דיבור ב־16,000 מדידות בשנייה הן כ־320KB. באונו זה בלתי אפשרי, ב־ESP32-S3 זה פחות מ־4% מה־PSRAM. אפשר גם להדליק את לד ה־RGB בצבע אחר בכל שלב, כך שרואים מתי הוא מקשיב, חושב ומדבר.
🔑 מפתח ה־API של שירות ה־AI הוא כמו כרטיס אשראי. לא כותבים אותו בקוד שעל הלוח: הלוח מדבר עם שרת קטן שלנו, והשרת מחזיק את המפתח.
🔊 מגבר MAX98357A
הפה של הצ'טבוט. ה־ESP32 שולח אליו את הקול כמספרים, באותה שפת I2S של המיקרופון, והמגבר הופך אותם בחזרה לגל חשמלי חזק מספיק כדי להזיז רמקול. המיקרופון שומע, הבקר חושב, המגבר מדבר.

למה צריך מגבר? אי אפשר לחבר רמקול ישר לבקר?
אי אפשר, משתי סיבות. הראשונה: פין של ESP32 נותן בערך 40 מיליאמפר ב־3.3V, ורמקול צריך פי עשרה ויותר. חיבור ישיר נותן קול חלש מאוד, ועלול לשרוף את הפין. השנייה: פין רגיל יודע רק דלוק או כבוי, וקול הוא גל שעולה ויורד בעדינות. ל־ESP32 הרגיל היה ממיר קטן (DAC) שיודע לייצר גל כזה, אבל ב־ESP32-S3 שלנו אין אותו בכלל. ה־MAX98357A פותר את שתי הבעיות: מקבל את הקול כמספרים, בונה ממנו גל, ומגביר אותו מהחשמל של ה־5V ולא מהפין.
החיבור ל־ESP32-S3
| פין במגבר | מה הוא עושה | לאן ב־ESP32-S3 |
|---|---|---|
| LRC | בחירת ערוץ: מתי מתחילה דגימה חדשה, שמאל או ימין (כמו WS במיקרופון) | GPIO 12 |
| BCLK | השעון של הביטים (כמו SCK במיקרופון) | GPIO 11 |
| DIN | הנתונים: המספרים של הקול נכנסים כאן | GPIO 10 |
| GAIN | עוצמת ההגברה | GND (12 דציבל) |
| SD | הפעלה וכיבוי, ובחירת ערוץ | GPIO 13 (HIGH = דולק) |
| GND | אדמה | GND |
| VIN | חשמל למגבר ולרמקול | 5V |
| + − | הרמקול, בשקע הבורג למעלה | רמקול 4 או 8 אוהם, 3W |
⚠️ שני חוטי הרמקול הולכים רק לשקע של המגבר. לא מחברים את המינוס של הרמקול ל־GND: המגבר דוחף וגם מושך בשני הצדדים, וחיבור לאדמה יכול לשרוף אותו.
בעוצמה גבוהה המגבר מושך הרבה זרם. אם הלוח מתאפס בדיוק כשהוא מדבר, מחליפים לכבל USB טוב יותר או למטען חזק, או מורידים את העוצמה בקוד.
פין GAIN: כמה חזק?
| מחברים את GAIN ל... | הגברה |
|---|---|
| GND דרך נגד 100K | 15dB, הכי חזק |
| GND ישירות | 12dB (החיבור שלנו) |
| לא מחברים כלום | 9dB |
| VIN ישירות | 6dB |
| VIN דרך נגד 100K | 3dB, הכי שקט |
הקוד
דורש את חבילת ESP32 של Espressif בגרסה 3 ומעלה ב־Arduino IDE.
🤖 המיקרופון והמגבר ביחד

עם שני הרכיבים האלה ל־ESP32 יש אוזניים ופה. קוד 2 (התוכי) כבר עושה חצי מהעבודה של צ'טבוט: מקליט כשמחזיקים את BOOT ומשמיע. בצ'טבוט האמיתי, בין ההקלטה להשמעה ההקלטה נשלחת ב־Wi-Fi לבינה מלאכותית, וחוזרת תשובה מדוברת שמתנגנת בדיוק באותה דרך. השרשרת המלאה מופיעה בעמוד המיקרופון.
🧩 מיקרופון ורמקול על אותו ESP32
החיבור המלא של הצ'טבוט: המיקרופון בפינים 15 עד 18, המגבר בפינים 10 עד 13. מחברים בכבלי סרבו (שחור, אדום ולבן צמודים) ובכבל זוגי (שחור ואדום), כך שכמה פינים נכנסים בתנועה אחת. לוחצים על כבל כדי לראות רק אותו.
שני סוגי חיבור בלוח ההרחבה
הכבלים, אחד אחד
| כבל | החוטים | איך הוא יושב |
|---|---|---|
| 🎤 1. אותות המיקרופון | L/R → GPIO 15WS → GPIO 16SCK → GPIO 17 | השורה העליונה של המיקרופון. שני הקצוות שטוחים: שלושה פינים שכנים בכל צד. |
| 🎤 2. חשמל ונתונים של המיקרופון | GND → GNDVDD → 3V3SD → GPIO 18 | השורה התחתונה של המיקרופון, בדיוק בסדר שחור־אדום־לבן. הצד השני נכנס שלם לשלישייה של IO18 בצד שמאל של הלוח: שחור ל־GND, אדום ל־3.3V, לבן לפין האות הצהוב. בלי לפצל חוטים. |
| 🔊 3. אותות המגבר | LRC → GPIO 12BCLK → GPIO 11DIN → GPIO 10 | שני הקצוות שטוחים. בבקר הסדר מלמעלה הוא לבן, אדום, שחור (10, 11, 12), כלומר הכבל פשוט הפוך. |
| 🔊 4. החשמל של המגבר | GND → GNDVIN → 5V | כבל זוגי. נכנס לשורה העליונה בעמודת ה־5V בצד שמאל של הלוח: שחור על השחור, אדום על האדום. |
| 5. שני חוטים בודדים | SD → GPIO 13GAIN → GND | SD של המגבר לפין 13 (מדלגים על 14). GAIN לשחור בשורה השנייה של עמודת ה־5V, ממש מתחת לכבל 4, וקובע הגברה של 12dB. אם אין חוט פנוי, אפשר להשאיר את GAIN באוויר ולקבל 9dB. |
הבקר יושב על לוח ההרחבה. כבלי האותות 1 ו־3 וחוט ה־SD נכנסים לשורת הפינים הצהובה שצמודה לבקר, שמסודרת בדיוק כמו הפינים שלו. כבל 2 נכנס לשלישייה של IO18 שמביאה איתה גם GND ו־3.3V, וכבל 4 לעמודת ה־5V. ככה אף חוט חשמל לא צריך לחצות את הלוח.
⚠️ בכבלים 1 ו־3 החוט האדום הוא אות, לא חשמל. בכבלים 2 ו־4 האדום הוא חשמל: 3V3 למיקרופון ו־5V למגבר. אם מחליפים ביניהם, 5V במיקרופון שורף אותו.
🎤 ה־L/R של המיקרופון מחובר לפין 15 ולא ל־GND, אז הקוד חייב להוריד את פין 15 ל־LOW בתחילת setup. בלי זה המיקרופון לא יודע באיזה ערוץ לשדר, ושומעים שקט.
בודקים שהכול עובד
מריצים את קוד 2 בעמוד המגבר, התוכי: מחזיקים את BOOT, מדברים, משחררים, והלוח משמיע בחזרה את מה ששמע. אם שומעים את עצמכם, כל חמשת הכבלים במקום. ה־ESP32-S3 בונה שני ערוצי I2S נפרדים, אחד לכל רכיב, ולכן הם עובדים יחד באותו זמן.

🤖 Voice Assistant: צ׳טבוט שמדבר
הפרויקט המלא: מחזיקים את BOOT, שואלים שאלה בקול, והלוח עונה בקול. ה־ESP32 הוא האוזניים והפה, והמוח נמצא בענן של OpenAI. בלי ספריות חיצוניות, רק מה שמגיע עם חבילת ESP32.
ב־ZIP יש תיקייה בשם voice_assistant ובה שני הקבצים. פותחים את התיקייה כמו שהיא ב־Arduino IDE, כי שם התיקייה חייב להיות זהה לשם קובץ ה־ino.
שיחה אחת, שלב אחרי שלב
בכל שלב הלוח כותב ב־Serial Monitor מה הוא עושה וכמה זמן זה לקח. צפצוף קצר = "שמעתי אותך". צפצוף נמוך וארוך = משהו נכשל, והסיבה כתובה ב־Serial.
לפני שמעלים
| מה | איך |
|---|---|
| החיבורים | מיקרופון בפינים 15 עד 18, מגבר בפינים 10 עד 13, בדיוק כמו בעמוד מיקרופון + רמקול. אם התוכי עבד, גם זה יעבוד. |
| Arduino IDE | חבילת esp32 של Espressif בגרסה 3 ומעלה. לוח: ESP32S3 Dev Module. |
| תפריט Tools | Flash Size = 16MB, ו־PSRAM = OPI PSRAM. בלי זה ההקלטה לא נכנסת לזיכרון והלוח נעצר עם הודעה. |
| Serial Monitor | 115200. אם מחוברים לשקע USB ולא ל־COM, מגדירים USB CDC On Boot = Enabled. |
| Wi-Fi | רשת 2.4GHz בלבד. ESP32 לא רואה רשתות 5GHz. |
הקובץ secrets.h
הסיסמאות לא נכתבות בתוך הקוד עצמו אלא בקובץ נפרד שיושב באותה תיקייה. ככה אפשר לשתף את הקוד, להעלות אותו לאתר או לשלוח לחבר, בלי לחשוף את סיסמת הבית ואת המפתח ל־OpenAI. זה המבנה, ואת הערכים ממלאים כל אחד אצלו:
341 שורות. דורש esp32 גרסה 3 ומעלה ו־PSRAM = OPI PSRAM.
הורדה🔑 מפתח OpenAI שווה כסף: כל שאלה עולה אגורות בודדות, אבל מי שמחזיק את המפתח יכול להשתמש בו על חשבונכם. לא מצלמים אותו, לא מדביקים בקבוצות, ואם הוא דלף, מבטלים אותו באתר של OpenAI ויוצרים חדש.
הקוד, חלק אחרי חלק
לוחצים על חלק כדי לסמן אותו בקוד ולקרוא מה הוא עושה.
משנים ומשחקים
📍 תרשים הפינים
לוח ESP32-S3 בפורמט DevKitC-1, 44 פינים, מבט מלמעלה כשכבלי ה־USB למטה. לוחצים על פין כדי לראות מה הוא יודע לעשות. המספר בריבוע הוא מספר ה־GPIO, וזה המספר שכותבים בקוד.

בחרו פין
לוחצים על אחד הריבועים בתרשים.
יש כמה יצרנים ללוחות האלה. אם ההדפסה על הלוח שלכם שונה מהתרשים, ההדפסה על הלוח קובעת.
הקוד
רגל ארוכה (+) לפין 13, רגל קצרה (−) ל־GND שצמוד אליו. נכנס ישר ללוח בלי חוטים.
ג'אמפר אדום מפין 8 לרגל הארוכה, ג'אמפר שחור מהרגל הקצרה ל־GND בשורת המתח.
בכיתה עדיף להוסיף נגד של 220Ω בטור לכל לד. בלי נגד הלד מקבל יותר זרם ממה שהוא צריך, והוא והפין עלולים להיפגע.
שני לדים על לוח ההרחבה
לד אדום לפין 8, לד כחול לפין 9. כל לד מתחבר בשני ג'אמפרים: הרגל הארוכה לשורה S (סיגנל), הרגל הקצרה לשורה G (גראונד). השורה האמצעית V לא בשימוש.
הקוד
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.

לוח ההרחבה יושב על הארדואינו. לכל פין יש טור של שלושה: G גראונד, V 5 וולט, S הסיגנל עצמו.
לרגל הארוכה של הלד קוראים אנודה (+), והיא הולכת ל־S. הרגל הקצרה, קתודה (−), הולכת ל־G. לד שחובר הפוך פשוט לא יידלק, ולא יקרה לו כלום. הופכים ומנסים שוב.
לד אדום: טור 8, חוט אדום לשורה S וחוט חום לשורה G. לד כחול: אותו דבר בטור 9. סופרים טורים מימין לשמאל: 8 הוא הראשון בקבוצה 11 10 9 8.
שנו את הקוד כך ששני הלדים יהבהבו יחד. ואחר כך: אדום דולק שנייה, כחול רק רבע שנייה, כמו אורות של ניידת.
חיבור גלגלים לגשר H
כרטיס L298N יודע לסובב מנועים קדימה ואחורה. כאן שני מנועים מחוברים יחד ליציאה הימנית, כמו שני הגלגלים של צד אחד במכונית.
החיבור בצד של הגשר
המנועים עומדים. לחצו "קדימה" או "אחורה".
החיבור בצד של לוח ההרחבה
איך מחברים
ארבעה חוטי ג׳אמפר נכנסים לארבעת הפינים האמצעיים בשורת הפינים הקטנה ליד בורגי החשמל: מתחילים מהפינה: שחור ל־IN4, לבן ל־IN3, אפור ל־IN2, סגול ל־IN1. בפינים שבקצוות, ENA ו־ENB, משאירים את הכובעונים השחורים במקום.
שני חוטי חשמל נכנסים לבורגי החשמל: האדום לבורג שהכי קרוב לפינה, +12V, והחום לבורג האמצעי, GND. הבורג השלישי, +5V, נשאר ריק.
ומשם ללוח ההרחבה של הארדואינו: שחור לפין 4, לבן ל־5, אפור ל־6, סגול ל־7. האדום נכנס ל־VIN והחום ל־GND. כך הארדואינו מקבל את החשמל שלו מאותה סוללה של המנועים.
שני החוטים השחורים נכנסים יחד לבורג OUT1, הבורג שקרוב יותר לצלעות הקירור.
שני החוטים האדומים נכנסים יחד לבורג OUT2, הבורג שרחוק יותר מצלעות הקירור.
כל מנוע מקבל חוט אדום אחד וחוט שחור אחד. כך שני המנועים מקבלים בדיוק את אותו חשמל ומסתובבים יחד.
בצד השמאלי, מנועים 3 ו־4, עושים אותו דבר: שני השחורים ל־OUT4 (קרוב לצלעות) ושני האדומים ל־OUT3.
🎛️ נסו בעצמכם: ארבעת המתגים של הגשר
לוחצים על מתג כדי להעביר אותו מ־LOW ל־HIGH. IN1 ו־IN2 שולטים בזוג הימני (מנועים 1 ו־2), IN3 ו־IN4 בזוג השמאלי (מנועים 3 ו־4).
הכרטיס יכול להפוך את כיוון החשמל במנוע. כשהחשמל זורם מהאדום לשחור המנוע מסתובב לכיוון אחד, וכשהוא זורם מהשחור לאדום, לכיוון השני.
מסובבים את שני הקצוות החשופים יחד, מכניסים לחור ורק אז מהדקים את הבורג. אחרת אחד החוטים משתחרר בנסיעה.
לא נוגעים בגשר. מחליפים בין האדום לשחור בקצה של אותו מנוע, וזהו.
מחברים ומנתקים חוטים רק כשהסוללה מנותקת. קצר בין חוט אדום לשחור עלול לחמם את הסוללה ואת הכרטיס.
קדימה ואחורה
המכונית נוסעת שנייה קדימה ושנייה אחורה, וחוזר חלילה. פינים 4 ו־6 מסובבים את הגלגלים קדימה, ופינים 5 ו־7 מסובבים אותם אחורה.
לחצו "הפעלה" כדי לראות את הקוד רץ.
הקוד
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.
4 ו־6 ב־HIGH, 5 ו־7 ב־LOW. בכל צד של המכונית זוג פינים אחד דלוק, והחשמל זורם במנועים לכיוון אחד.
מחליפים: 5 ו־7 ב־HIGH, 4 ו־6 ב־LOW. החשמל זורם הפוך, והגלגלים מסתובבים לכיוון השני.
אם 4 ו־5 (או 6 ו־7) דלוקים באותו זמן, המנוע לא יודע לאן להסתובב ועומד. לכן תמיד אחד HIGH והשני LOW.
הוסיפו עצירה של חצי שנייה בין קדימה לאחורה: כל ארבעת הפינים ב־LOW ו־delay(500). זה גם שומר על המנועים.
גלגל אחד מסתובב הפוך מהשאר? לא משנים את הקוד. מחליפים בין האדום לשחור בקצה של אותו מנוע.
פנייה ימינה ופנייה שמאלה
כדי לפנות, מסובבים רק צד אחד של המכונית. לפנייה ימינה נוסעים רק שני הגלגלים של צד שמאל, ולפנייה שמאלה רק שני הגלגלים של צד ימין. בין הפניות יש עצירה.
לחצו "הפעלה" כדי לראות את הקוד רץ.
הקוד
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.
רק פין 4 ב־HIGH. הגלגלים של צד שמאל דוחפים קדימה, צד ימין עומד, והמכונית מסתובבת ימינה.
רק פין 6 ב־HIGH. עכשיו צד ימין דוחף וצד שמאל עומד, והמכונית מסתובבת שמאלה.
כל ארבעת הפינים ב־LOW. אף מנוע לא מקבל חשמל, והמכונית עומדת.
סימן שאצלכם 4 ו־5 מחוברים לצד ימין. מחליפים בקוד בין 4 ל־6 בשתי הפניות, וזהו.
אתגר: פנייה חדה יותר. במקום לעצור את הצד השני, סובבו אותו אחורה (פין 7 ב־HIGH בפנייה ימינה). המכונית תסתובב במקום.
עוקב קו עם חיישן אחד
החיישן לא נוסע על הקו, אלא על הגבול שלו: חצי על שחור וחצי על לבן. רואה לבן? פונים שמאלה חזרה לקו. רואה שחור? פונים ימינה החוצה. באמצע? ישר.
הגלגלים שנוסעים נצבעים בצהוב. הנקודה האדומה היא החיישן, והקו האדום הוא הדרך שהוא עבר. פעמיים־שלוש בסיבוב המכונית סוטה בכוונה, ורואים איך הקוד מחזיר אותה לגבול.
חיישן מרחק: צהוב (Trig) לפין 12, כתום (Echo) לפין 13, כמו בחיישן מרחק. באזר: פלוס לשורה S בפין 11, מינוס לשורה G. המדידה קורית רק פעם ב־50 אלפיות שנייה, ומחכה להד לכל היותר 3 אלפיות שנייה, כך שהמכונית ממשיכה לעקוב אחרי הקו בלי הפרעה. משהו קרוב מ־20 ס"מ? המכונית עוצרת, הבאזר מצפצף שתי שניות, ואז ממשיכים לנסוע.
לד אדום לפין 8 ולד כחול לפין 9 בלוח ההרחבה, בדיוק כמו בשני לדים בלוח ההרחבה. לבן ופונים שמאלה: אדום. שחור ופונים ימינה: כחול. ישר: שניהם כבויים.
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.
מעתיקים, מדביקים ב־Arduino IDE, מעלים ופותחים Serial Monitor על 115200.
לאן מחברים? כל הפינים של המכונית
רגל קצרה ← G
רגל קצרה ← G
מינוס ← G
Vcc ← V
GND ← G
אדום ← V
חום ← G
ימין: 4 קדימה, 5 אחורה
הכול על לוח ההרחבה. בכל טור: S = הסיגנל (הפין עצמו), V = 5 וולט, G = גראונד. חוט אדום תמיד לפלוס, חוט חום תמיד לגראונד.
הסבר מפורט: איך חיישן אחד מחזיק מכונית על הקו
כל הסוד בשלוש שורות של if. אבל כדי להבין למה הן עובדות, צריך להבין קודם מה החיישן רואה, למה הוא נוסע דווקא על הגבול, ולמה המכונית תמיד קצת מתנדנדת.
1מה החיישן רואה?
החיישן לא רואה נקודה אחת, אלא עיגול קטן על הרצפה (העיגול האדום). הוא שולח אור אינפרה אדום ומודד כמה ממנו חזר. לבן מחזיר הרבה אור, שחור בולע אותו. analogRead(A0) הופך את זה למספר: ככה שיותר שחור בתוך העיגול, המספר גבוה יותר.
שימו לב למשהו חשוב: כשהעיגול בדיוק על הגבול, חצי שחור וחצי לבן, המספר באמצע. זה מה שהופך חיישן אחד לחכם: הוא לא רק אומר "שחור" או "לבן", הוא אומר גם "אני על הגבול".
2שלושה מצבים, שלוש פעולות
המכונית נוסעת למעלה, הקו השחור משמאל לה והרצפה הלבנה מימין. החיישן יושב על הצד הימני של הקו. אם הוא רואה לבן, המכונית זזה ימינה מדי, אז פונים שמאלה חזרה לקו: הגלגלים השמאליים עוצרים והימניים ממשיכים. אם הוא רואה שחור, המכונית נכנסה שמאלה מדי, אז פונים ימינה. ואם הוא באמצע, נוסעים ישר.
3הזיגזג: ככה זה נראה בתנועה
חיישן: —
השביל האדום הוא הדרך שהחיישן עבר. הוא אף פעם לא ישר לגמרי: המכונית יוצאת קצת ללבן, מתקנת, נכנסת קצת לשחור, מתקנת שוב. זה בסדר גמור, ככה עובד עוקב קו. בארדואינו אמיתי הלולאה loop() רצה אלפי פעמים בשנייה, אז התיקונים קטנים מאוד והנסיעה נראית כמעט חלקה.
עכשיו לחצו "להתחיל בצד השני" וראו מה קורה כשהחיישן על הצד השמאלי של הקו, עם אותו קוד בדיוק.
4למה לא באמצע הקו?
משמאל: חיישן שנוסע באמצע הקו רואה שחור כל הזמן. ברגע שהמכונית סוטה, הוא רואה לבן, אבל לבן בצד ימין ולבן בצד שמאל נראים בדיוק אותו דבר. המכונית לא יודעת לאן לחזור. מימין: על הגבול, לבן יכול להיות רק בצד אחד ושחור רק בצד השני. הצבע עצמו אומר לאן לפנות. בגלל זה עם שני חיישנים אפשר לנסוע באמצע הקו, אבל עם חיישן אחד נוסעים על הגבול.
5בדקו את עצמכם: מה המכונית תעשה?
החיישן קורא: —
נכון: 0 מתוך 0
חיבור החיישן ללוח ההרחבה
שלושת החוטים נכנסים לאותו טור, A0 (המסומן בקו צהוב), כל חוט לשורה שלו: הכתום לשורה S (הסיגנל, מה שהקוד קורא ב־analogRead(A0)), האדום לשורה V (5 וולט), והחום לשורה G (גראונד). אותו סדר בדיוק גם בצד של החיישן.
החיישן יצא מהקו. turnLeft: צד שמאל עוצר, צד ימין נוסע, והמכונית חוזרת לגבול.
החיישן נכנס עמוק לקו. turnRight: צד ימין עוצר, והמכונית יוצאת החוצה לגבול.
החיישן בדיוק על הגבול. driveForward: שני הצדדים נוסעים ישר.
פותחים Serial Monitor על 115200, מעבירים את החיישן מעל לבן ומעל שחור, ומעדכנים את 20 ו־100 לפי המספרים שרואים.
המכונית בורחת מהקו במקום לחזור אליו? היא על הצד השני של הגבול. שמים אותה בצד השני, או מחליפים בקוד בין turnLeft ל־turnRight.
חיישן מרחק אולטרסוני
החיישן צועק צעקה שאנחנו לא שומעים, ומודד כמה זמן לוקח לה לחזור. כמו עטלף. מהזמן הזה הארדואינו מחשב את המרחק לקיר.
למעלה: הגלים יוצאים מה־T, פוגעים בקיר וחוזרים ל־R. למטה: מה הארדואינו רואה בפינים. הקו הכתום של ECHO נשאר למעלה בדיוק כל זמן שהקול בדרך.
הקוד
חיבור החיישן ללוח ההרחבה
שלושה חוטים נכנסים לטור 12: החום לשורה G, האדום לשורה V והצהוב (Trig) לשורה S. הכתום (Echo) הולך לשורה S בטור 13. כל החיישן יושב בקבוצה 13 12. פין 11 שמור לבאזר, עם פלוס ל־S ומינוס ל־G.

שתי "עיניים" שהן בעצם רמקול ומיקרופון. T (Transmitter) שולח, R (Receiver) מקשיב.
הארדואינו מעלה את Trig ל־HIGH לעשר מיליוניות שנייה. החיישן שולח שמונה "ציוצים" של 40,000 הרץ, גבוה מדי בשביל האוזן שלנו.
ברגע הצעקה החיישן מעלה את Echo ל־HIGH, ומוריד אותו כשההד חוזר. pulseIn(echoPin, HIGH) מודד כמה מיקרו־שניות הוא היה למעלה.
הקול עובר 0.034 ס"מ בכל מיקרו־שנייה. כופלים בזמן ומחלקים ב־2, כי הקול הלך לקיר וגם חזר. 1,000 מיקרו־שניות הן בערך 17 ס"מ.
עובד טוב מ־2 ס"מ ועד כ־4 מטר. בד, ספוג או וילון בולעים את הקול, וקיר עקום מקפיץ אותו הצידה. אז לפעמים יוצאים מספרים מוזרים.
מחברים גם את הלדים מפין 8 ו־9: כחול כשהקיר רחוק מ־20 ס"מ, אדום כשהוא קרוב יותר. והשלב הבא: מכונית שעוצרת לפני קיר.
חיישן ויברציה
בתוך החיישן יש קפיץ קטן שנוגע ולא נוגע. כשנוקשים על השולחן או מזיזים את החיישן, הקפיץ רועד, והחיישן שולח לארדואינו סימן. הארדואינו מדליק את הלד בפין 13.
מעתיקים, מדביקים ב־Arduino IDE, מעלים ופותחים Serial Monitor על 9600.
Serial Monitor
כשאין רעידה, פין 4 קורא LOW. ברגע של רעידה הוא קופץ ל־HIGH, והלד נדלק לשנייה אחת.
הקוד
חיבור החיישן ללוח ההרחבה
שלושה חוטים, כולם לטור 4: DO לשורה S, VCC לשורה V, GND לשורה G. את הלד לא צריך לחבר: בפין 13 יש לד קטן מובנה על הארדואינו, מסומן באות L.
בתוך הגליל הקטן יש קפיץ ומוט. במנוחה הם לא נוגעים זה בזה. כשמשהו רועד, הקפיץ נוגע במוט לרגע קצר מאוד, ונסגר מעגל.
פוטנציומטר שקובע כמה רגיש החיישן. מסובבים עם מברג קטן: ברגישות גבוהה גם נקישה עדינה על השולחן מדליקה את הלד.
delay(1000)?הרעידה נמשכת אלפיות שנייה. בלי ההשהיה הלד היה מהבהב כל כך מהר שלא היינו רואים אותו. ככה הוא נשאר דולק שנייה שלמה.
בחלק מהחיישנים 0 ו־1 הפוכים: הלד דולק כל הזמן ונכבה ברעידה. פשוט מחליפים בקוד את HIGH ב־LOW בשורת ה־if.
סופרים נקישות: כל רעידה מוסיפה 1 למשתנה ומדפיסה אותו. אחרי 3 נקישות מדליקים את הלד לשלוש שניות. מנעול סודי בנקישות!
על המכונית פינים 4 עד 7 תפוסים על ידי גשר ה־H. התרגיל הזה הוא על ארדואינו בלי המכונית. כשמחברים את החיישן למכונית, מעבירים אותו לפין פנוי ומשנים את vibPin בקוד.
🔧 הרכבת המכונית
בונים את המכונית שלב אחרי שלב, מהשלדה התחתונה ועד הנסיעה הראשונה. לוחצים "הבא", והחלק החדש נדלק בציור.
תרשים החיבורים של הערכה
לוחצים על התרשים כדי לפתוח אותו בגודל מלא. בתרשים: החזית למעלה, הצד של המנועים שפונה פנימה הוא הצד התחתון שלהם. הפינים בתרשים הם של קוד הערכה. בשיעורים במעבדה משתמשים בפינים שבטבלה שלמטה.
טבלת החיבורים של המעבדה
| רכיב | חוט / רגל | לאן |
|---|---|---|
| מנועים ימין (M1, M2) | שני השחורים · שני האדומים | OUT1 · OUT2 |
| מנועים שמאל (M3, M4) | שני השחורים · שני האדומים | OUT4 · OUT3 |
| סוללה | אדום (דרך המתג) · שחור | +12V · GND של L298N |
| L298N ← לוח ההרחבה | סגול · אפור · לבן · שחור | IN1→7 · IN2→6 · IN3→5 · IN4→4 |
| L298N ← לוח ההרחבה | אדום · חום | +12V→VIN · GND→GND |
| חיישן קו | S · V · G | A0 |
| חיישן מרחק HC-SR04 | כתום Echo · צהוב Trig · אדום Vcc · חום GND | 13 · 12 · 5V · GND |
| באזר | S | 11 |
| לדים | אדום · כחול (רגל ארוכה ל־S) | 8 · 9 |
מחברים ומנתקים חוטים רק כשהמתג כבוי והסוללות בחוץ. בבדיקה הראשונה מרימים את המכונית כך שהגלגלים באוויר.
חיישן קו 4 ערוצים
כרטיס בקרה אחד וארבעה ראשי חיישן קטנים. כל ראש מסתכל על הרצפה ואומר רק דבר אחד: לבן או שחור. עם ארבעה ראשים המכונית יודעת בדיוק איפה הקו נמצא.
לחצו על ריבוע הרצפה מתחת לכל ראש כדי להחליף בין לבן לשחור, וראו מה קורה לנורית וליציאה.
Serial Monitor: 0 0 0 0
הקוד: קריאה של ארבעת החיישנים
מעתיקים, מדביקים ב־Arduino IDE ומעלים ללוח.
איך החיישן יודע אם זה לבן או שחור?
בכל ראש יש שני רכיבים: המשדר (השחור) שולח אור אינפרה אדום שהעין שלנו לא רואה, והמקלט (הכחול) בודק כמה ממנו חזר. משטח לבן מחזיר את האור כמו מראה עמומה, ומשטח שחור בולע אותו. טיפ לכיתה: מצלמת טלפון רואה אינפרה אדום, אז אפשר לכוון אותה אל המשדר ולראות אותו דולק בסגול.
להרחבה: פרויקט רובוט עוקב קו ב־Arduino Project Hub (באנגלית), עם שני חיישנים, גשר H ושליטה במהירות.
בכל ראש יש שני "עיניים": נורית אינפרה אדום ששולחת אור לרצפה, ומקלט שבודק כמה אור חזר. לבן מחזיר הרבה אור, שחור בולע אותו.
השבב במרכז משווה את האור שחזר לגבול שקבענו, ומוציא תשובה פשוטה: 0 או 1. לכל ערוץ יש נורית קטנה שנדלקת על לבן.
פוטנציומטר לכל ערוץ. מסובבים עם מברג קטן עד שהנורית נדלקת על לבן ונכבית על הקו השחור. כל ערוץ מכוונים בנפרד.
VCC ל־5V, GND ל־GND, ו־OUT1 עד OUT4 לפינים 8, 9, 10, 11 בשורת S של לוח ההרחבה. פינים 4 עד 7 כבר תפוסים על ידי הגשר.
הראשים עובדים הכי טוב בגובה של כחצי עד סנטימטר וחצי מהרצפה. גבוה מדי, הם כבר לא מבחינים בין לבן לשחור. אם בחיישן שלכם 0 ו־1 הפוכים, זה בסדר: בודקים ב־Serial Monitor ומתאימים את הקוד.
🏁 רובוט עוקב קו
🎶 נגן מוסיקה ושעון
🗑️ פח חכם
