K145 ανίχνευση κίνησης με τον HC-SR501

Σε αυτό το πρότζεκτ θα σας δείξω πως μπορείτε να ανιχνεύσετε κίνηση θερμού σώματος χρησιμοποιώντας τις ιδιότητες της υπέρυθρης ακτινοβολίας. Η κατασκευή αυτή μπορεί να χρησιμοποιηθεί σαν ένα απλό σύστημα συναγερμού που με την βοήθεια κάποιου μικροελεγκτή, σαν τον μικροελεγκτή Arduino, βασισμένο στην αναπτυξιακή πλακέτα με τον Arduino Nano, που έχουμε παρουσιάσει σε άλλο μέρος αυτού του ισοτόπου.

Η βασική ιδέας της κατασκευής στηρίζεται στην χρήση του module HC-SR501 σαν αισθητήρας υπέρυθρης ακτινοβολίας, ο οποίος δομείται από ένα μικρό pcb με ένα ειδικό ολοκληρωμένο κύκλωμα πάνω του με μερικά άλλα εξαρτήματα και αυτό είναι ότι χρειάζεται για πλήρη λειτουργία ανίχνευσης κίνησης με απλή έξοδο με δυο καταστάσεις HIGH και LOW.

To HC-SR501 ανιχνεύει κίνηση βασιζόμενο στην υπέρυθρη ακτινοβολία που εκπέμπουν τα σώματα καθώς κινούνται από μπροστά του.  Ο PIR αισθητήρας είναι σχεδιασμένος έτσι ώστε να αναγνωρίζει την υπέρυθρη ακτινοβολία του ανθρώπου και των ζώων που περνούν μπροστά του και την ξεχωρίζει από εκείνη που εκπέμπει το περιβάλλον.

Παρακάτω θα διασυνδέσουμε τον υπέρυθρο αισθητήρα με την αναπτυξιακή πλακέτα που έχουμε παρουσιάσει σε άλλο μέρος. Ο κώδικας είναι απλός και δεν έχει καμία ιδιαιτερότητα και αυτό οφείλεται στο γεγονός ότι ο αισθητήρας έχει μια και μοναδική ψηφιακή έξοδο που παίρνει μια από τις δυο καταστάσεις HIGH  ή  LOW ανάλογα αν ανιχνεύεται κίνηση από μπροστά του.

Μπορείς να συνδέσεις την ψηφιακή έξοδο του HC-SR501 σε ένα από τα I/O ψηφιακά πινς του Arduino. Στην κατασκευή μας το συνδέουμε με το πιν  8 του Arduino. Έπειτα συνδέουμε τα πινς Vcc και GND του αισθητήρα με τα 5V και GND της αναπτυξιακής πλακέτας αντίστοιχα.

Για να δουλέψει ο κώδικας σωστά είναι καλύτερο να θέσεις τον βραχυκυκλωτήρα trigger mode σε ‘Η’ (Repeat trigger mode). Επίσης ρυθμίζουμε το χρόνο καθυστέρησης με το ποτενσιόμετρο στη χαμηλότερη τιμή (γύρισε το τέρμα αριστερόστροφα).

Ο κώδικας διαβάζει την κατάσταση του αισθητήρα HC-SR501 και εμφανίζει πάνω στην οθόνη LCD το αντίστοιχο μήνυμα και συγκεκριμένα το «Motion detected!» ή «Motion ended!»

Ο κώδικας για τούτο το παράδειγμα είναι ο ακόλουθος:

