מה נלמד כאן
- לשלב כמה מערכות בקרה בפרויקט אחד
- זיהוי קצה יורד בלחצן
- לבנות מאוורר מסתובב עם דרגות
המאוורר המלא
זה הפרויקט המורכב ביותר בקורס: מאוורר שמסתובב מצד לצד, עם שלוש דרגות מהירות, ושליטה בלחצן.

כל מה שלמדתם נפגש כאן: PWM לבקרת מהירות, סרוו לתנועת הסיבוב, לחצנים עם טיפול בריטוט, וניהול מצב.
הידע שצריך
שילוב מערכות

למאוורר יש שתי מערכות עצמאיות שרצות במקביל:
| המערכת | מה היא עושה | מה מפעיל אותה |
|---|---|---|
| הנעה | מסובבת את הלהב | מנוע DC ב-PWM |
| סיבוב | מניעה את הראש ימינה ושמאלה | סרוו בלולאה |
והאתגר האמיתי: שתיהן צריכות לרוץ בו-זמנית. אם התוכנית "תיתקע" בלולאת הסרוו, היא לא תשמע לחיצות על הכפתור.
זיהוי קצה יורד
if (buttonState == LOW && lastButtonState == HIGH) {
// הכפתור *הרגע* נלחץ
}
עד עכשיו בדקנו "האם הכפתור לחוץ". כאן בודקים משהו מדויק יותר: "האם הכפתור השתנה ממצב משוחרר ללחוץ ברגע זה".
זה נקרא זיהוי קצה יורד (falling edge), והוא עובד על ידי שמירת המצב הקודם והשוואה אליו.
למה זה עדיף על while שממתין לשחרור? כי while עוצר את כל התוכנית — והסרוו היה קופא באמצע התנועה. זיהוי קצה לא עוצר כלום.
זו קפיצת מדרגה אמיתית בתכנות. מעבר מ"תוכנית שמחכה" ל"תוכנית שמנטרת". בפרויקטים גדולים זה ההבדל בין מערכת שמגיבה למערכת שנתקעת.
ההרכבה
בלי ערכת הבנייה — דלגו לקוד.
שלבי ההרכבה:















































הניסוי
המטרה: לחצן מפעיל ומכבה ומחליף דרגות; הסרוו מסובב את המאוורר.
רשימת רכיבים
| הרכיב | כמות |
|---|---|
| לוח ESP32 | 1 |
| דרייבר מנועים | 1 |
| מנוע DC + מאוורר | 1 |
| סרוו | 1 |
| לחצנים | 3 |
מבנה התוכנית
#include <ESP32Servo.h>
Servo myServo;
#define servoPin 5
#define motor1A 16
#define motor2A 17
int angle = 90, step = 1;
int minAngle = 30, maxAngle = 150;
bool isPaused = false;
bool lastButtonState = HIGH;
void setup() {
myServo.attach(servoPin, 500, 2400);
myServo.write(90);
pinMode(motor1A, OUTPUT);
pinMode(motor2A, OUTPUT);
pinMode(23, INPUT_PULLUP); // לחצן עצירת סיבוב
pinMode(18, INPUT); // לחצני מהירות
pinMode(19, INPUT);
Serial.begin(115200);
analogWrite(motor1A, 0);
analogWrite(motor2A, 0);
}
// מטפלת בתנועת הסרוו — נקראת בכל סיבוב, לא חוסמת
void Servomove() {
int buttonState = digitalRead(23);
// זיהוי קצה יורד — הכפתור הרגע נלחץ
if (buttonState == LOW && lastButtonState == HIGH) {
delay(50); // ריטוט
if (digitalRead(23) == LOW) { // אימות
isPaused = !isPaused; // עצירה/המשך
}
}
lastButtonState = buttonState;
if (!isPaused) {
myServo.write(angle);
delay(15);
angle += step;
if (angle >= maxAngle || angle <= minAngle) {
step = -step; // היפוך כיוון בקצה
}
}
}
void loop() {
Servomove(); // צעד אחד של הסרוו
// כאן קוראים את לחצני המהירות ומעדכנים PWM
}
שלושה רעיונות בקוד
1. Servomove() מבצעת צעד אחד, לא תנועה שלמה. היא נקראת בכל סיבוב של loop, מזיזה את הסרוו מעלה אחת, ויוצאת. ככה התוכנית אף פעם לא "תקועה".
2. step = -step — כשהסרוו מגיע לקצה, הצעד מחליף סימן והתנועה מתהפכת. שורה אחת שיוצרת תנועת הלוך ושוב אינסופית.
3. INPUT_PULLUP — שימו לב: כאן משתמשים בנגד Pull-Up פנימי של ה-ESP32, במקום נגד חיצוני כמו בשיעור 4. פחות חוטים, אותה תוצאה.
נסו בעצמכם
- שנו את
minAngleו-maxAngle. מה טווח הסיבוב הנוח? - שנו את
delay(15)בתוךServomove. מה קורה לחלקות התנועה? - החליפו את זיהוי הקצה ב-
whileשממתין לשחרור והריצו. מה קורה לסרוו? - הוסיפו דרגת מהירות רביעית.
- הוסיפו תצוגת LCD עם הדרגה הנוכחית ומצב הסיבוב.


