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

הסבר קוד למנורה אולטרהסונית

ערכה: מנורה אולטרהסונית

נעבור על הקוד עבור המנורה:

הגדרת פינים

    
#define relayPin  5
#define trigPin   9
#define echoPin   10
  

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

משתנים עבור ניהול המנורה

    
bool lampIsOn;
  

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

 

משתנים עבור מדידת המרחק

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

    
long duration;
int distance;
  

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

    
int max_dist=30; // cm
int alert_dist=30; // cm

  

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

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

    
bool oneDetectionOnly=true;
int stay_time_ms=30; 
long came_time_ms;

#define DIST_FAR            1
#define DIST_CAME           2
#define DIST_NEAR           3
#define DIST_WENT           4
#define DIST_WAIT_2_LEAVE   5

byte currect_dist_state;
bool long_near=false;

  

נחשב את הזמן המקסימלי שמחכים להחזר

    
float maxLenInMicroSec=max_dist * 2 / 0.034; 

  

ונתחיל את הקוד

הגדרות התחלה

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

    
void setup() {
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT); 
    pinMode(relayPin, OUTPUT);

    killTheLight();
  currect_dist_state=DIST_FAR;
}
  

 

פעילות שוטפת

בדיקה האם יש עצם קרוב

    

byte nearCnt=0;
bool handIsNear(){
  dist_state_handler(); 
  return detect_stay();
}
  

פונקציית LOOP

אם יש עצם קרוב - החלף את מצב המנורה

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

    
void loop() {
  if(handIsNear()){
    toggle_light();
  }
  delay(50);
}
  

זיהוי הישארות

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

    

bool detect_stay(){
  bool ret=false;

  if((currect_dist_state==DIST_NEAR) and (long_near == true)){
    ret = true;
    if(oneDetectionOnly){
      currect_dist_state=DIST_WAIT_2_LEAVE;
      long_near=false;
    }
  }
  return ret;

}
  

ניהול תהליך הגילוי

הגילוי כולו (שמטרתו לתת גילוי אחד על כל מעבר היד) נכתב בשיטה של מכונת מצבים, העוברת בין המצבים הבאים:

מתחילים במצב DIST_FAR כלומר אין גילוי של עצם.

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

בגילוי נוסף, עוברים אל מצב  DIST_NEAR שבו נישאר כל עוד יש גילוי

לאחר שנגמרו הגילויים, נעבור אל DIST_WENT וממנו אל מצב DIST_FAR (אם אין יותר גילויים).

    

void dist_state_handler() {
  byte nextState;

  calc_dist();

  bool detected=((distance==0)||(distance > alert_dist))?false:true;
  switch(currect_dist_state){
    case DIST_FAR:
                  nextState=(detected)?DIST_CAME:DIST_FAR;
                  break;
    case DIST_CAME:
                  nextState=DIST_FAR;
                  if(detected){
                    nextState=DIST_NEAR;
                    came_time_ms=millis();
                  }
                  break;
    case DIST_NEAR:
                  nextState=(detected)?DIST_NEAR:DIST_WENT;
                  break;
    case DIST_WENT:
                  nextState=DIST_FAR;
                  if(detected){
                    nextState=(oneDetectionOnly)?DIST_WAIT_2_LEAVE:DIST_NEAR;
                  }
                  break;
    case DIST_WAIT_2_LEAVE:
                  nextState=(detected)?DIST_WAIT_2_LEAVE:DIST_WENT;
                  break;
  }
  currect_dist_state=nextState;
}
  

פונקציות בסיס של מד מרחק

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

השנייה שולחת את הגל (TRIG) והראשונה מזהה החזר ומחשבת את מרחק העצם

    
void calc_dist(){
  sendTrig();
  duration = pulseIn(echoPin, HIGH,maxLenInMicroSec);
  distance= round(duration*0.034/2); 
}
void sendTrig(){
    // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
}
  

 

פונקציות השליטה במנורה

הדלקה, כיבוי, והחלפת מצב

    
void lightTheLamp(){
    digitalWrite(relayPin, HIGH);
    lampIsOn=true;
}
void killTheLight(){
    digitalWrite(relayPin, LOW);
    lampIsOn=false;
}
void toggle_light(){
  if(lampIsOn){
    killTheLight();
  }
  else {
    lightTheLamp();
  }
}

  

 

קוד להורדה (ino)

 

 

<< איך להרכיב את המנורה

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