בשיעור הקודם גרמנו לנורה להבהב — אבל היא "התעלמה" מהעולם. היום הארדואינו יתחיל לחוש אור ומרחק, להחליט בעצמו מה לעשות, ולהציג מספרים על מסך. הלולאה סוף־סוף נסגרת. Last lesson we made a light blink — but it "ignored" the world. Today the Arduino starts to sense light and distance, decide on its own what to do, and show numbers on a display. The loop finally closes.
ניווט: חצים ← → במקלדת, או הכפתורים למטה · לחצו EN למונחים באנגלית Navigate: ← → arrow keys, or the buttons below · press עב for Hebrew
בשיעור 1 אמרנו: כל רובוט הוא לולאה — חש ← חושב ← פועל. אבל ה-Blink שלנו רק חשב (טיימר) ופעל (נורה). הוא לא חש שום דבר — הוא היה מהבהב גם בחושך וגם באור, גם מול קיר וגם מול חלל ריק. In Lesson 1 we said: every robot is a loop — sense → think → act. But our Blink only thought (a timer) and acted (an LED). It never sensed anything — it would blink the same in the dark or the light, facing a wall or empty space.
היום נוסיף את החלק החסר: חישה. ברגע שלרובוט יש חוש, הוא יכול להגיב לעולם — וזה בדיוק מה שהופך מכונה ל"חכמה". Today we add the missing part: sensing. The moment a robot has a sense, it can react to the world — and that's exactly what makes a machine feel "smart".
חיישן האור הוא רכיב קטן על מודול עם 4 רגליים. ככל שמגיע אליו יותר אור, כך הוא "מעביר" מתח גבוה יותר. הארדואינו קורא את המתח הזה והופך אותו למספר. The light sensor is a small part on a 4-leg module. The more light hits it, the higher the voltage it "passes". The Arduino reads that voltage and turns it into a number.
| רגל במודולModule leg | אלTo |
|---|---|
| VCC | 5V |
| GND | GND |
| AO | A0 |
| DO | לא מחברים (בינתיים)leave unconnected (for now) |
גררו את כמות האור וראו מה הארדואינו "קורא":Drag the amount of light and see what the Arduino "reads":
בשיעור הקודם הפינים היו דיגיטליים: רק שני מצבים — דלוק/כבוי, HIGH/LOW, 1/0. כמו מתג אור בקיר. Last lesson the pins were digital: only two states — on/off, HIGH/LOW, 1/0. Like a light switch on the wall.
חיישן אור נותן הרבה יותר מזה — טווח שלם של ערכים, 0 עד 1023. כמו חוגת עמעם במקום מתג. לכן קוראים אותו מהפינים האנלוגיים (A0–A5) עם analogRead, ולא עם digitalRead. A light sensor gives much more — a whole range of values, 0 to 1023. Like a dimmer dial instead of a switch. So we read it from the analog pins (A0–A5) with analogRead, not digitalRead.
| דיגיטליDigital | אנלוגיAnalog | |
|---|---|---|
| דוגמהLike a | מתגswitch | חוגה/עמעםdial/dimmer |
| ערכיםValues | 0 / 1 | 0 … 1023 |
| פקודה לקריאהRead with | digitalRead | analogRead |
| פיניםPins | D0–D13 | A0–A5 |
| לדוגמהExample | כפתור לחוץ?button pressed? | כמה אור יש?how much light? |
הקוד הקצר הזה הוא ה"עיניים" שלנו אל תוך הארדואינו. אנחנו קוראים מספר מהחיישן ומדפיסים אותו, כדי שגם אנחנו נראה מה הארדואינו רואה. פותחים Serial Monitor במהירות 9600. This short program is our "eyes" into the Arduino. We read a number from the sensor and print it, so that we can see what the Arduino sees. Open the Serial Monitor at 9600.
const int LIGHT_PIN = A0; // sensor's AO leg
void setup() {
Serial.begin(9600); // window to the PC
}
void loop() {
int light = analogRead(LIGHT_PIN); // 0..1023
Serial.print("Light: ");
Serial.println(light);
delay(200);
}זה מה שתראו ב-Serial Monitor — כסו את החיישן ביד:This is what you'll see in the Serial Monitor — cover the sensor with your hand:
עכשiו שיש לנו מספר מהחיישן, הקוד יכול להחליט. זה ה-חושב שבלולאה. ההחלטה הכי בסיסית במחשב היא פיצול בדרך: Now that we have a number from the sensor, the code can decide. This is the think in the loop. The most basic decision a computer makes is a fork in the road:
if (light < DARK_LEVEL) {
// it's dark -> do this
} else {
// otherwise -> do that
}קוראים את זה כמו משפט בעברית: "אם האור נמוך מהסף — הדלק; אחרת — כבה." המחשב בודק את התנאי בסוגריים, ובוחר רק אחד משני המסלולים. Read it like a sentence: "if the light is below the threshold — turn on; else — turn off." The computer checks the condition in the parentheses and takes exactly one of the two paths.
גררו את האור. ראו איזה מסלול נבחר, ואת הנורה:Drag the light. See which path is chosen, and the LED:
אותו חיווט כמו שלב 1 (רק חיישן האור), ובלי רכיב חדש: נשתמש בנורה שכבר על הלוח — פין 13. עכשיו הלולאה שלמה: חש אור ← החלט ← הדלק/כבה. Same wiring as Level 1 (just the light sensor), and no new part: we use the LED that is already on the board — pin 13. Now the loop is complete: sense light → decide → on/off.
const int LIGHT_PIN = A0;
const int LED_PIN = 13;
const int DARK_LEVEL = 400; // tune to your room
void loop() {
int light = analogRead(LIGHT_PIN);
if (light < DARK_LEVEL) {
digitalWrite(LED_PIN, HIGH); // dark -> on
} else {
digitalWrite(LED_PIN, LOW); // bright -> off
}
delay(100);
}הסף 400 מופיע כקבוע עם שם בראש הקובץ — לא מספר "קסם" תקוע באמצע הקוד. כשהחדר אצלכם בהיר או חשוך יותר, משנים מקום אחד וסיימתם. זה הכלל הראשון של קוד נקי. The threshold 400 lives as a named constant at the top of the file — not a "magic number" stuck in the middle of the code. When your room is brighter or darker, you change one place and you're done. That's rule one of clean code.
void loop() {
if (analogRead(0) < 400) {
digitalWrite(13, 1);
} else {
digitalWrite(13, 0);
}
delay(100);
}מה זה 0? מה זה 13? מה זה 400? בעוד שבוע — גם אתם לא תזכרו.What's 0? What's 13? What's 400? In a week — you won't remember either.
const int LIGHT_PIN = A0;
const int LED_PIN = 13;
const int DARK_LEVEL = 400;
void loop() {
int light = analogRead(LIGHT_PIN);
if (light < DARK_LEVEL)
digitalWrite(LED_PIN, HIGH);
else
digitalWrite(LED_PIN, LOW);
delay(100);
}חיישן ה-HC-SR04 מודד מרחק בדיוק כמו עטלף: הוא שולח "ציוץ" קולי שאוזן לא שומעת, ומודד כמה זמן לקח להד לחזור. יותר זמן = העצם רחוק יותר. The HC-SR04 sensor measures distance just like a bat: it sends a sound "chirp" your ear can't hear, and times how long the echo takes to return. More time = the object is farther.
שימו לב להבדל היפה: חיישן האור מדד מתח; החיישן הזה מודד זמן. אותה פקודה לא תתאים לשניהם — לכן יש לו שתי רגליים מיוחדות: Note the lovely difference: the light sensor measured voltage; this one measures time. The same command won't fit both — so it has two special legs:
לחצו "ציוץ!" וגררו את העצם קרוב/רחוק:Press "chirp!" and drag the object near/far:
מדידת מרחק דורשת כמה שורות טכניות (ציוץ, המתנה, חישוב). אם נדחוף אותן לתוך loop(), הוא יהפוך לג'ונגל. הפתרון: נארוז אותן בפונקציה עם שם, getDistanceCm(), שמחזירה מספר. Measuring distance takes a few technical lines (chirp, wait, compute). If we cram them into loop(), it becomes a jungle. The fix: wrap them in a named function, getDistanceCm(), that returns a number.
עכשיו loop() נקרא כמו משפט: "קבל מרחק, הצג אותו". מי שרוצה לדעת איך מודדים — יורד לפונקציה. מי שלא — ממשיך לקרוא בשקט. Now loop() reads like a sentence: "get the distance, show it". Whoever wants to know how we measure — dives into the function. Whoever doesn't — keeps reading in peace.
void loop() {
int distance = getDistanceCm();
display.showNumberDec(distance);
delay(200);
}
// all the fiddly steps live here, once
int getDistanceCm() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long t = pulseIn(ECHO_PIN, HIGH);
return t * 0.0343 / 2;
}🗣️ "קח את הזמן ששמעת, הכפל במהירות הקול, חלק ב-2 (הלוך ושוב) — וקיבלת ס"מ."🗣️ "take the time you heard, times the speed of sound, divide by 2 (there and back) — and you have cm."
עד עכשיו "דיברנו" עם המחשב דרך ה-Serial Monitor. אבל רובוט אמיתי צריך להראות דברים בלי מחשב מחובר. המסך הזה מציג מספר בן 4 ספרות שרואים מהצד השני של החדר. So far we "talked" to the computer through the Serial Monitor. But a real robot needs to show things with no computer attached. This display shows a 4-digit number you can read from across the room.
| רגלPin | אלTo | מה זהWhat |
|---|---|---|
| CLK | D4 | הקצב שמסנכרןthe sync beat |
| DIO | D5 | הנתונים עצמםthe data itself |
| VCC | 5V | — |
| GND | GND | — |
זהו המסך. גררו את המרחק וראו את הספרות:This is the display. Drag the distance and watch the digits:
הפקודה: display.showNumberDec(distance);The command: display.showNumberDec(distance);
שמתם לב שלמסך יש שני חוטי מידע (CLK ו-DIO), ולא אחד? הנה למה. המסך מקבל את המספר ביט אחרי ביט (0 או 1) על חוט אחד — אבל איך הוא יודע מתי כל ביט מוכן לקריאה? Notice the display has two data wires (CLK and DIO), not one? Here's why. The display receives the number bit by bit (0 or 1) on one wire — but how does it know when each bit is ready to be read?
בלי שעון משותף, הצד המקבל לא יודע מתי הקו מחליף ערך ומתי הוא יציב. השעון הוא המטרונום ששני הצדדים סופרים לפיו. זו "תקשורת טורית" (serial): ביט-אחרי-ביט על חוט אחד, בקצב של השעון. Without a shared clock, the receiver can't tell when the line is switching versus steady. The clock is the metronome both sides count to. This is "serial communication": bit after bit on one wire, paced by the clock.
לחצו "הפעל שעון" — בכל פעימה נקלט ביט מחוט הנתונים:Press "run the clock" — on each beat one bit is captured from the data wire:
מחברים הכול: החיישן מודד, הפונקציה מחזירה מספר, והמסך מציג אותו. שימו לב כמה loop() קצר וברור — כל הטכניקה חבויה ב-getDistanceCm(). Put it together: the sensor measures, the function returns a number, the display shows it. Notice how short and clear loop() is — all the technique hides inside getDistanceCm().
#include <TM1637Display.h>
const int TRIG_PIN=9, ECHO_PIN=10;
const int CLK_PIN=4, DIO_PIN=5;
TM1637Display display(CLK_PIN, DIO_PIN);
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
display.setBrightness(5);
}
void loop() {
int distance = getDistanceCm();
display.showNumberDec(distance);
delay(200);
}📄 code/level3_sonar_display.ino · כל הקוד📄 code/level3_sonar_display.ino · all the code
הפרויקט המסכם: בדיוק כמו חיישן חניה ברכב. המסך מראה את המרחק, ונורת אזהרה מהבהבת מהר יותר ככל שמתקרבים. זו החלטה (if/else) ועוד כלי חדש — map(). The capstone: exactly like a car's parking sensor. The display shows the distance, and a warning LED blinks faster the closer you get. That's a decision (if/else) plus one new tool — map().
map() "מותח" טווח אחד על טווח אחר. כאן: מרחק 0→30 ס"מ הופך להשהיית הבהוב 40→500 מילישניות. קרוב = השהיה קטנה = הבהוב מהיר. map() "stretches" one range onto another. Here: distance 0→30 cm becomes a blink delay of 40→500 ms. Close = small delay = fast blink.
➕ חיווט נוסף: נורה + נגד 220Ω מ-D6 ל-GND (כמו בשיעור 1).➕ Added wiring: an LED + 220Ω resistor from D6 to GND (like Lesson 1).
גררו את המכשול לכיוון החיישן:Drag the obstacle toward the sensor:
const int WARN_CM = 30; // warning zone starts here
void loop() {
int distance = getDistanceCm();
display.showNumberDec(distance);
if (distance > WARN_CM) {
digitalWrite(LED_PIN, LOW); // clear
delay(100);
} else {
// closer -> smaller delay -> faster
int d = map(distance, 0, WARN_CM, 40, 500);
digitalWrite(LED_PIN, HIGH); delay(d);
digitalWrite(LED_PIN, LOW); delay(d);
}
}📄 code/level4_parking_sensor.ino📄 code/level4_parking_sensor.ino
הלולאה נסגרה: עכשיו הארדואינו חש (אור, מרחק), מחליט לבד (if/else), ופועל (מסך, נורה). זה כבר לא טיימר עיוור — זו מכונה שמגיבה לעולם. וכתבתם את זה בקוד נקי: שמות, קבועים, ופונקציה. The loop closed: now the Arduino senses (light, distance), decides on its own (if/else), and acts (display, LED). It's no longer a blind timer — it's a machine that reacts to the world. And you wrote it in clean code: names, constants, and a function.
analogRead · if / else · if/else if · const · פונקציהfunction · return · pulseIn · map() · showNumberDec
נתנו לארדואינו חושים — עכשיו ניתן לו שרירים. נוסיף מנוע, ונגרום לדברים לזוז לפי מה שהחיישנים אומרים. הלולאה חש→חושב→פועל סוף־סוף תזיז משהו בעולם. We gave the Arduino senses — now we give it muscles. We add a motor, and make things move based on what the sensors say. The sense→think→act loop will finally move something in the world.
💻 כל קבצי הקוד של השיעור — הורדהAll of this lesson's code — download
עבודה יפה — נתראה בשיעור הבא! 👋Nice work — see you next lesson! 👋