Σκοπός Συλλογή & Επεξεργασία Δεδομένων Εξαμηνιαία 2015 ΡομποΚαθαριστής Μέρος Β : Το Πρόγραμμα. Σχεδίαση Συστήματος Πραγματικής Εφαρμογής (Prototyping). Μονάδες ενός Ρομποτικού Συστήματος Μονάδα Συλλογής Δεδομένων, Μονάδα Επεξεργασίας & Μηχανικό Σύστημα. Η Λειτουργία του Μικροελεγκτή, σ ένα Ρομποτικό Σύστημα. Σύστημα Οδήγησης Κινητήρα (Motor Control Unit). Η Έννοια της Πλακέτας Πρόσθετης Λειτουργίας (Shield) Πλακέτα Οδήγησης Κινητήρα (Motor Control Shield) Αισθητήρας Υπέρηχων () Δομές προγραμματισμού. 1
ΕΞ.1 ΕΠΙΔΙΩΞΗ ΤΟΥ Β ΜΕΡΟΥΣ Στο Α Μέρος της εργασίας, είδαμε τις βασικές μονάδες ενός χαρακτηριστικού ρομποτικού συστήματος, της ρομποτικής σκούπας, τους αισθητήρες, το σασί, το μικροελεγκτή και το μηχανικό σύστημα, από τους κινητήρες και τη πλακέτα οδήγησης των κινητήρων (motor control shield) και πως από αυτές τις μονάδες, εύκολα, μπορούμε να δημιουργήσουμε όλο το σύστημα. Αν σ αυτό το σύστημα, ο μικροελεγκτής είναι το μυαλό, το πρόγραμμα είναι η συνείδηση του συστήματος, αυτή δηλαδή η μονάδα που επιτρέπει στο σύστημα να αντιλαμβάνεται το εξωτερικό περιβάλλον και να παράγει διάφορες δράσεις (initiates action), σ αυτό (Εικόνα ). Για παράδειγμα, το πρόγραμμα για τη ρομποτική σκούπα, είναι αυτό που τακτικά, θα παίρνει τη μέτρηση από τον αισθητήρα υπέρηχων, για να υπολογίζει την απόσταση αντικειμένων ή εμποδίων, μπροστά από τη σκούπα, ώστε ανάλογα, να ρυθμίζει τη κίνησή της σκούπας, κινώντας την εμπρός, αν δεν υπάρχουν εμπόδια σε κοντινή α- πόσταση, σ αυτή τη κατεύθυνση ή αντίθετα, στρίβοντάς την αριστερά ή δεξιά, αν υπάρχουν εμπόδια σε κοντινή απόσταση, μπροστά από τη σκούπα. Σ αυτή την ενότητα, αναλυτικότερα, εξετάζουμε τη μορφή αυτού του προγράμματος. Στις εργαστηριακές ασκήσεις, είδαμε τα επιμέρους τμήματα αυτού του προγράμματος. Είδαμε δηλαδή το πρόγραμμα για να διαβάζει τη μέτρηση απόστασης από έναν αισθητήρα υπέρηχων και το πρόγραμμα, για να λειτουργεί / περιστρέφει έναν DC κινητήρα, μπροστά ή πίσω. Όπως στο Α Μέρος, είδαμε πως συνδυάζουμε επιμέρους μονάδες, όπως αισθητήρες, κινητήρες και μικροελεγκτές, σ ένα σύνθετο σύστημα, ανάλογα, σ αυτή την ενότητα, ο σκοπός είναι να δούμε πως μπορούμε να συνδυάζουμε σχετικά απλά, επιμέρους προγράμματα, για να δημιουργούμε ένα πολύ συνθετότερο πρόγραμμα που να ρυθμίζει τη λειτουργία ενός σύνθετου συστήματος (Εικόνα ). ΕΞ.2 Οι Βασικές Λειτουργίες του Προγράμματος Η βασική λειτουργία του προγράμματος για τη ρομποτική σκούπα, είναι να περιστρέφει του κινητήρες που δίνουν κίνηση στους τροχούς της σκούπας, επιτρέποντας στη σκούπα να κινείται αυτόνομα, στο χώρο που θα καθαρίσει. Όμως, αυτή είναι η μία μόνον από τις βασικές λειτουργίες αυτού του προγράμματος. Η άλλη βασική λειτουργία του προγράμματος είναι να εντοπίζει τα αντικείμενα ή εμπόδια, όπως έπιπλα και τοίχους, στο χώρο που θα καθαρίσει. Γιατί, κατά κανόνα, η ρομποτική σκούπα, όπως και μία χειροκίνητη ηλεκτρική σκούπα, δεν θα χρησιμοποιείται, για να καθαρίζει άδειους χώρους, αλλά κατά κανόνα, χώρους που θα περιέχουν πολλά αντικείμενα. Ακόμα και ένας τελείως άδειος χώρος θα περιβάλλεται από εσωτερικούς τοίχους που η σκούπα, θα πρέπει να εντοπίζει και ό- 2
ταν φτάνει κοντά σ ένα αντικείμενο ή τοίχο, να μην πέφτει τυφλά, επάνω σ αυτό, αλλά να αλλάζει τη κατεύθυνση της κίνησης της, αριστερά ή δεξιά, απ αυτό το αντικείμενο. Εκτός από τη λειτουργία των κινητήρων, η άλλη βασική λειτουργία του προγράμματος της ρομποτικής σκούπας, είναι να μπορεί να αποφεύγει όλα τα εμπόδια που συναντάει στο χώρο που καθαρίζει. Ο τρόπος που επιλέξαμε ώστε η ρομποτική σκούπα να μπορεί να εντοπίζει τα διάφορα φυσικά εμπόδια, στο χώρο που καθαρίζει, είναι ο αισθητήρας υπέρηχων που μετράει την απόσταση αντικειμένων, μπροστά από τη ρομποτική σκούπα. Καθώς το πρόγραμμα λειτουργεί / περιστρέφει τους κινητήρες της σκούπας, οδηγώντας την να σκουπίζει σε μία κατεύθυνση, ταυτόχρονα, θα πρέπει σε τακτικά χρονικά διαστήματα, να παίρνει τη μέτρηση από τον αισθητήρα υπέρηχων και να χρησιμοποιεί αυτή τη μέτρηση, για να εντοπίζει αν υπάρχουν εμπόδια σε κοντινή απόσταση από τη σκούπα. Αν δεν υπάρχουν, τότε απλά, το πρόγραμμα θα εξακολουθήσει να κινεί τη σκούπα, στην ίδια κατεύθυνση. Αν όμως, υπάρχει ένα κοντινό εμπόδιο, εμπρός από τη σκούπα, τότε το πρόγραμμα θα πρέπει να στρίψει τη σκούπα αριστερά ή δεξιά. Ξεκινάμε να γράφουμε το πρόγραμμα, για τη ρομποτική σκούπα, από το μέρος του προγράμματος που διαβάζει τον αισθητήρα υπέρηχων. ΕΞ.3 Το Πρόγραμμα για να Διαβάζει τη Μέτρηση από τον Αισθητήρα Υπέρηχων Είδαμε το πρόγραμμα για τον αισθητήρα υπέρηχων στην Εργαστηριακή Άσκηση, όπου εξετάσαμε τον αισθητήρα υπέρηχων. Μπορούμε να χρησιμοποιήσουμε το ίδιο πρόγραμμα (Εικόνα ), για να μετράμε την απόσταση αντικειμένων, μπροστά από τη ρομποτική σκούπα. Η βασική λειτουργία του προγράμματος, είναι να εκπέμπει ένα ηχητικό σήμα, από το μεγάφωνο του αισθητήρα υπέρηχων, δημιουργώντας ένα πολύ σύντομε τετραγωνικό παλμό, στη θύρα 7 του Arduino, όπου έχουμε συνδέσει τον ακροδέκτη TRIG του αισθητήρα. Το πρόγραμμα μετράει το χρόνο που η αντανάκλαση αυτού του σήματος, στα διάφορα αντικείμενα μπροστά από τη σκούπα, κάνει να επιστρέψει στο μικρόφωνο του αισθητήρα υπέρηχων που παίρνουμε, από τον ακροδέκτη ECHO του αισθητήρα. Στη βάση αυτού του χρόνου και της ταχύτητας του ήχου στον αέρα, υπολογίζουμε την απόσταση αντικειμένων, μπροστά από τη σκούπα (Εικόνα ). Έχοντας την απόσταση αντικειμένων μπροστά από τη σκούπα, το πρόγραμμα μπορεί να αποφασίζει για τη κατεύθυνση της κίνησης της σκούπας, αν θα εξακολουθήσει να κινεί τη σκούπα στην ίδια κατεύθυνση ή αν θα στρίψει τη σκούπα, αριστερά ή δεξιά. Πριν δούμε πως το πρόγραμμα αποφασίζει, για τη κατεύθυνση της κίνησης τη σκούπας, χρειάζεται να δούμε καθεμία από αυτές τις λειτουργίες, δηλαδή: 3
Εικόνα 11: Η γενική μορφή του προγράμματος, για τη λήψη και την επεξεργασία των μετρήσεων απόστασης αντικειμένων, από τη ρομποτική σκούπα. 4
Τη κίνηση της σκούπας προς τα εμπρός, λειτουργώντας ταυτόχρονα τους δύο κινητήρες Τη στροφή της σκούπας δεξιά ή αριστερά. ΕΞ.4 Το Μηχανικό Σύστημα Η Πλακέτα Οδήγησης των Κινητήρων Είδαμε στην Άσκηση πως για να μπορούμε να περιστρέφουμε έναν DC κινητήρα και στις δύο φορές την ορθή ή την ανάστροφη φορά, χρειάζεται να χρησιμοποιήσουμε το ολοκληρωμένο της γέφυρας. Μέσα από το ολοκληρωμένο της γέφυρας, μπορούμε να ρυθμίζουμε τη φορά, αλλά και τη ταχύτητα περιστροφής των κινητήρων, από το πρόγραμμα. Ένας λίγο διαφορετικός τρόπος να οδηγούμε κινητήρες, από το πρόγραμμα, είναι η πλακέτα οδήγησης κινητήρων, η motor shield. H motor shield είναι μία πλακέτα που περιέχει το ολοκληρωμένο της γέφυρας και άλλα ολοκληρωμένα σε μία πλακέτα που μπορούμε να συνδέουμε / να βυσματώνουμε στον Arduino, κάνοντας την σάντουιτς με τον Arduino (Εικόνα ). Αυτός ο τρόπος εφαρμογής της πλακέτας στον Arduino, μας επιτρέπει να συνδέουμε το σύστημα / κύκλωμα οδήγησης των κινητήρων στο μικροελεγκτή, εύκολα, χωρίς να χρησιμοποιούμε καλώδια. Απλά, συνδέουμε τη πλακέτα στον Arduino, κάνοντάς την σάντουιτς με τον Arduino και συνδέουμε τους κινητήρες τους ακροδέκτες κάθε κινητήρα, στις υποδοχές, για κάθε κινητήρα, στη πλακέτα. Στη πλακέτα, υπάρχουν τέσσερα ζεύγη υποδοχών, για τέσσερεις DC κινητήρες, όμως, θα χρησιμοποιήσουμε δύο ζεύγη υποδοχών, έστω τις Μ1 και Μ2, για να συνδέουμε τους δύο κινητήρες της σκούπας (Εικόνα ). Η επικοινωνία της πλακέτας με τον Arduino, γίνεται, χρησιμοποιώντας τον I2C δίαυλο. Η επικοινωνία δηλαδή της πλακέτας με τον Arduino, γίνεται, χρησιμοποιώντας μόνον δύο θύρες του Arduino, τις SDL και SCL (Εικόνα ). Αφού χρησιμοποιούμε αυτές τις θύρες, για την λειτουργία των DC κινητήρων, μέσα από τη motor shield, μπορούμε να χρησιμοποιήσουμε οποιεσδήποτε από τις ψηφιακές θύρες του Arduino, έστω τις θύρες 7 και 6, για να συνδέσουμε σ αυτές τις θύρες, τους ακροδέκτες Trig και Echo του αισθητήρα υπέρηχων. Δεν έχει τόσο σημασία σε ποια από τις δύο υποδοχές, ενός ζεύγους υποδοχών της πλακέτας, θα συνδέσουμε το κόκκινο και σε ποια το μαύρο καλώδιο ενός κινητήρα. Ο τρόπος που κάνουμε αυτή τη σύνδεση, καθορίζει τη φορά περιστροφής του κινητήρα. Αν δούμε ότι ο κινητήρας περιστρέφεται αντίθετα από τη φορά που ορίζουμε, μέσα από το πρόγραμμα, απλά, αλλάζουμε / αντιστρέφουμε τη σύνδεση των δύο καλωδίων, στις αντίστοιχες υποδοχές. 5
ΕΞ.5 Ελέγχοντας τη Ταχύτητα και τη Φορά Περιστροφής ενός Κινητήρα Για να λειτουργήσουμε τους κινητήρες, μέσα από τη motor shield, χρειάζεται πρώτα να εγκαταστήσουμε τη βιβλιοθήκη συναρτήσεων της motor shield και μετά, να χρησιμοποιούμε συναρτήσεις αυτής της βιβλιοθήκης, για να ρυθμίζουμε τόσο τη φορά, όσο και τη ταχύτητα περιστροφής κάθε κινητήρα. Έτσι, αφού κατεβάσουμε και εγκαταστήσουμε τις βιβλιοθήκες της motor shield, δηλαδή, την Adafruit_Motorshield, μετά, περιλαμβάνουμε στο πρόγραμμα, τις συναρτήσεις αυτής της βιβλιοθήκης, χρησιμοποιώντας, στην αρχή του προγράμματος, τις εντολές: #include <Wire.h> #include <Adafruit_MotorShield.h> #include "utility/adafruit_pwmservodriver.h" Μετά, στο πρόγραμμα, δημιουργούμε ένα αντικείμενο το αντικείμενο είναι ένα παράδειγμα της κλάσης, για τη motor shield: Adafruit_MotorShield AFMS = Adafruit_MotorShield(); Δημιουργούμε ακόμα, ένα αντικείμενο, για κάθε κινητήρα της σκούπας: Adafruit_DCMotor *Motor_A = AFMS.getMotor(1); Adafruit_DCMotor *Motor_B = AFMS.getMotor(2); όπου οι αριθμοί 1 και 2 στη συνάρτηση getmotor(), δηλώνουν τις υποδοχές που έχουμε συνδέσει τους δύο κινητήρες. Αν δηλαδή, έχουμε συνδέσει τους δύο κινητήρες στις υποδοχές Μ1 και Μ2, τότε στη συνάρτηση getmotor(), για κάθε κινητήρα, χρησιμοποιούμε τιμές 1 και 2, αντίστοιχα. Στη setup(), ξεκινάμε τη επικοινωνία μικροελεγκτή motor shield, με την εντολή: AFMS.begin(); Ρυθμίζουμε τη ταχύτητα περιστροφής κάθε κινητήρα με τη συνάρτηση setspeed(ταχύτητα), όπου η παράμετρος ταχύτητα μπορεί να παίρνει τιμές από 0 (για να σταματάμε το κινητήρα) μέχρι 255 (μέγιστη ταχύτητα περιστροφής). Για παράδειγμα, η κλήση: Motor_Α->setSpeed(100); ρυθμίζει τη ταχύτητα περιστροφής του κινητήρα Α, στη τιμή 100 που είναι μία μεσαία ταχύτητα περιστροφής. 6
Για περιστρέφουμε κάθε κινητήρα, καλούμε τη συνάρτηση run(direction), όπου η παράμετρος direction μπορεί να έχει μία από τις τιμές FORWARD, BACKWARD ή RELEASE. Για παράδειγμα, η κλήση: Motor_A->run(FORWARD); περιστρέφει το κινητήρα Α στην ορθή φορά. Όλο το πρόγραμμα, για τη λειτουργία των κινητήρων, παριστάνεται στη παρακάτω Εικόνα: #include <Wire.h> #include <Adafruit_MotorShield.h> #include "utility/adafruit_pwmservodriver.h" Adafruit_MotorShield AFMS = Adafruit_MotorShield(); Adafruit_DCMotor *Motor_A = AFMS.getMotor(1); Adafruit_DCMotor *Motor_B = AFMS.getMotor(2); void setup() AFMS.begin(); void loop() delay(50); if ( distance > 50 distance == 0) //κινούμε τη σκούπα, μπροστά, στην ορθή φορά forward(150); else if (distance < 50) //Στρίβουμε τη σκούπα δεξιά turnright(100); delay(500); void drivemotor (byte motor, byte dir, byte spd) if (motor == MOTOR_A) Motor_A->run(dir); 7
Motor_Α->setSpeed(spd); else if (motor == MOTOR_B) Motor_B->run(dir); Motor_B->setSpeed(spd); void forward(byte spd) // Περιστρέφει τους δύο κινητήρες με ταχύτητα 'spd' drivemotor (MOTOR_A, FORWARD, spd); //Motor A με ταχύτητα spd drivemotor (MOTOR_B, FORWARD, spd); //Motor B με ταχύτητα spd void turnright(byte spd) //Motor B stop //Motor A run void stopmotor(byte motor) 8