היום נחבר למכונית מודול Bluetooth, נשלח לה פקודות מהמחשב — והיא גם תענה לנו. נגלה שבלוטות' הוא בעצם כבל סיריאלי בלי חוט. Today we add a Bluetooth module to the car, send it commands from the computer — and it will answer back. We'll find out that Bluetooth is really a serial cable without the wire.
ניווט: חצים ← → במקלדת, או הכפתורים למטה · לחצו EN לבדיקת מונחים באנגלית Navigate: ← → arrow keys, or the buttons below · press עב for Hebrew
שניהם עובדים היום באותה צורה. ל-HC-05 יש 6 רגליים וכפתור קטן, ל-HC-06 בדרך כלל 4 רגליים.Both work the same way today. The HC-05 has 6 pins and a small button; the HC-06 usually has 4 pins.
זו השיטה לכל רכיב, בכל שיעור. היום נענה עליה יחד עבור ה-HC-05 — והשלבים של השיעור הם בדיוק התשובות.This is the method for every part, every lesson. Today we answer it together for the HC-05 — and the lesson's levels are exactly the answers.
| רגלPin | מה היא עושהWhat it does | היום?Today? |
|---|---|---|
| VCC | מתח 5V5V power | ✓ |
| GND | אדמהGround | ✓ |
| TXD | המודול שולח ← לארדואינוModule sends → to Arduino | ✓ |
| RXD | המודול מקבל ← מהארדואינו (3.3V!)Module receives ← from Arduino (3.3V!) | ✓ |
| STATE | HIGH כשיש חיבורHIGH while connected | — |
| EN / KEY | כניסה למצב הגדרות (AT)Enter settings (AT) mode | בונוסbonus |
הקוד מחזיר כל תו שהוא מקבל, יחד עם המספר שלו. אין בו שום דבר של Bluetooth — רק Serial.The code sends back every character it gets, with its number. There's nothing Bluetooth in it — just Serial.
void loop() {
if (Serial.available() > 0) { // is a character waiting?
char c = Serial.read(); // take ONE out
Serial.print("Got: ");
Serial.print(c);
Serial.print(" (code ");
Serial.print((int)c); // its number
Serial.println(")");
}
}📄 level1_bt_hello.ino📄 level1_bt_hello.ino
בחלק מגרסאות macOS החיבור לא יציב — אם זה קורה, עוברים למחשב Windows או לאנדרואיד.On some macOS versions the connection is flaky — if so, switch to a Windows laptop or Android.
תווים שמגיעים נכנסים לתור (כמו תור בדואר) ומחכים שם עד שנקרא אותם:Arriving characters go into a queue (like a line at the post office) and wait there until we read them:
זה פרוטוקול — הסכם בין שני הצדדים. הכי פשוט שיש: קל להקליד, קל לבדוק ב-if.That's a protocol — an agreement between both sides. The simplest there is: easy to type, easy to check with if.
if (Serial.available() > 0) {
char cmd = Serial.read();
// ignore the hidden Enter characters
if (cmd == '\n' || cmd == '\r') return;
if (cmd == '1') {
digitalWrite(LED_PIN, HIGH);
Serial.println("OK: LED on"); // always answer!
} else if (cmd == '0') {
digitalWrite(LED_PIN, LOW);
Serial.println("OK: LED off");
} else {
Serial.println("Unknown command");
}
}| שולחיםSend | הארדואינו עושהThe Arduino does | ועונהand answers |
|---|---|---|
| 1 | מדליק את ה-LEDturns the LED on | OK: LED on |
| 0 | מכבהturns it off | OK: LED off |
| ? | בודק מצבchecks state | LED is on |
| x | לא מכירdoesn't know it | Unknown command: x |
ה-LED הוא נורית ה-L הקטנה שעל הלוח (פין 13). אפשר לחבר גם LED משלכם עם נגד ל-D13.The LED is the small L LED on the board (pin 13). You can also connect your own LED + resistor to D13.
אותן חמש פונקציות תנועה מכל השיעורים. רק הקלט השתנה: עכשיו הוא מגיע כאות.The same five motion functions from every lesson. Only the input changed: now it arrives as a letter.
מרחק מהחיישן:Sensor distance: 60 cm
| פקודהCommand | IN1 | IN2 | IN3 | IN4 |
|---|---|---|---|---|
| S | 0 | 0 | 0 | 0 |
הפקודה "נשארת" עד הפקודה הבאה: שולחים F פעם אחת והמכונית נוסעת עד S.A command "stays on" until the next one: send F once and the car drives until S.
void loop() {
// 1) INPUT: did a command arrive?
if (Serial.available() > 0) {
char c = toupper(Serial.read()); // 'f' = 'F'
if (c == 'F' || c == 'B' || c == 'L' || c == 'R' || c == 'S') {
move = c;
Serial.print("OK ");
Serial.println(move);
}
}
// 2) SAFETY: never drive into a wall
if (move == 'F' && getDistanceCm() <= STOP_CM) move = 'S';
// 3) OUTPUT: do the current move
switch (move) {
case 'F': forward(); break;
case 'B': backward(); break;
case 'L': turnLeft(); break;
case 'R': turnRight(); break;
default: stopCar(); break;
}
}דרך מסודרת לכתוב הרבה if / else if על אותו משתנה: "אם move הוא F — קדימה; אם B — אחורה...". break אומר "סיימנו, צאו מה-switch". default = כל מקרה אחר.A tidy way to write many if / else if checks on the same variable: "if move is F — forward; if B — back...". break means "done, leave the switch". default = any other case.
החיישן משיעור 2 עדיין על המכונית. אתם מחליטים לאן לנסוע — אבל אם יש קיר קרוב מ-15 ס"מ, המכונית מסרבת לנסוע קדימה.The sensor from Lesson 2 is still on the car. You decide where to go — but if a wall is closer than 15 cm, the car refuses to drive forward.
📄 level3_bt_car.ino · חיווט המכונית כמו בשיעור 2 (IN1 על D2), והמודול על D0/D1.📄 level3_bt_car.ino · car wiring as in Lesson 2 (IN1 on D2), module on D0/D1.
במקום להקליד אותיות — ג'ויסטיק על מסך הטלפון. מחזיקים חץ = נוסעים, עוזבים = עוצרים. אותן פונקציות תנועה, אותה שכבת בטיחות.Instead of typing letters — a gamepad on the phone screen. Hold an arrow = drive, let go = stop. Same motion functions, same safety layer.
הבונוס: D0/D1 נשארים פנויים — לא צריך לנתק כלום לפני Upload, וה-Serial Monitor בכבל ממשיך לעבוד.The bonus: D0/D1 stay free — nothing to unplug before Upload, and the Serial Monitor on the cable keeps working.
אייפון: Dabble עובד שם רק עם מודולי BLE (כמו HM-10), לא עם HC-05.iPhone: Dabble there only works with BLE modules (like HM-10), not the HC-05.
#define CUSTOM_SETTINGS
#define INCLUDE_GAMEPAD_MODULE
#include <Dabble.h>
void setup() {
Dabble.begin(9600, 11, 12); // module on RX=D11, TX=D12
}
void loop() {
Dabble.processInput(); // read the phone
if (GamePad.isUpPressed()) {
if (getDistanceCm() <= STOP_CM) stopCar(); // safety
else forward();
}
else if (GamePad.isDownPressed()) backward();
else if (GamePad.isLeftPressed()) turnLeft();
else if (GamePad.isRightPressed()) turnRight();
else stopCar();
}📄 level3b_dabble_car.ino · Dabble מדבר ב"שפה" משלו (בינארית) — לכן בשלב 4 חוזרים לפקודות טקסט.📄 level3b_dabble_car.ino · Dabble speaks its own (binary) "language" — so Level 4 goes back to text commands.
Bluetooth הוא דו-כיווני. עד עכשיו המכונית רק הקשיבה — עכשיו היא גם מדווחת, 5 פעמים בשנייה, שורה אחת בכל פעם:Bluetooth is two-way. So far the car only listened — now it also reports, 5 times a second, one line at a time:
// every 200 ms, send one report line
if (millis() - lastReport >= REPORT_MS) {
lastReport = millis();
Serial.print("D="); Serial.print(distanceCm);
Serial.print(",M="); Serial.print(move);
Serial.print(",S="); Serial.println(speed);
}למה לא delay(200)? כי בזמן ה-delay הארדואינו קפוא: לא קורא פקודות ולא בודק את החיישן. עם millis() שואלים "עברו כבר 200ms?" — וממשיכים הלאה.Why not delay(200)? Because during a delay the Arduino is frozen: it doesn't read commands or check the sensor. With millis() we ask "have 200 ms passed yet?" — and move on.
בכיתה מלאה במודולים שכולם נקראים HC-05 — קשה למצוא את שלכם. במצב AT מדברים עם המודול עצמו (לא דרכו) ומשנים לו הגדרות.In a room full of modules all called HC-05 — finding yours is hard. In AT mode you talk to the module itself (not through it) and change its settings.
| מקלידיםType | המודול עונהModule answers |
|---|---|
| AT | OK |
| AT+NAME=CAR-07 | OK |
| AT+NAME? | +NAME:CAR-07 |
| מה רואיםWhat you see | מה בודקיםWhat to check |
|---|---|
| ההעלאה נכשלת: not in syncUpload fails: not in sync | חוטי המודול עדיין על D0/D1 — מנתקים ומעלים שובThe module wires are still on D0/D1 — unplug and upload again |
| המודול לא מופיע ברשימהThe module doesn't appear in the list | הנורית מהבהבת מהר? אם לא — בדקו VCC/GND. אולי מישהו אחר כבר מחובר אליוIs the LED blinking fast? If not — check VCC/GND. Maybe someone else is already connected to it |
| מחובר, אבל לא מגיע כלוםConnected, but nothing arrives | TXD↔RX מוצלבים? בחרתם את פורט ה-Outgoing ולא את ה-Incoming? מהירות 9600 בשני הצדדים?TXD↔RX crossed? Did you pick the Outgoing port, not Incoming? 9600 on both sides? |
| מגיעות אותיות משובשותGarbled characters arrive | מהירות לא תואמת — ה-Serial Monitor וה-Serial.begin() חייבים להיות אותו מספרSpeed mismatch — the Serial Monitor and Serial.begin() must use the same number |
| כל פקודה מקבלת גם "Unknown"Every command also gets "Unknown" | תווי ה-Enter הנסתרים (\n, \r) — מתעלמים מהם בקוד, או בוחרים "No line ending"The hidden Enter characters (\n, \r) — ignore them in code, or choose "No line ending" |
| Dabble מתחבר אבל המכונית לא זזהDabble connects but the car doesn't move | המודול חייב להיות על D11/D12 (לא D0/D1), ובקוד Dabble.begin(9600, 11, 12). באפליקציה פתחתם את GamePad?The module must be on D11/D12 (not D0/D1), with Dabble.begin(9600, 11, 12) in the code. Did you open GamePad in the app? |
| הארדואינו מתאפס כשהמנועים מתחיליםThe Arduino resets when the motors start | סוללות חלשות, או חסר גראונד משותף בין הסוללה לארדואינוWeak batteries, or no common ground between the battery and the Arduino |
| החיבור נפל והמכונית ממשיכה לנסועThe connection dropped and the car keeps driving | הפקודות "נשארות" עד הפקודה הבאה — מרימים את המכונית. (אתגר: לעצור לבד אם לא הגיעה פקודה שנייה שלמה)Commands "stay on" until the next one — pick the car up. (Challenge: stop by itself if no command arrived for a full second) |
Bluetooth לא שינה את הקוד — Serial הוא Serial, בכבל או באוויר. מה שכן חדש: המצאנו פרוטוקול — הסכם על מה כל אות אומרת, ועל איך נראית שורת דיווח.Bluetooth didn't change the code — Serial is Serial, on a cable or over the air. What is new: we invented a protocol — an agreement on what each letter means, and on what a report line looks like.
💻 כל קבצי הקוד של השיעור — הורדה והסברAll of this lesson's code — download & walkthrough
תודה — נתראה בפעם הבאה! 👋Thanks — see you next time! 👋