Bluetooth: המכונית מדברת · כל קובץ בעמוד משלו, עם הקוד המלא וכפתור הורדה.Bluetooth: the car talks · one file per page, with the full code and a download button.
⬇ להוריד הכל (zip)Download all (zip)
מחזיר כל תו שמקלידים, עם המספר שלו. בודקים קודם בכבל, ואז באוויר.Echoes every character you type, with its number. Test on the cable first, then over the air.
/* Robotika – Lesson 4 · LEVEL 1: Hello over Bluetooth (echo) ---------------------------------------------------------- The big idea: the HC-05 is a WIRELESS SERIAL CABLE. This sketch is plain Serial code - it works exactly the same over the USB cable and over Bluetooth. Nothing in the code "knows" about Bluetooth. What it does: whatever you type is sent back to you, one character at a time, with its number (ASCII code). Watch for the HIDDEN characters that the Enter key adds: '\n' (10) and sometimes '\r' (13). Test 1 - USB: upload, open Serial Monitor (9600), type "F" + Enter. Test 2 - Bluetooth: pair the HC-05, pick its COM port, type again. Wiring (HC-05): VCC -> 5V GND -> GND HC-05 TXD -> Arduino RX (D0) HC-05 RXD <- Arduino TX (D1) through a divider: D1 --[1k]--+--> RXD | [2k] | GND (the HC-05 RX pin wants ~3.3V) !! D0/D1 are also the USB upload pins. UNPLUG the two HC-05 data wires while uploading, then plug them back.*/void setup() { Serial.begin(9600); // HC-05 default speed is 9600 pinMode(LED_BUILTIN, OUTPUT); // the small "L" LED on the board (pin 13) Serial.println("Hello! Type something and I'll send it back.");}void loop() { // Is there at least one character waiting for us? if (Serial.available() > 0) { char c = Serial.read(); // take ONE character out of the queue digitalWrite(LED_BUILTIN, HIGH); // blink on every character we get Serial.print("Got: "); if (c == '\n') Serial.print("\\n <- hidden 'new line' from Enter"); else if (c == '\r') Serial.print("\\r <- hidden 'carriage return'"); else Serial.print(c); Serial.print(" (code "); Serial.print((int)c); // the character's number Serial.println(")"); delay(30); digitalWrite(LED_BUILTIN, LOW); }}
1 = דולק, 0 = כבוי, ? = מצב. מתעלמים מתווי ה-Enter הנסתרים.1 = on, 0 = off, ? = state. Hidden Enter characters are ignored.
/* Robotika – Lesson 4 · LEVEL 2: Commands - turn an LED on and off ---------------------------------------------------------------- Now the characters MEAN something. We agree on a tiny "language" (a protocol) between the computer and the Arduino: '1' -> LED on '0' -> LED off '?' -> tell me the LED's state The Arduino answers every command, so we can SEE that it understood. Hidden Enter characters ('\n', '\r') are simply ignored. Wiring: same as Level 1 (HC-05 on D0/D1). The LED is the built-in "L" LED (pin 13) - or connect your own LED + resistor to D13. !! Unplug the HC-05 data wires while uploading.*/const int LED_PIN = LED_BUILTIN; // pin 13bool ledOn = false;void setup() { Serial.begin(9600); pinMode(LED_PIN, OUTPUT); Serial.println("Ready. Commands: 1 = on, 0 = off, ? = state");}void loop() { if (Serial.available() > 0) { char cmd = Serial.read(); // 1) ignore the invisible characters that Enter adds if (cmd == '\n' || cmd == '\r') return; // 2) do what the command says - and answer if (cmd == '1') { ledOn = true; digitalWrite(LED_PIN, HIGH); Serial.println("OK: LED on"); } else if (cmd == '0') { ledOn = false; digitalWrite(LED_PIN, LOW); Serial.println("OK: LED off"); } else if (cmd == '?') { Serial.println(ledOn ? "LED is on" : "LED is off"); } else { Serial.print("Unknown command: "); Serial.println(cmd); } }}
F B L R S מהמחשב, והחיישן מסרב לנסוע לתוך קיר. חיווט כמו בשיעור 2 + מודול על D0/D1.F B L R S from the computer, and the sensor refuses to drive into a wall. Lesson 2 wiring + module on D0/D1.
/* Robotika – Lesson 4 · LEVEL 3: Drive the car over Bluetooth ----------------------------------------------------------- Same motor functions as in every lesson - only the input changed: the commands now arrive as letters over Bluetooth. F = forward B = back L = turn left R = turn right S = stop A command stays on until the next one ("latched"): send F once and the car keeps driving until you send S (or another move). Safety layer: the HC-SR04 is still on the front. If you are driving forward and something is closer than STOP_CM, the car REFUSES and stops - even if you keep sending F. (That was the Lesson 3 challenge.) Wiring (the car - same as Lesson 2): HC-SR04: Trig -> D9 Echo -> D10 L298N ch. A (both LEFT motors): ENA D5, IN1 D2, IN2 D3 L298N ch. B (both RIGHT motors): ENB D6, IN3 D4, IN4 D7 HC-05: TXD -> D0 (RX) RXD <- D1 (TX) via 1k/2k divider VCC -> 5V GND -> GND Motor battery and Arduino MUST share ground. !! Unplug the HC-05 data wires (D0/D1) while uploading. Works from: Arduino IDE Serial Monitor on the Bluetooth COM port, or an Android "Bluetooth serial terminal" app. (iPhones can't talk to HC-05.)*/// --- HC-SR04 (front) ---const int trigPin = 9;const int echoPin = 10;// --- L298N motor driver ---const int ENA = 5, IN1 = 2, IN2 = 3, IN3 = 4, IN4 = 7, ENB = 6;const int SPEED = 160; // 0..255const int STOP_CM = 15; // refuse to drive forward closer than thischar move = 'S'; // the command we are currently doingvoid setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); stopCar(); Serial.println("Car ready. F B L R S");}void loop() { // 1) INPUT: did a command arrive? if (Serial.available() > 0) { char c = toupper(Serial.read()); // 'f' works like 'F' if (c == 'F' || c == 'B' || c == 'L' || c == 'R' || c == 'S') { move = c; Serial.print("OK "); Serial.println(move); } else if (c != '\n' && c != '\r') { Serial.print("Unknown: "); Serial.println(c); } } // 2) SAFETY: never drive forward into an obstacle if (move == 'F') { int distanceCm = getDistanceCm(); if (distanceCm <= STOP_CM) { move = 'S'; Serial.print("Obstacle at "); Serial.print(distanceCm); Serial.println(" cm - stopped!"); } } // 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; }}// ---------- the four moves (same as every lesson) ----------void forward() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); // left side forward digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); // right side forward analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void backward() { digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); // left side back digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); // right side back analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void turnRight() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); // left forward digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); // right back -> spins right analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void turnLeft() { digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); // left back digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); // right forward -> spins left analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void stopCar() { analogWrite(ENA, 0); analogWrite(ENB, 0); digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);}// ---------- the sensor ----------int getDistanceCm() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH, 25000); // timeout so we never get stuck if (duration == 0) return 999; // no echo = nothing close = clear return duration * 0.0343 / 2;}
ג'ויסטיק באפליקציה (אנדרואיד). המודול עובר ל-D11/D12 — Dabble ב-Uno לא משתמש ב-D0/D1.A gamepad in the app (Android). The module moves to D11/D12 — Dabble on the Uno doesn't use D0/D1.
/* Robotika – Lesson 4 · LEVEL 3b (option): Drive with the Dabble app (Android) --------------------------------------------------------------------------- Same car, same five motion functions - but the remote is the free "Dabble" app and its on-screen GamePad instead of typed letters. Hold an arrow to drive; let go and the car stops. !! Dabble on the Uno does NOT use D0/D1. The library talks to the module through SoftwareSerial. Its default pins are D2/D3 - our motor pins! - so we move it to D11/D12 with Dabble.begin(9600, 11, 12). Bonus: D0/D1 stay free, so you DON'T unplug anything to upload, and Serial Monitor still works over USB for debugging. Phones: Android + HC-05 works. iPhone Dabble only talks to BLE modules (HM-10), not to the HC-05. Setup: 1) Install "Dabble" on the phone (Play Store). 2) Library: "Dabble" (Manage Libraries -> search "Dabble"). 3) In the app: tap the connect icon, pick your module (PIN 1234 if asked), then open the GamePad module. Wiring (the car - as in Lesson 2, module moved to D11/D12): HC-SR04: Trig -> D9 Echo -> D10 L298N ch. A (both LEFT motors): ENA D5, IN1 D2, IN2 D3 L298N ch. B (both RIGHT motors): ENB D6, IN3 D4, IN4 D7 HC-05: TXD -> D11 RXD <- D12 via the 1k/2k divider VCC -> 5V GND -> GND*/#define CUSTOM_SETTINGS#define INCLUDE_GAMEPAD_MODULE#include <Dabble.h>const int trigPin = 9;const int echoPin = 10;const int ENA = 5, IN1 = 2, IN2 = 3, IN3 = 4, IN4 = 7, ENB = 6;const int SPEED = 160;const int STOP_CM = 15; // refuse to drive forward closer than thisvoid setup() { Serial.begin(9600); // USB - free for debugging Dabble.begin(9600, 11, 12); // module: RX = D11, TX = D12 pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); stopCar();}void loop() { Dabble.processInput(); // 1) INPUT: read what the phone sent if (GamePad.isUpPressed()) { // 2) SAFETY: never drive into a wall if (getDistanceCm() <= STOP_CM) stopCar(); else forward(); } else if (GamePad.isDownPressed()) backward(); // 3) OUTPUT else if (GamePad.isLeftPressed()) turnLeft(); else if (GamePad.isRightPressed()) turnRight(); else stopCar(); // finger off -> stop}// ---------- the four moves (same as every lesson) ----------void forward() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void backward() { digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void turnRight() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void turnLeft() { digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENA, SPEED); analogWrite(ENB, SPEED);}void stopCar() { analogWrite(ENA, 0); analogWrite(ENB, 0); digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);}int getDistanceCm() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH, 25000); if (duration == 0) return 999; return duration * 0.0343 / 2;}
המכונית מדווחת D=מרחק,M=תנועה,S=מהירות חמש פעמים בשנייה. 1–9 משנים מהירות.The car reports D=distance,M=move,S=speed five times a second. 1–9 change speed.
/* Robotika – Lesson 4 · LEVEL 4: Telemetry - the car talks back ------------------------------------------------------------- Bluetooth is TWO-WAY. Level 3 only listened. Now the car also REPORTS what it sees, 5 times a second, as one line of text: D=23,M=F,S=160 | | '-- S = speed (0..255) | '------ M = current move (F/B/L/R/S) '----------- D = distance in cm (999 = nothing in front) One line = one message. key=value pairs, separated by commas - simple for any program (even a web page) to read. New commands: '1'..'9' = speed (1 slow ... 9 full) New idea: millis() - a clock that does NOT stop the program. delay(200) would freeze the car and miss commands. Wiring: exactly as Level 3. !! Unplug the HC-05 data wires (D0/D1) while uploading.*/const int trigPin = 9;const int echoPin = 10;const int ENA = 5, IN1 = 2, IN2 = 3, IN3 = 4, IN4 = 7, ENB = 6;const int STOP_CM = 15;const unsigned long REPORT_MS = 200; // send a report every 200 msint speed = 160; // not const any more - commands change itchar move = 'S';int distanceCm = 999;unsigned long lastReport = 0;void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); stopCar();}void loop() { // 1) INPUT: commands from the computer if (Serial.available() > 0) { char c = toupper(Serial.read()); if (c == 'F' || c == 'B' || c == 'L' || c == 'R' || c == 'S') { move = c; } else if (c >= '1' && c <= '9') { speed = map(c - '0', 1, 9, 80, 255); // '1' -> 80 ... '9' -> 255 } // anything else ('\n', '\r', typos) is ignored } // 2) SENSOR + SAFETY distanceCm = getDistanceCm(); if (move == 'F' && distanceCm <= STOP_CM) move = 'S'; // 3) OUTPUT: motors switch (move) { case 'F': forward(); break; case 'B': backward(); break; case 'L': turnLeft(); break; case 'R': turnRight(); break; default: stopCar(); break; } // 4) TELEMETRY: report without stopping the program 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); }}// ---------- the four moves (now with a changing speed) ----------void drive(int a1, int a2, int b1, int b2) { digitalWrite(IN1, a1); digitalWrite(IN2, a2); digitalWrite(IN3, b1); digitalWrite(IN4, b2); analogWrite(ENA, speed); analogWrite(ENB, speed);}void forward() { drive(HIGH, LOW, HIGH, LOW); }void backward() { drive(LOW, HIGH, LOW, HIGH); }void turnRight() { drive(HIGH, LOW, LOW, HIGH); }void turnLeft() { drive(LOW, HIGH, HIGH, LOW); }void stopCar() { analogWrite(ENA, 0); analogWrite(ENB, 0); digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);}int getDistanceCm() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH, 25000); if (duration == 0) return 999; return duration * 0.0343 / 2;}
גשר בין ה-Serial Monitor למודול במצב AT: AT+NAME=CAR-07.A bridge between the Serial Monitor and the module in AT mode: AT+NAME=CAR-07.
/* Robotika – Lesson 4 · BONUS: Give your module its own name (AT mode) -------------------------------------------------------------------- In a room full of modules that are ALL called "HC-05", finding yours is hard. Here we talk to the module ITSELF (not through it) and rename it. This sketch is a "bridge": whatever you type in the Serial Monitor goes to the module, and the module's answers come back to the monitor. We use SoftwareSerial on D11/D12, so the USB cable stays free. Wiring (just the Arduino + HC-05, the car can stay disconnected): HC-05 VCC -> 5V GND -> GND HC-05 TXD -> D11 HC-05 RXD <- D12 through the 1k/2k divider (same as before) Enter AT mode (HC-05): 1) Unplug the HC-05's VCC wire. 2) HOLD the small button on the module, plug VCC back in, release. 3) The LED now blinks SLOWLY (about once every 2 seconds) = AT mode. Serial Monitor: 9600 baud, line ending "Both NL & CR". Then type: AT -> OK AT+NAME=CAR-07 -> OK (use your own number!) AT+NAME? -> +NAME:CAR-07 (some modules only answer this while the button is held) Power the module off and on to leave AT mode. On your computer, "remove" the old HC-05 device and pair again with the new name. HC-06 instead? It has no button and no AT mode switch: set BT_BAUD to 9600, line ending "No line ending", and type AT+NAMECAR-07 (no "=") while it is NOT connected.*/#include <SoftwareSerial.h>SoftwareSerial bt(11, 12); // RX = D11, TX = D12const long BT_BAUD = 38400; // HC-05 AT mode speed (HC-06: 9600)void setup() { Serial.begin(9600); // to the computer bt.begin(BT_BAUD); // to the module Serial.println("Bridge ready. Type AT and press Enter.");}void loop() { if (Serial.available()) bt.write(Serial.read()); // computer -> module if (bt.available()) Serial.write(bt.read()); // module -> computer}