// Παράδειγμα κώδικα για τον υπέρυθρο αισθητήρα HC-SR501
//Συμπερίληψη βιβλιοθήκης για το LCD
#include <LiquidCrystal.h> 
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Δημιουργία αντικειμένου lcd
// Δηλωση πιν επικοινωνίας:
#define pirPin 8
// Δημιουργία μεταβλητών:
int val = 0;
bool motionState = false; // Ξεκινάμε με μη ανίχνευση κίνησης
void setup() {
  // Διαμόρφωση πινς σαν είσοδος ή έξοδος:
   pinMode(pirPin, INPUT);
  // Αρχικοποίηση του LCD σαν 16 στήλες και 2 γραμμές:
  lcd.begin(16, 2);
}
void loop() {
  // Διάβασμα του πιν pirPin και εκχώρηση στη μεταβλητή val:
  val = digitalRead(pirPin);
  // Εάν ανιχνευτεί κίνηση (pirPin = HIGH), κάνε τα ακόλουθα:
  if (val == HIGH) {
     // Άλλαξε την κατάσταση κίνησης σε true (motion detected):
    if (motionState == false) {
      lcd.setCursor(0, 0);
      lcd.print("Motion detected!");
      motionState = true;
    }
  }
  // Εάν δεν ανιχνευτεί κίνηση (pirPin = LOW), κάνε τα ακόλουθα:
  else {
     // Άλλαξε την κατάσταση κίνησης σε false (no motion):
    if (motionState == true) {
      lcd.setCursor(0, 0);
      lcd.print("Motion ended!   ");
      motionState = false;
    }
  }
}

Επεξήγηση του κώδικα

Ο κώδικας είναι πολύ απλός και μπορείς εύκολα να τον κατανοήσεις. Αυτό φαίνεται και από το γεγονός ότι δεν συμπεριλαμβάνει βιβλιοθήκη παρά μόνο αυτή για την λειτουργία της οθόνης LCD την οποία γνωρίζουμε να την χρησιμοποιούμε από άλλες εφαρμογές αυτού του ιστοτόπου.

Στην αρχή του κώδικα δηλώνουμε με την έκφραση #define pirPin 8 το ψηφιακό πιν πάνω στο Arduino που είναι συνδεμένος ο αισθητήρας. Με την έκφραση #define δίνουμε ένα όνομα σε μια σταθερή τιμή. Έτσι κάθε φορά που γίνεται αναφορά στη σταθερά pirPin ο compiler θα την αντικαταστήσει με την τιμή 8 καθώς ο κώδικας μεταγλωττίζεται

Επίσης ορίζουμε δυο μεταβλητές val και motionState που δηλώνονται σαν int και bool  αντίστοιχα. Η μεταβλητή val χρησιμοποιείται για να αποθηκεύσει την έξοδο του αισθητήρα και η motionState παίρνει την τιμή true εάν ανιχνεύει κίνηση και false όταν δεν υπάρχει κίνηση στο χώρο.

//Συμπερίληψη βιβλιοθήκης για το LCD
#include <LiquidCrystal.h> 
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Δημιουργία αντικειμένου lcd
// Δήλωση πιν επικοινωνίας:
#define pirPin 8
// Δημιουργία μεταβλητών:
int val = 0;
bool motionState = false; // Ξεκινάμε με μη ανίχνευση κίνησης

Στην συνάρτηση setup() θέτουμε το πιν pirPin σαν input με την χρήση της εντολής pinMode(pin, mode);. Επίσης αρχικοποιούμε την μονάδα απεικόνισης LCD με 16 στήλες και 2 γραμμές.

void setup() {
  // Διαμόρφωση πινς σαν είσοδος ή έξοδος:
   pinMode(pirPin, INPUT);
  // Αρχικοποίηση του LCD σαν 16 στήλες και 2 γραμμές:
  lcd.begin(16, 2);
}

Μέσα στη συνάρτηση επανάληψης loop() πρώτα διαβάζουμε την έξοδο του αισθητήρα digitalRead(pin); η οποία επιστρέφει HIGH ή LOW. Εάν ανιχνευθεί κίνηση εμφανίζεται το μήνυμα «Motion detected!» στην οθόνη LCD ενώ όταν δεν έχουμε κίνηση εμφανίζεται το μήνυμα «Motion endend!»

