ממשיכים להגיע אליכם עד הבית!
משלוח חינם

ערוצי נורות - פתרון התרגיל

ערכה: קורס ארדואינו בסיסי

ראשית נגדיר את הפינים בהם נשתמש

            
                #define pinBtnRed 12 
#define pinBtnGreen 4
#define pinBtnBlue 3
#define pinBtnYellow 2

עבור הכפתורים

            
                #define pinU 6 
#define pinL 9
#define pinD 10
#define pinR 11

עבור הנורות

 

גם בתרגיל זה נגדיר מערכים (עבור הכפתורים ועבור הנורות)

כיוון שאנו רוצים קשר בין הכפתור לבין הנורה (כפתור כחול ידליק נורה כחולה) נקפיד לסדר את הפינים כך שעבור כפתור ונורה בעלי אותו צבע יהיה גם אותו אינדקס במערך

            
                #define NUMBER_OF_CHANNELS 4 
int Btns[NUMBER_OF_CHANNELS]={pinBtnRed,pinBtnGreen,pinBtnBlue,pinBtnYellow};
int Leds[NUMBER_OF_CHANNELS]={pinR,pinL,pinU,pinD};
כמו כן, נרצה משתנה שיחזיק את מצב הנורה (כדי שנוכל לשנות את המצב) ומשתנה שיכיל את מצב הכפתור (כדי שנשנה את מצב הנורה רק פעם אחת בכל לחיצה של הכפתור)

כמובן שמשתנים אלה הם עבור כל סט של כפתור-נורה ולכן גם עבורם נגדיר מערך

            
                bool LedIsOn[NUMBER_OF_CHANNELS]={false,false,false,false}; 
bool BtnIsPressed[NUMBER_OF_CHANNELS]={false,false,false,false};

בפונקציית האתחול setup נגדיר את מוד העבודה של הפינים. כמובן שנשתמש בלולאה לשם כך

            
                void setup() { 
   for(byte k=0;k<NUMBER_OF_CHANNELS;k++){
     pinMode(Btns[k],INPUT_PULLUP);
     pinMode(Leds[k],OUTPUT);
   }
}

השליטה על הנורה

כדי לשלוט על הנורה אנו זקוקים לפונקציה שתדליק את הנורה, ולפונקציה שתכבה

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

הפונקציה גם צריכה לשמור את מצב הנורה במשתנה המתאים, כדי שנוכל להשתמש בו כשנרצה להחליף את מצב הנורה

ולכן פונקציית ההדלקה תהיה

            
                void LedOn(byte channel){ 
  digitalWrite(Leds[channel],HIGH);
  LedIsOn[channel]=true;
}

ופונקציית הכיבוי

            
                void LedOff(byte channel){ 
  digitalWrite(Leds[channel],LOW);
  LedIsOn[channel]=false;
}

פונקציית ההחלפה תפעיל את הפונקציה המתאימה מבין השתיים, בהתבסס על מצב הנורה

            
                void toggleLed(byte channel){ 
  if(LedIsOn[channel]){
    LedOff(channel);
  } else {
    LedOn(channel);
  }
}

זיהוי לחיצה בודדת

כאשר לוחצים על כפתור, הערך שלו יהיה נמוך, כלומר התנאי

            
            	if(digitalRead(Btns[channel])==LOW){
            
        

יתקיים כאשר הכפתור לחוץ

אבל

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

אנו צריכים להבטיח שכל לחיצה תשפיע רק פעם אחת

לשם כך אנו זוכרים את המצב של הכפתור

כאשר הכפתור משוחרר (כלומר ה-else של התנאי הקודם), אנו יכולים להגדיר את המשתנה אל false

                
                    else { 
   BtnIsPressed[channel]=false;
}

ואז כשאנחנו מזהים לחיצה על הכפתור, אנו יודעים שהיא חדשה רק אם מצב הכפתור הידוע לנו הוא לא לחוץ (כלומר יש שינוי במצב הכפתור)

במצב כזה, של לחיצה חדשה, נשנה את מצב הנורה, וכמובן נעדכן את מצב הכפתור

            
                if(digitalRead(Btns[channel])==LOW){ 
   if(! BtnIsPressed[channel]){
     BtnIsPressed[channel]=true;
     toggleLed(channel);
   }
}

כמובן שאת הקוד הזה אנחנו מריצים בתוך לולאה הסורקת את כל הכפתורים

debouncing

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

לכן נוסיף

            
              delay(20);
            
        

בפונקציית loop

זו השהיה מספיק קטנה כדי שלא תשפיע על זיהוי הלחיצה על הכפתור, ומספיק ארוכה כדי להתעלם מתופעת ה-bouncing, כך שנצליח לספור רק פעם אחת כל לחיצה על הכפתור

 

 

 

כל הפונקציה תהיה

            
                void loop() { 
  for(byte channel=0;channel<NUMBER_OF_CHANNELS;channel++){
    if(digitalRead(Btns[channel])==LOW){
      if(! BtnIsPressed[channel]){
        BtnIsPressed[channel]=true;
        toggleLed(channel);
      }
    } else {
      BtnIsPressed[channel]=false;
    }
  }
  delay(20);
}

 

 

והנה הקוד להורדה

<< ערוצי נורות - תיאור התרגיל ערוצי נורות - תיאור התרגיל >>

תגובות גולשים