Δημιουργία ενός συστήματος συναγερμού με τον αισθητήρα PIR και ενός βομβητή

Με λίγες αλλαγές στον κώδικα μπορούμε να δημιουργήσουμε ένα σύστημα συναγερμού καθώς και με τη βοήθεια ενός βομβητή (buzzer). Για πιο ωραίο ήχο συνδέουμε σε σειρά με τον βομβητή μια αντίσταση 100Ω ή μπορείτε να πειραματιστείτε με την τιμή της.

Ο κώδικας γι’ αυτή την εφαρμογή είναι ο ακόλουθος που διαφέρει ελάχιστα από το προηγούμενο παράδειγμα κώδικα. Μπορείς να πειραματιστείς με τον ήχο του βομβητή αλλάζοντας τις παραμέτρους στη συνάρτηση alarm(duration, frequency);

/* Παράδειγμα κώδικα για την δημιουργία συστήματος συναγερμού*/
#include <LiquidCrystal.h> 
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Δημιουργία αντικειμένου lcd

// Δήλωση αντιστοίχησης ακροδεκτών:
#define buzzerPin 9
#define pirPin 8

// Δημιουργία μεταβλητών:
int val = 0;
bool motionState = false; // Αρχή σαν μην ανίχνευση κίνησης.

void setup() {
  // Διαμόρφωση πιν σαν input or output:
  pinMode(buzzerPin, OUTPUT);
  pinMode(pirPin, INPUT);

  // Αρχικοποίηση αντικειμένου της οθόνης lcd:
  lcd.begin(16, 2);
}

void loop() {
  // Διάβασμα του pirPin και αποθήκευση του στη val:
  val = digitalRead(pirPin);

  // Εάν ανιχνευθεί κίνηση (pirPin = HIGH), κάνε τα ακόλουθα:
  if (val == HIGH) {
     alarm(500, 1000);  // Κάλεσε την συνάρτηση alarm(duration, frequency).
    delay(150);

    // Άλλαξε την κατάσταση κίνησης σε true (motion detected):
    if (motionState == false) {
      lcd.setCursor(0, 0);
      lcd.print("Motion detected!");
      motionState = true;
    }
  }

  // Εάν δεν ανιχνευχθεί κίνηση (pirPin = LOW), κάνε τα ακόλουθα:
  else {
    noTone(buzzerPin); // Βεβαιώσου ότι δεν ηχεί ο βομβητής όταν δεν ανιχεύεται κίνηση.
    delay(150);

    // Άλλαξε την κατάσταση κίνησης σε false (no motion):
    if (motionState == true) {
      lcd.setCursor(0, 0);
      lcd.print("Motion ended!  ");
      motionState = false;
    }
  }
}

// Function to create a tone with parameters duration and frequency:
void alarm(long duration, int freq) {
  tone(buzzerPin, freq);
  delay(duration);
  noTone(buzzerPin);
}

Σημεία που πρέπει να λάβεις υπόψη για να σχεδιάζεις PIR εφαρμογές

Όπως στους περισσότερους PIR υπέρυθρους αισθητήρες, ο HC-SR501 χρειάζεται κάποιο χρόνο για να επεξεργαστεί την υπέρυθρη ακτινοβολία που δέχεται από το χώρο. Αυτό παίρνει χρόνο από 30 έως 60 δευτερόλεπτα μετά που ο αισθητήρας τροφοδοτηθεί με τάση.

Επιπρόσθετα, ο αισθητήρας έχει ένα χρονικό διάστημα αδράνειας μετά από μια ανάγνωση, που σε αυτό το χρονικό διάστημα αδυνατεί να ανιχνεύσει κίνηση.

Όταν σχεδιάζεις μια εφαρμογή βασισμένη στον υπέρυθρο αισθητήρα HC-SR501, πρέπει να λάβεις υπόψη  όλες αυτές τις καθυστερήσεις.