Ultrasonic Sensor HC-SR04 and Arduino
Σε αυτό το άρθρο θα δούμε πώς λειτουργεί ο αισθητήρας υπερήχων HC-SR04 και πώς να τον χρησιμοποιήσουμε με το Arduino. Αυτός είναι ο πιο δημοφιλής αισθητήρας για μέτρηση απόστασης. Μπορούμε να τον χρησιμοποιήσουμε στη δημιουργία ρομπότ αποφυγής εμποδίων με το Arduino, και αυτό περίπου θα κάνουμε στη συνέχεια.
Περιγραφή του υλικού HC-SR04
Ο HC-SR04 είναι ένας προσιτός στην τιμή και εύκολος στη χρήση αισθητήρας μέτρησης απόστασης. Έχει εύρος από 2 cm έως 400 cm.
Ο αισθητήρας αποτελείται από δύο μετατροπείς υπερήχων. Ο ένας είναι πομπός που εκπέμπει υπερηχητικούς παλμούς ήχου και ο άλλος είναι δέκτης που ακούει τα ανακλώμενα κύματα. Είναι βασικά ένα SONAR σαν αυτά που χρησιμοποιούν τα υποβρύχια.
Στο σχήμα που ακολουθεί βλέπουμε την εικόνα του αισθητήρα.
Ο αισθητήρας έχει 4 ακίδες. Το VCC και το GND πηγαίνουν στις ακίδες 5V και GND στο Arduino και το Trig και το Echo πηγαίνουν σε οποιαδήποτε ψηφιακή ακίδα Arduino. Χρησιμοποιώντας τον ακροδέκτη Trig στέλνουμε το κύμα υπερήχων από τον πομπό και με τον ακροδέκτη Echo λαμβάνουμε το ανακλώμενο σήμα.
Πώς λειτουργεί ο αισθητήρας απόστασης υπερήχων HC-SR04
Όπως φαίνεται στην εικόνα που ακολουθεί ο αισθητήρας εκπέμπει έναν υπέρηχο στα 40 000 Hz που ταξιδεύει στον αέρα και εάν υπάρχει κάποιο αντικείμενο ή εμπόδιο στην πορεία του, θα ανακλασθεί πίσω στη μονάδα. Λαμβάνοντας υπόψη τον χρόνο ταξιδιού και την ταχύτητα του ήχου μπορούμε να υπολογίσουμε την απόσταση.
Για να δημιουργήσουμε τον υπέρηχο πρέπει να ρυθμίσουμε την ακίδα Trig σε υψηλή κατάσταση για 10 µs. Αυτό θα στείλει μια ομάδα 8 κύκλων υπερήχου που θα ταξιδέψει με την ταχύτητα του ήχου. Οι ακίδα Echo ανεβαίνει αμέσως μετά την αποστολή της ομάδας των 8 κύκλων υπερήχων και αρχίζει να ακούει ή να περιμένει να ανακλαστεί αυτό το κύμα από ένα αντικείμενο.
Εάν δεν υπάρχει αντικείμενο ή ανακλώμενος παλμός, η ακίδα Echo θα λήξει μετά από 38 ms και θα επανέλθει σε χαμηλή κατάσταση.
Εάν λάβουμε έναν ανακλώμενο παλμό, η ακίδα Echo θα πέσει νωρίτερα από αυτά τα 38 ms. Ανάλογα με το χρόνο που η ακίδα Echo ήταν HIGH, μπορούμε να προσδιορίσουμε την απόσταση που διένυσε το ηχητικό κύμα, άρα και την απόσταση από τον αισθητήρα στο αντικείμενο.
Στο παρακάτω διάγραμμα φαίνεται η λειτουργία που περιγράψαμε.
Για τον σκοπό αυτό χρησιμοποιούμε τον ακόλουθο βασικό τύπο για τον υπολογισμό της απόστασης:
D = U x T Απόσταση ίσον ταχύτητα επί χρόνο.
Στην πραγματικότητα γνωρίζουμε και τις τιμές ταχύτητας και χρόνου. Ο χρόνος είναι ο χρόνος που η ακίδα Echo ήταν HIGH και η ταχύτητα είναι η ταχύτητα του ήχου που είναι 340 m/s. Υπάρχει ένα επιπλέον βήμα που πρέπει να κάνουμε, και αυτό είναι να διαιρέσουμε το τελικό αποτέλεσμα με το 2. Αυτό πρέπει να το κάνουμε επειδή μετράμε τη διάρκεια που χρειάζεται το ηχητικό κύμα για να ταξιδέψει στο αντικείμενο και να ανακλαστεί πίσω.
Ας υποθέσουμε ότι η ακίδα Echo ήταν HIGH για 2 ms. Αν θέλουμε το αποτέλεσμα της απόστασης να το εκφράσουμε σε cm, μπορούμε να μετατρέψουμε την τιμή της ταχύτητας του ήχου από 340m/s σε 34cm/ms.
Έτσι, εάν η ακίδα Echo ήταν HIGH για 2 ms (το οποίο μετράμε χρησιμοποιώντας τη συνάρτηση pulseIn() για το Arduino, η απόσταση από τον αισθητήρα στο αντικείμενο είναι 34 cm.
D = (U x T) / 2 = (34cm/ms x 2ms) / 2 = 34cm.
Πώς συνδέoυμε τον αισθητήρα υπερήχων HC-SR04 στο Arduino
Η σύνδεση του Arduino Uno με τον αισθητήρα απόστασης φαίνεται στο σχήμα που ακολουθεί.

Οι ακροδέκτες γείωσης GRD και VCC της μονάδας πρέπει να συνδεθούν στη γείωση και τους ακροδέκτες 5 V στην πλακέτα Arduino αντίστοιχα και οι ακροδέκτες trig και echo σε οποιoδήποτε pin Digital I/O στην πλακέτα Arduino.
Κώδικας Arduino για τον αισθητήρας υπερήχων HC-SR04
/*
Ultrasonic Sensor HC-SR04 and Arduino Tutorial
by Dejan Nedelkovski,
www.HowToMechatronics.com
*/
// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
// defines variables
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Starts the serial communication
}
void loop() {
// 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);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance = duration * 0.034 / 2;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
delay(500);
}
Επεξήγηση του κώδικα
Πρώτα πρέπει να ορίσουμε τις ακίδες (pin) Trig και Echo. Σε αυτήν την περίπτωση είναι οι ακίδες με αριθμό 9 και 10 στην πλακέτα του Arduino και τα ονομάζουμαι trigPin και echoPin. Χρειαζόμαστε μια μεταβλητή Long, που ονομάζεται "duration" για το χρόνο ταξιδιού που θα λάβουμε από τον αισθητήρα και μια ακέραια μεταβλητή για την απόσταση την “distance”.
// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
// defines variables
long duration;
long distance;
Στo setup πρέπει να ορίσουμε το trigPin ως έξοδο και το echoPin ως είσοδο και επίσης να ξεκινήσουμε τη σειριακή επικοινωνία για την εμφάνιση των αποτελεσμάτων στην οθόνη.
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Starts the serial communication
}
Στον βρόχο του loop() πρώτα πρέπει να βεβαιωθούμε ότι το trigPin είναι καθαρό, επομένως πρέπει να ρυθμίσετε αυτόν τον ακροδέκτη σε κατάσταση LOW για 2 μs. Τώρα για τη δημιουργία του Ultra ηχητικού κύματος πρέπει να ρυθμίσουμε το trigPin σε κατάσταση HIGH για 10 μs.
// 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);
Χρησιμοποιώντας τη συνάρτηση pulseIn() διαβάζουμε τον χρόνο ταξιδιού και βάζουμε αυτή την τιμή στη μεταβλητή «duration». Αυτή η συνάρτηση έχει 2 παραμέτρους, η πρώτη είναι το όνομα της ακίδας Echo και η δεύτερη είναι η κατάσταση του παλμού που διαβάζουμε, είτε High είτε Low.
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
Σε αυτήν την περίπτωση, χρειαζόμαστε αυτό το σετ σε HIGH, καθώς οι αισθητήρες HC-SR04 ρυθμίζουν την ακίδα Echo σε High μετά την αποστολή της ριπής υπερήχων 8 κύκλων από τον πομπό. Αυτό ουσιαστικά ξεκινάει τον χρονισμό και μόλις λάβουμε το ανακλώμενο ηχητικό κύμα, η ακίδα Echo θα πάει στο Low που σταματά τον χρονισμό. Στο τέλος η συνάρτηση θα επιστρέψει το μήκος του παλμού σε μικροδευτερόλεπτα.
Για να πάρουμε την απόσταση θα πολλαπλασιάσουμε τη διάρκεια με 0,034 και θα τη διαιρέσουμε με το 2 όπως εξηγήσαμε προηγουμένως αυτήν την εξίσωση.
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance = duration * 0.034 / 2;
Στο τέλος θα εκτυπώσουμε την τιμή της απόστασης στην οθόνη.
Τις πληροφορίες που παρέθεσα τις πήρα κυρίως από το site
https://howtomechatronics.com/tutorials/arduino/ultrasonic-sensor-hc-sr04/
Βηματικός κινητήρας
Ένας βηματικός κινητήρας είναι ένας τύπος κινητήρα συνεχούς ρεύματος που περιστρέφεται σε βήματα. Όταν εφαρμόζεται ηλεκτρικό ρεύμα, ο κινητήρας περιστρέφεται σταδιακά και η ταχύτητα περιστροφής εξαρτάται από την “ταχύτητα” με την οποία εφαρμόζετε το ηλεκτρικό ρεύμα στα πηνία του. Η φορά περιστροφής εξαρτάται από τη διαδοχή ενεργοποίησης των πηνίων του κινητήρα. Η γωνία ενός βήματος εξαρτάται από το πόσα τυλίγματα έχει ο κινητήρας.
Τύποι βηματικού κινητήρα
Σε γενικές γραμμές, υπάρχουν δύο τύποι βηματικού κινητήρα, ο μονοπολικός και ο διπολικός.
Οι διπολικοί κινητήρες έχουν 4 καλώδια που συνδέονται με τα δύο ξεχωριστά πηνία μέσα στον κινητήρα - ένα ζεύγος για κάθε πηνίο.
Υπάρχουν επίσης δύο τύποι μονοπολικού κινητήρα - αυτοί με 5 καλώδια και αυτοί με 6 καλώδια.
Οι κινητήρες 6 καλωδίων μπορούν επίσης να αναφέρονται ως υβριδικοί κινητήρες. Είναι παρόμοιοι με τους διπολικούς κινητήρες 4 συρμάτων και έχουν απλώς ένα επιπλέον καλώδιο συνδεδεμένο στο κέντρο καθενός από τα πηνία. Εάν θέλετε να χρησιμοποιήσετε έναν κινητήρα 6 συρμάτων σε διπολική λειτουργία, απλώς αγνοήστε τα καλώδια που συνδέονται με τα κέντρα των πηνίων.
Οι κινητήρες 5 καλωδίων δεν μπορούν να οδηγηθούν από οδηγό σχεδιασμένο για διπολικό κινητήρα. Ένα παράδειγμα κινητήρα 5 καλωδίων, που αναπτύσσουμε στη συνέχεια, είναι ο μικρός κινητήρας 28BYJ-48 που μπορεί να δει κανείς σε πολλά έργα Arduino και συνήθως χρησιμοποιεί ένα τσιπ ULN2003 ως πρόγραμμα οδήγησης.
Ο βηματικός κινητήρας αποτελείται από στάτορα (πηνία) και ρότορα (μόνιμοι μαγνήτες), βλέπε στο σχήμα BIPOLAR. Ο διπολικός (bipolar) βηματικός κινητήρας περιέχει ανεξάρτητα πηνία (χωρίς να είναι συνδεδεμένα με μεσαία λήψη μεταξύ τους), ενώ στον μονοπολικό (unipolar) βηματικό κινητήρα τα πηνία έχουν μεσαία λήψη. Συνήθως οι δύο μεσαίες λήψεις είναι συνδεδεμένες μεταξύ τους και συνδέονται στο θετικό πόλο της πηγής. Έτσι ο διπολικός κινητήρας έχει τέσσερα καλώδια ενώ ο μονοπολικός έχει πέντε.

Στον διπολικό κινητήρα 
για να αναστρέψουμε το μαγνητικό πεδίο του πηνίου πρέπει να αναστρέψουμε την πολικότητα της τάσης στα άκρα του.
Στο μονοπολικό κινητήρα
εάν στην μεσαία λήψη του πηνίου εφαρμόζεται ο θετικός πόλος της τάσης, τότε για να αναστρέψουμε το μαγνητικό πεδίο του πηνίου αρκεί να επιλέξουμε το άλλο άκρο σύνδεσης του πηνίου για τη γείωση. Το κύκλωμα είναι πολύ πιο απλό, αλλά η ισχύς του κινητήρα είναι η μισή, μια που σε κάθε βήμα λειτουργεί το μισό πηνίο.
Προδιαγραφές κινητήρα
Τα φύλλα δεδομένων συνήθως αναφέρουν το ρεύμα του πηνίου, την αντίσταση του πηνίου, την ονομαστική τάση και τη ροπή συγκράτησης και τα βήματα ανά περιστροφή. Για παράδειγμα, για έναν τον κινητήρα οι τιμές αυτές είναι είναι ρεύμα 1 Amp, αντίσταση 2,7 Ohms, τάση 2,7 Volts, ροπή 1,4 Kg-cm και 200 βήματα ανά στροφή.
Η ονομαστική τάση είναι άσχετη για πρακτικούς λόγους. Το σημαντικό στοιχείο είναι το ονομαστικό ρεύμα.
Το ονομαστικό ρεύμα είναι κανονικά το ρεύμα ανά πηνίο, και όταν αναφέρονται στα ρεύματα βηματικού κινητήρα για τις πλακέτες οδήγησης, αυτό συνήθως είναι μια τιμή ανά πηνίο.
Η ροπή συγκράτησης είναι η ροπή που είναι διαθέσιμη για να αντισταθεί στην περιστροφή ενώ ο κινητήρας είναι ακίνητος. Η διαθέσιμη ροπή θα μειωθεί όσο αυξάνεται η ταχύτητα.
Ορισμένοι κατασκευαστές παρέχουν γραφήματα που δείχνουν πώς η ροπή μεταβάλλεται ανάλογα με την ταχύτητα.
Τάση λειτουργίας
Οι βηματικοί κινητήρες είναι πολύ διαφορετικοί από τους κανονικούς κινητήρες συνεχούς ρεύματος.
Σε έναν κινητήρα συνεχούς ρεύματος ελέγχετε το ρεύμα για να ελέγχετε την ταχύτητα του κινητήρα. Ο συνηθισμένος τρόπος ελέγχου του ρεύματος είναι να μεταβάλλετε την τάση - ίσως χρησιμοποιώντας τη συνάρτηση Arduino analogWrite() για να ελέγξετε μια τροφοδοσία ρεύματος με διαμόρφωση πλάτους παλμού στον κινητήρα.
Οι βηματικοί κινητήρες σχεδόν τραβούν το πλήρες ρεύμα τους όλη την ώρα, ακόμα και όταν είναι ακίνητοι - έτσι αντιστέκονται να μετακινηθούν από την παρούσα θέση τους. Αυτό σημαίνει ότι είναι πολύ αναποτελεσματικοί.
Για πρακτικούς λόγους, η ονομαστική τάση ενός βηματικού κινητήρα είναι άσχετη. Είναι η τάση που θα οδηγεί το ονομαστικό ρεύμα μέσω του πηνίου όταν ο κινητήρας είναι ακίνητος με βάση το νόμο Ωμ π.χ. 2,7v = 1A * 2,7 Ohms. Ωστόσο, μόλις ο κινητήρας αρχίσει να κινείται, ο συνδυασμός της αυτεπαγωγής των πηνίων και του back-emf που δημιουργείται από την κίνηση θα εμποδίσει την ονομαστική τάση να παράγει το ονομαστικό ρεύμα.
Για το λόγο αυτό οι βηματικοί κινητήρες συνήθως κινούνται με πολύ υψηλότερη τάση. Αυτό, με τη σειρά του, σημαίνει ότι χρειάζεται μια εξειδικευμένη πλακέτα οδήγησης βηματικού κινητήρα που μπορεί να περιορίσει το ρεύμα σε ό,τι μπορεί να πάρει ο κινητήρας. Εάν το ρεύμα δεν είναι περιορισμένο, η υψηλή τάση θα καταστρέψει γρήγορα τον κινητήρα.
Σχετικά άρθρα για την οδήγηση διαφόρων τύπων από βηματικούς κινητήρες
https://www.makerguides.com/a4988-stepper-motor-driver-arduino-tutorial/
Παράδειγμα Λειτουργίας του βηματικού κινητήρα 28BYJ-48 5v
Εδώ έχω επιλέξει να δώσω ένα παράδειγμα λειτουργίας βηματικού κινητήρα χρησιμοποιώντας τον 28BYJ-48 5v που φαίνεται στο παρακάτω σχήμα.
Θα χρησιμοποιήσω ένα Arduino Uno για να προγραμματίσω την κίνηση του κινητήρα και έναν driver με το ULN2003 Darlington για να εξασφαλίσω το απαιτούμενο ρεύμα για την κίνηση του.
Το ULN2003 ομαδοποιεί 7 τρανζίστορ Darlington σε ένα ενιαίο ολοκληρωμένο κύκλωμα, το οποίο καθιστά δυνατή την παροχή ενός κινητήρα με πολύ υψηλότερο ρεύμα από αυτό που μπορεί να δώσει ένας μικροελεγκτής όπως το Arduino.
ΣΗΜΑΝΤΙΚΟ: Το ULN2003 λειτουργεί εξαιρετικά για μονοπολικούς βηματικούς κινητήρες (αυτούς με 5 ή 6 καλώδια), αλλά δεν είναι καθόλου σχεδιασμένο να οδηγεί με διπολικούς βηματικούς κινητήρες (αυτούς με μόνο 4 καλώδια).
Για έναν διπολικό κινητήρα, θα χρειαστεί να χρησιμοποιήσουμε ένα άλλο κύκλωμα, όπως για παράδειγμα μια Η-διπλή γέφυρα L298Ν που βασίζεται στο πολύ δημοφιλές L298 Dual H-Bridge Motor Driver Integrated Circuit.
Λίγα λόγια για τον κινητήρα 28BYJ-48 5v
Παραπάνω δείξαμε τον χρωματικό πίνακα των καλωδίων του κινητήρα. Όμως πρέπει να πούμε ότι ο κινητήρας αυτός έχει ενσωματωμένο ένα μειωτήρα στροφών, όπως φαίνεται και στο σχήμα.
Σύμφωνα με το φύλλο δεδομένων, όταν ο κινητήρας 28BYJ-48 λειτουργεί σε λειτουργία πλήρους βήματος, κάθε βήμα αντιστοιχεί σε περιστροφή 11,25°. Αυτό σημαίνει ότι υπάρχουν 32 βήματα ανά περιστροφή (360°/11,25° = 32).
Επιπλέον, ο κινητήρας διαθέτει ένα μειωτήρα στροφών 1/64. (Στην πραγματικότητα είναι 1/63.68395, αλλά για τις περισσότερες εφαρμογές το 1/64 είναι μια αρκετά καλή προσέγγιση)
Αυτό σημαίνει ότι στην πραγματικότητα έχουμε 32*63,68395 βήματα ανά περιστροφή = 2037,8864 ~ 2038 βήματα!
Οδηγός για τον κινητήρα 28BYJ-48 5v
Στην εικόνα που ακολουθεί βλέπουμε το σχηματικό διάγραμμα του ULN2003 driver για τον κινητήρα 28BYJ-48.
Ενώ σε αυτή την εικόνα βλέπουμε την πλακέτα που υλοποιεί τον driver για τον κινητήρα 28BYJ-48 .
Και τέλος στην εικόνα που ακολουθεί βλέπουμε τη συνδεσμολογία του Arduino UNO με τον driver και τη συνδεσμολογία του driver με τον κινητήρα.
Προγραμματισμός του βηματικού κινητήρα 28BYJ-48.
Στην εικόνα που ακολουθεί βλέπουμε τη σειρά με την οποία θα πρέπει να τροφοδοτηθούν τα πηνία του κινητήρα έτσι ώστε να κάνει μια περιστροφή κατά τη φορά που κινείται το ρολόι.
Αυτή την εναλλαγή στη συνδεσμολογία των πηνίων την εξασφαλίζει το πρόγραμμα που γράφουμε για τον Arduino και που το παραθέτω στη συνέχεια.
Έλεγχος βηματικού κινητήρα με Arduino με τη χρήση του L298N Driver
// Προγραμματισμός του βηματικού κινητήρα 28BYJ-48 5v
// μια πλήρης στροφή δεξιά και μία αριστερά.
//ορίζω τα pin που θα χρησιμοποιήσω για τη σύνδεση του κινητήρα
#define IN1 8
#define IN2 9
#define IN3 10
#define IN4 11
int Steps = 0; // μετρητής φάσης βηματισμού
boolean Direction = true; //κατεύθυνση κίνησης
void setup() {
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
}
void loop() {
for(int i=0; i<4076; i++){
stepper(1);
delayMicroseconds(1200);
}
Direction = !Direction;
}
void stepper(int xw) {
for (int x = 0; x < xw; x++) {
switch (Steps) {
case 0:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
case 1:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
break;
case 2:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 3:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 4:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 5:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 6:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 7:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
default:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
}
SetDirection();
}
}
void SetDirection() {
if (Direction == 1) {
Steps++;
}
if (Direction == 0) {
Steps--;
}
if (Steps > 7) {
Steps = 0;
}
if (Steps < 0) {
Steps = 7;
}
}
Βέβαια το περιβάλλον Arduino IDE περιλαμβάνει βιβλιοθήκες που απλοποιούν πολύ τον προγραμματισμό βηματικών κινητήρων και έχουν και αρκετά παραδείγματα.
Τέτοιες βιβλιοθήκες είναι η stepper library που τη δηλώνετε στο πρόγραμμα με το #include <Stepper.h> . Η stepper library χρησιμοποιείται για block προγραμματισμό. Δηλαδή ο μικρο-κοντρόλερ θα περιμένει να τελειώσει ο αριθμός των βημάτων που θα κάνει ο κινητήρας για να πάει στην επόμενη εντολή του προγράμματος.
Η βιβλιοθήκη AccelStepper library που τη δηλώνετε με το #include <AccelStepper.h> δίνει τη δυνατότητα για επιτάχυνση ή επιβράδυνση στην κίνηση του βηματικού κινητήρα. Επίσης είναι non-block programming library. Δηλαδή ο μικρο-κοντρόλερ ΔΕΝ θα περιμένει να τελειώσει ο αριθμός των βημάτων που θα κάνει ο κινητήρας για να πάει στην επόμενη εντολή του προγράμματος.
Ελεγκτής PID
Ο Ελεγκτής PID είναι ένας αναλογικός-ολοκληρωτικός-παράγωγος (Proportional–Integral–Derivative ) ελεγκτής ή αλλιώς ελεγκτής τριών όρων. Είναι ένας μηχανισμός βρόχου ελέγχου που χρησιμοποιεί ανάδραση και χρησιμοποιείται ευρέως σε βιομηχανικά συστήματα ελέγχου και σε μια ποικιλία άλλων εφαρμογών που απαιτούν συνεχώς διαμορφωμένο έλεγχο. Ένας ελεγκτής PID υπολογίζει συνεχώς μια τιμή σφάλματος e(t) ως τη διαφορά μεταξύ ενός επιθυμητού σημείου ρύθμισης (SetPoint -SP) και της τρέχουσας τιμής μιας μετρούμενης μεταβλητής διεργασίας (Process Variable PV) και εφαρμόζει μια διόρθωση που βασίζεται σε αναλογικό, ολοκληρωτικό και παράγωγο όρο (που συμβολίζονται με P, I και D αντίστοιχα), εξ ου και το όνομα.
Πρακτικά, εφαρμόζει αυτόματα μια ακριβή και ανταποκρινόμενη διόρθωση σε μια λειτουργία ελέγχου. Ένα καθημερινό παράδειγμα είναι το cruise control σε ένα αυτοκίνητο, όπου η ανάβαση σε ένα λόφο θα μείωνε την ταχύτητα εάν υπήρχε μόνο σταθερή ισχύς κινητήρα. Ο αλγόριθμος PID του ελεγκτή επαναφέρει τη μετρούμενη ταχύτητα στην επιθυμητή ταχύτητα με ελάχιστη καθυστέρηση και υπέρβαση αυξάνοντας την ισχύ εξόδου του κινητήρα με ελεγχόμενο τρόπο.
Λειτουργία του ελεγκτή
Το χαρακτηριστικό γνώρισμα του ελεγκτή PID είναι η δυνατότητα χρήσης των τριών όρων ελέγχου της αναλογικής, της ολοκληρωτικής και της παράγωγης επιρροής στην έξοδο του ελεγκτή για την εφαρμογή ακριβούς και βέλτιστου ελέγχου. Το μπλοκ διάγραμμα του ελεγκτή που φαίνεται πιο κάτω, δείχνει τις αρχές του τρόπου με τον οποίο δημιουργούνται και εφαρμόζονται αυτοί οι όροι. Εμφανίζει έναν ελεγκτή PID, ο οποίος υπολογίζει συνεχώς μια τιμή σφάλματος e(t) ως τη διαφορά μεταξύ ενός επιθυμητού σημείου ρύθμισης SP=r(t) και μια μετρημένη μεταβλητή διαδικασίας PV=y(t) e(t)=r(t)-y(t) και εφαρμόζει μια διόρθωση που βασίζεται σε αναλογικό, ολοκληρωτικό και παράγωγο όρο. Ο ελεγκτής προσπαθεί να ελαχιστοποιήσει το σφάλμα με την πάροδο του χρόνου προσαρμόζοντας μια μεταβλητή ελέγχου u(t), όπως π.χ. το άνοιγμα μιας βαλβίδας ελέγχου, σε μια νέα τιμή που καθορίζεται από ένα σταθμισμένο άθροισμα των όρων ελέγχου .
Σε αυτό το μοντέλο:
Ο όρος P είναι ανάλογος με την τρέχουσα τιμή του σφάλματος SP−PV = e(t).

Για παράδειγμα, εάν το σφάλμα είναι μεγάλο και θετικό, η έξοδος ελέγχου θα είναι αναλογικά μεγάλη και θετική, λαμβάνοντας υπόψη τον παράγοντα απολαβής Kp. Η χρήση μόνο του αναλογικού ελέγχου θα οδηγήσει σε σφάλμα μεταξύ του σημείου ρύθμισης και της πραγματικής τιμής διεργασίας, επειδή απαιτεί σφάλμα για τη δημιουργία της αναλογικής απόκρισης. Εάν δεν υπάρχει σφάλμα, δεν υπάρχει διορθωτική απάντηση.
Ο όρος I λαμβάνει υπόψη τις προηγούμενες τιμές του σφάλματος SP−PV

και τις ενσωματώνει με την πάροδο του χρόνου για να παράγει τον όρο I. Για παράδειγμα, εάν υπάρχει ένα υπολειπόμενο σφάλμα SP−PV μετά την εφαρμογή του αναλογικού ελέγχου, ο ολοκληρωτικός όρος επιδιώκει να εξαλείψει το υπολειπόμενο σφάλμα προσθέτοντας ένα αποτέλεσμα ελέγχου, με βαρύτητα Ki , λόγω της ιστορικής αθροιστικής τιμής του σφάλματος. Όταν εξαλειφθεί το σφάλμα, ο ολοκληρωτικός όρος θα πάψει να αυξάνεται. Αυτό θα έχει ως αποτέλεσμα τη μείωση του αναλογικού αποτελέσματος καθώς μειώνεται το σφάλμα, αλλά αυτό αντισταθμίζεται από το αυξανόμενο ολοκληρωτικό αποτέλεσμα.
Ο όρος D είναι η καλύτερη εκτίμηση της μελλοντικής τάσης του σφάλματος SP−PV,

με βάση τον τρέχοντα ρυθμό μεταβολής του. Μερικές φορές αποκαλείται «προληπτικός έλεγχος», καθώς επιδιώκει ουσιαστικά να μειώσει την επίδραση του σφάλματος SP−PV ασκώντας μια επιρροή ελέγχου που δημιουργείται από τον ρυθμό μεταβολής του σφάλματος. Όσο πιο γρήγορη είναι η αλλαγή, τόσο μεγαλύτερο είναι το αποτέλεσμα ελέγχου ή απόσβεσης. Σημαντικός είναι ο ρόλος της σταθεράς Kd στον υπολογισμό της διόρθωσης D.
Εφαρμογή ελεγκτή PID στον Κώδικα
Για να εφαρμόσετε έναν ελεγκτή PID σε κώδικα ή σε ένα πρόγραμμα Arduino, πρέπει να είναι γνωστές πέντε παράμετροι:
- αναλογική σταθερά Kp
- ολοκληρωτική σταθερά Ki
- και παράγωγη σταθερά Kd
- τιμή εισόδου (PV)
- και τιμή σημείου ρύθμισης (SP)
Ο υπολογισμός PID πρέπει να βρίσκεται μέσα σε μια συνάρτηση βρόχου. Το πρώτο μέρος της συνάρτησης θα πρέπει να είναι ο καθορισμός του χρόνου που έχει παρέλθει.
Στο Arduino, η τρέχουσα ώρα μπορεί να προσδιοριστεί με τη συνάρτηση millis() και ο χρόνος που έχει παρέλθει είναι απλώς:
currentTime = millis();
elapsedTime = currentTime - previousTime;
Στη συνέχεια, πρέπει να προσδιοριστεί το σφάλμα:
error = setPoint – input;
Προγραμματίζοντας σε Arduino οι υπολογισμοί απλοποιούνται πάρα πολύ με τη χρήση της βιβλιοθήκης PID_v1. Στο παράδειγμα που σας παραθέτω έκανα χρήση της βιβλιοθήκης PID_v1.
Σε κάθε περίπτωση είναι αναγκαίος ο προσδιορισμός για τις τρεις σταθερές P, I, D. Αυτός ο προσδιορισμός γίνεται συνήθως πειραματικά και είναι μια επίπονη διαδικασία.
Κατασκευή
Η κατασκευή είναι συνέχεια της προηγούμενης που έκανα με τους δύο σερβοκινητήρες. Αφού σε αυτή έχουμε προσθέσει τον αισθητήρα MPU-9250. Βλέπε σχετικά εδώ.
Το σημαντικότερο για την κατασκευή είναι το λογισμικό που θα γράψουμε έτσι ώστε η κίνηση στους σερβοκινητήρες να ελέγχεται πλέον από τον αισθητήρα και να γίνεται ομαλά, χωρίς ταλαντώσεις και να φέρνει το σύστημα στην επιθυμητή (οριζόντια) θέση.
Το πρόγραμμα της κατασκευής για Arduino UNO θα το κατεβάσετε από εδώ.
Κίνηση είναι η συνεχής μεταβολή της θέσης ενός αντικειμένου στο χώρο. Εδώ θα σας παρουσιάσω με απλά λόγια τον αισθητήρα 9 αξόνων που παρακολουθεί τη μεταβολή της θέσης του στο χώρο των τριών διαστάσεων, τον MPU 9250.
Στη συνέχεια θα σας παρουσιάσω μία απλή κατασκευή με τον αισθητήρα MPU 9250 βασισμένη στην κατασκευή που έκανα με τους σερβοκινητήρες.
Ο αισθητήρας μεταβολής της θέσης μπορεί να χρησιμοποιηθεί σε αεροσκάφη (διάφορα drones και τετρακόπτερα) σε smartphones και στη ρομποτική, σε διάφορους χειρισμούς και σε συσκευές που σχετίζονται με τρισδιάστατο έλεγχο και την αναγνώριση κινήσεων.
Το MPU-9250 είναι ένα System in Package (SiP) που συνδυάζει δύο τσιπ: το γυροσκόπιο τριών αξόνων MPU-6500 που είναι και επιταχυνσιόμετρο τριών αξόνων, και το AK8963 που είναι μαγνητόμετρο τριών αξόνων. Έτσι το MPU 9250 εκτελεί τις λειτουργίες πολλών αισθητήρων ταυτόχρονα: είναι γυροσκόπιο, επιταχυνσιόμετρο και μαγνητόμετρο.
Ας σταθούμε λίγο περισσότερο σε καθένα από αυτά.
Το γυροσκόπιο είναι ένας αισθητήρας που ανταποκρίνεται στις αλλαγές των γωνιών προσανατολισμού στο διάστημα. Στο τετραπτέριγο (drone), χρησιμοποιείται για τη σταθεροποίηση της θέσης της συσκευής στον αέρα και την προστασία από τον άνεμο.
Το επιταχυνσιόμετρο συγκρίνει την προβολή της επιτάχυνσης ενός αντικειμένου με την επιτάχυνση της βαρύτητας και είναι ικανό να μετρήσει τη γραμμική ταχύτητα του αντικειμένου και, μαζί με το γυροσκόπιο, τη θέση του στο χώρο.
Το μαγνητόμετρο είναι μια συσκευή για τη μέτρηση της έντασης του πλησιέστερου μαγνητικού πεδίου που δρα σε ένα αντικείμενο (το όνομα του αισθητήρα μιλά από μόνο του).
Σύμφωνα με ορισμένες πηγές, η μονάδα MPU 9250 είναι ο μικρότερος αισθητήρας εννέα αξόνων στον κόσμο. Αυτό υποδεικνύει την υψηλή απόδοση του τσιπ, το οποίο παρέχεται με τη χρήση της τεχνολογίας CMOS MEMS (μικροηλεκτρομηχανικά συστήματα ).
Η θήκη της μονάδας αποτελείται από δύο μικρότερους κρυστάλλους, ένας από τους οποίους είναι υπεύθυνος για το γυροσκόπιο και το επιταχυνσιόμετρο και ο άλλος για το μαγνητόμετρο. Τα δεδομένα από αυτούς τους κρυστάλλους επεξεργάζονται από τον ενσωματωμένο επεξεργαστή σήματος DMP (Data Management Platform) χρησιμοποιώντας αλγόριθμους Motion Fusion και μεταδίδονται μέσω των διεπαφών I2C ή SPI.
Εκτός από τις υψηλές επιδόσεις, η μονάδα είναι αρκετά δημοφιλής μεταξύ των ηλεκτρολόγων μηχανικών και εκείνων που αγαπούν τις συσκευές για τηλεχειρισμό, ενώ έχει επίσης χαμηλή κατανάλωση ενέργειας και κόστος.
Αρχή λειτουργίας του επιταχυνσιόμετρου
Ένα επιταχυνσιόμετρο μετρά το ρυθμό μεταβολής της ταχύτητας ενός αντικειμένου σε σχέση με το χρόνο, γνωστό και σαν επιτάχυνση. Με ένα επιταχυνσιόμετρο, μπορείτε επίσης να καταλάβετε τη γωνία κλίσης του αισθητήρα σε σχέση με το έδαφος.
Ένα επιταχυνσιόμετρο έχει μικροσκοπικούς κρυστάλλους που υφίστανται πίεση όταν συμβαίνουν δονήσεις. Από αυτήν την πίεση, παράγεται μια τάση που δημιουργεί μια ένδειξη σε οποιαδήποτε επιτάχυνση. Η μονάδα μέτρησης για την επιτάχυνση είναι το μέτρο ανά δευτερόλεπτο στο τετράγωνο (m/s^2). Αλλά καθώς οι αισθητήρες του επιταχυνσιόμετρου εκφράζουν μετρήσεις σε "g", ένα "g" είναι η τιμή της βαρύτητας της γης που είναι ίση με 9,8 μέτρα ανά δευτερόλεπτο στο τετράγωνο.
Για παράδειγμα, σε ένα επιταχυνσιόμετρο 3 αξόνων όπως ο αισθητήρας επιταχυνσιόμετρου MPU9250, όταν τοποθετείται σε οριζόντιο επίπεδο με τον άξονα Ζ προς τα πάνω, η έξοδος του άξονα Ζ του αισθητήρα = 1 g ή 9,8m/s2 ενώ X και Y = 0. Αυτό συμβαίνει λόγω της δύναμης της βαρύτητας που είναι κάθετη στους άξονες Χ και Υ και έτσι δεν τους επηρεάζει.
Από αυτά τα δεδομένα, με απλά μαθηματικά τριγωνομετρίας, μπορεί κανείς να υπολογίσει τη γωνία του αισθητήρα και κατ επέκταση της κατασκευής επάνω στην οποία ο αισθητήρας είναι προσδεδεμένος.
Αρχή λειτουργίας γυροσκοπίου
Το γυροσκόπιο μετρά την ταχύτητα περιστροφής ή το ρυθμό αλλαγής της γωνιακής θέσης με την πάροδο του χρόνου. Η λειτουργία του βασίζεται στο φαινομένο Coriolis.
Όταν μια μάζα κινείται σε μια συγκεκριμένη κατεύθυνση με μια συγκεκριμένη ταχύτητα και εφαρμοστεί ένας εξωτερικός ρυθμός γωνιακής περιστροφής, τότε θα προκύψει μια δύναμη την οποία ο αισθητήρας θα ανιχνεύσει.
Οι έξοδοι του γυροσκοπίου είναι σε μοίρες ανά δευτερόλεπτο
Εάν γνωρίζουμε την αρχική γωνία του IMU, μπορούμε να προσθέσουμε την τιμή που μας δίνει το γυροσκόπιο για να γνωρίσουμε τη νέα γωνία κάθε στιγμή. Ας υποθέσουμε ότι ξεκινάμε το IMU από 0 °. Εάν το όργανο μας δίνει μια μέτρηση κάθε δευτερόλεπτο και σημειώνει 3 στον άξονα Χ, θα έχουμε τη γωνία με αυτόν τον απλό τύπο:
AngleX=PreviousAngleX + GyroDataX * elapsedTime
AngleY=PreviousAngleY + GyroDataY * elapsedTime
Όπου elapsedTime είναι ο χρόνος που μεσολαβεί κάθε φορά που υπολογίζεται αυτός ο τύπος εντός του βρόχου, PreviousAngle είναι η γωνία που υπολογίστηκε την τελευταία φορά που κλήθηκε αυτός ο τύπος και GyroData είναι η ανάγνωση της γωνίας Y ή X του γυροσκοπίου.
Το μαγνητόμετρο
Το τσιπ MPU-9250 περιλαμβάνει το AK8963 που είναι το μαγνητόμετρο. Αυτό μπορεί να γνωρίζει τον προσανατολισμό σε σχέση με τον μαγνητικό βορρά, παρόμοια με το πώς λειτουργεί μια πυξίδα χειρός. Οι ενσωματωμένοι ADC 16-bit δειγματίζουν ταυτόχρονα τους 3 άξονες κίνησης (X, Y, Z).
Η βαθμονόμηση του μαγνητόμετρου μπορεί να γίνει αυτόματα με χρήση της συνάρτησης magcalMPU9250 (float * dest1, float * dest2) και βαθμονομεί το μαγνητόμετρο ενώ μετακινείτε τον αισθητήρα σε σχήμα οκτώ. Αποθηκεύει τις μέγιστες και ελάχιστες ενδείξεις και παίρνει το μέσο όρο.
Κατασκευή
Η κατασκευή είναι συνέχεια της προηγούμενης που έκανα με τους δύο σερβοκινητήρες. Σε αυτή θα προσθέσουμε τον αισθητήρα MPU-9250. Το σημαντικότερο για την κατασκευή είναι το λογισμικό που θα γράψουμε έτσι ώστε η κίνηση στους σερβοκινητήρες να ελέγχεται πλέον από τον αισθητήρα και όχι από τα ποτενσιόμετρα.
Το επόμενο σχήμα μας δείχνει το κύκλωμα σύνδεσης του αισθητήρα με το Arduino UNO.
Η σύνδεση γίνεται με το I2C (Inter-Integrated Circuit) bus, πρωτόκολλο επικοινωνίας με δύο αγωγούς που διαθέτει ο αισθητήρας.
Για χάρη απλότητας θα χρησιμοποιήσω τρεις από τους εννέα άξονες που διαθέτει ο αισθητήρας. Θα χρησιμοποιήσω μόνο το επιταχυνσιόμετρο για τους άξονες x, y και z. Η κίνηση θα γίνεται σε δύο επίπεδα κάθετα μεταξύ τους και θα εξασφαλίζεται από τους δύο σερβοκινητήρες. Όπως βλέπετε επάνω στην πλακέτα του αισθητήρα ο κατασκευαστής έχει σημειώσει τους άξονες. Οι άξονες είναι παράλληλοι προς τα επίπεδα κίνησης, ο καθένας με ένα επίπεδο κίνησης.
Ο στόχος της κατασκευής είναι να παραμένει σε οριζόντιο επίπεδο ο αισθητήρας όπως και να στρέφω εγώ το επίπεδο στήριξης της κατασκευής.
Ο αισθητήρας βρίσκεται τοποθετημένος σε μία βάση που στην κατάσταση ηρεμίας είναι οριζόντια. Την τοποθετούμε έτσι ώστε να είναι παράλληλη με τη βάση στήριξης. Στη συνέχεια ενόσω εγώ θα περιστρέφω τη βάση στήριξης θα παρατηρώ πώς οι σερβοκινητήρες φέρνουν σε οριζόντια θέση τον αισθητήρα.
Από το καλάθι με τα παιχνίδια των εγγονιών μου πήρα ένα στρουμφάκι, τον Σπιρτούλη, και το έβαλα στην πλατφόρμα με τον αισθητήρα. Η όρθια στάση του Σπιρτούλη επισημαίνει άμεσα ότι ο αισθητήρας είναι οριζόντιος.
Στη φωτογραφία που ακολουθεί φαίνεται η κατασκευή και στο βίντεο που σας δίνω στο τέλος του άρθρου φαίνεται η λειτουργία της κατασκευής.
Προγραμματισμός
Η συμβουλή μου είναι οι βιβλιοθήκες που χρησιμοποιείτε για το Arduino IDE να βρίσκονται στο φάκελο του project που δουλεύετε. Η βιβλιοθήκη που χρησιμοποίησα για τον MPU9250 είναι η Bolder_Flight_Systems_MPU9250 που αν δεν την έχετε εγκατεστημένη είναι εύκολο να κατεβάσετε από το internet.
Στη συνέχεια παραθέτω τον κώδικα που έγραψα τον οποίο μπορείτε να κατεβάσετε από το εδώ
//Author : Manolis Aristovoulidis
//Το πρόγραμμα αυτό χρησιμοποιεί ένα MPU-9250 και δύο σερβοκινητήρες
//με τη λειτουργία του προγράμματος οισερβοκινητήρες κρατουν πάντα σε
//οριζόντια θέση τον αισθητήρα
#include <Wire.h>
#include <MPU9250.h>
#include <Servo.h>
Servo servo_x; // δημιουργία ενός servo object για τον έλεγχο του servo
Servo servo_y;
int val_x = 95; // μεταβλητή για την γωνια κίνησης του servo_x
int val_y = 100; // μεταβλητή για την γωνια κίνησης του servo_y
// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68
MPU9250 IMU(Wire,0x68);
int status;
//Acc Variables
float rad_to_deg = 180/3.141592654; //This value is for pasing from radians to degrees values
float Acc_rawX, Acc_rawY, Acc_rawZ; //Here we store the raw data read
float Acc_angle_x, Acc_angle_y; //Here we store the angle value obtained with Acc data
float Total_angle_x, Total_angle_y; //Here we store the final total angle
int x_tilt = 0;
int y_tilt = 0;
int i;
void setup() {
// serial to display data
Serial.begin(115200);
while(!Serial) {}
servo_x.attach(4); //κάνει προσάρτηση του servo στο pin 4 του servo object
servo_y.attach(5); //κάνει προσάρτηση του servo στο pin 5 του servo object
//περιστοφή των σερβοκινητήρων
servo_x.write(val_x); //Μετά από πειραματισμούς αυτή είναι η
servo_y.write(val_y); //οριζόντια θέση για τη βάση του MPU9250
delay(1000);
// start communication with IMU
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
/* Default values of MPU9250
* accel range to 16G as default
* gyro range to 2000DPS as default
* bandwidth to 184Hz as default
* sample rate divider to 0 as default
*
*/
// αναμονή για το calibration που προκαλει η IMU.begin()
delay(3000);
}
void loop() {
IMU.readSensor();
Acc_rawX = IMU.getAccelX_mss();
Acc_rawY = IMU.getAccelY_mss();
Acc_rawZ = IMU.getAccelZ_mss();
/*---Y---*/
Acc_angle_x = (atan((Acc_rawY)/sqrt(pow((Acc_rawX),2) + pow((Acc_rawZ),2)))*rad_to_deg) ;
/*---Y---*/
Acc_angle_y = (atan(-1*(Acc_rawX)/sqrt(pow((Acc_rawY),2) + pow((Acc_rawZ),2)))*rad_to_deg) ;
////////////////////////////////////// Γωνία κλίσης και φίλτρο /////////////////////////////////////
Total_angle_x = 0.94 *Total_angle_x + 0.06*Acc_angle_x;
Total_angle_y = 0.94 *Total_angle_y + 0.06*Acc_angle_y;
x_tilt = (int)Total_angle_x ;
y_tilt = (int)Total_angle_y ;
//********************* Υπολογισμός κίνηση επαναφοράς στον άξονα των Χ **************************************
if(x_tilt > 1){
val_x--;
}
if(x_tilt < -1){
val_x++;
}
if(val_x > 180){val_x = 180;}
if(val_x < 0){val_x = 0;}
//********************* Υπολογισμός κίνηση επαναφοράς στον άξονα των Υ ****************************************
if(y_tilt > 1){
val_y++;
}
if(y_tilt < -1){
val_y--;
}
if(val_y > 180){val_y = 180;}
if(val_y < 0){val_y = 0;}
//******************* Κίνηση των σερβοκινητήρων σε γωνία μεταξύ 0-180 μοιρών ******************************************
servo_x.write(val_x); // ρυθμίζει τη θέση του servo στην τιμή της κλίμακας
servo_y.write(val_y); // ρυθμίζει τη θέση του servo στην τιμή της κλίμακας
delay(50);
}
Με τη χρήση δύο σερβοκινητήρων διατηρείται σε οριζόντια θέση πάντα η πλατφόρμα που στηρίζει τον αισθητήρα κίνησης MPU9250. Όπως και να περιστρέψω εγώ τη βάση στην οποία στηρίζεται ολόκληρος ο μηχανισμός η πλατφόρμα επανέρχεται σε οριζόντια θέση.
Στην εικόνα που ακολουθεί βλέπετε τις τιμές που δίνει το επιταχυνσιόμετρο του αισθητήρα κατά την κίνηση, ενόσω προσπαθεί να ισορροπήσει στην τιμή μηδέν για τον άξονα x. Η κόκκινη γραμμή παρουσιάζει τις τιμές του αισθητήρα και η πράσινη παρουσιάζει τις τιμές που δίνει το φίλτρο εξομάλυνσης στη γραμμή 166 του προγράμματος και οι οποίες τιμές κινούν το σερβοκινητήρα x.
Η κατασκευή σε λειτουργία φαίνεται εδώ.
Έλεγχος κινητήρα DC
Σε αυτή την κατασκευή θα δώσουμε κίνηση στον κινητήρα με τη χρήση ενός κοντρόλερ και θα μετράμε την ταχύτητά του, όπως κάναμε στην εφαρμογή “Κινητήρας DC – Encoder”. Για να το κάνουμε αυτό θα προσθέσουμε ένα ακόμη κύκλωμα, αυτό της τροφοδοσίας του κινητήρα, και λίγες γραμμές κώδικα στο πρόγραμμα που γράψαμε για την προηγούμενη κατασκευή μας με τον τίτλο “Κινητήρας DC – Encoder”.
Δευτερευόντως θα χρησιμοποιήσουμε ένα infrared τηλεκοντρόλ για να δίνουμε εντολές κίνησης στον κινητήρα.
Τα υλικά για την κατασκευή είναι τα ίδια. Εδώ θα εστιάσουμε περισσότερο στον κοντρόλερ για την οδήγηση του κινητήρα, και θα πούμε λίγα λόγια για την PWM διαμόρφωση (Pulse Width Modulation) και πως αυτή θα την υλοποιήσουμε στο Arduino UNO.
PWM
Η διαμόρφωση PWM είναι μια περιοδική τετραγωνική κυματομορφή που διαφοροποιείται από το ποσοστό του χρόνου που είναι σε κατάσταση ΟΝ ή αλλιώς Hight σε μία περίοδο. Αυτή την κατάσταση ΟΝ την ονομάζουμε Duty Cycle και τη μετράμε σαν ποσοστό της συνολικής διάρκειας μιας περιόδου.
Στο σχήμα που ακολουθεί βλέπουμε έξι διαφορετικές μορφές μιας PWM. Οι πράσινες κάθετες γραμμές καθορίζουν τη διάρκεια ενός κύκλου ή αλλιώς το πλήθος των κύκλων στη μονάδα του χρόνου.
Στην πρώτη γραμμή διακρίνουμε ότι η κατάσταση των παλμών είναι 0 για όλη τη διάρκεια της περιόδου τους. Τότε λέμε οτι το Duty Cycle είναι 0%. Σε αυτή την περίπτωση η ισχύς που παρέχει ο παλμός είναι μηδενική.
Στη δεύτερη γραμμή ένα μικρό τμήμα της περιόδου, το 25% είναι ΟΝ. Στην περίπτωση αυτή η ισχύς που παρέχει ο παλμός είναι 25% της δυνατότητας του.
Τέλος στην τελευταία γραμμή ο παλμός είναι ΟΝ καθ όλη τη διάρκεια του και η ισχύς που παρέχει είναι το 100% της δυνατότητας του.
Το Arduino UNO με πολύ απλό τρόπο μπορεί να παρέχει PWM διαμόρφωση στα pin 3, 9, 10, 11 με συχνότητα 490 Hz ενώ στα pins 5 και 6 με συχνότητα 980 Hz. Στην εφαρμογή αυτή δεν μας ενδιαφέρει η συχνότητα του παλμού, μας ενδιαφέρει μόνο το Duty Cycle.
Με την εντολή analogWrite(pin, value) , που δεν έχει καμία σχέση με αναλογική έξοδο, δημιουργείται PWM παλμός στο pin που έχουμε ορίσει. Η μεταβλητή value παίρνει τιμές από 0 έως 255. Για την τιμή 0 δημιουργεί παλμό με Duty Cycle 0% και για την τιμή 255 δημιουργεί παλμό με Duty Cycle 100%. Έτσι η τιμή που θα έχει η μεταβλητή καθορίζεται από τη σχέση value = Duty Cycle * 255.
Για παράδειγμα για να φτιάξουμε παλμό με Duty Cycle 20% η τιμή της μεταβλητής είναι value = 0,2 * 255 = 51.
Κοντρόλερ
Ο κοντρόλερ που χρησιμοποιούμε εδώ είναι ο 7A/160W. Μπορεί να οδηγήσει δύο κινητήρες με τάση από 7 έως 24V. Στην παρακάτω εικόνα φαίνονται τα σημεία διασύνδεσης του κοντρόλερ και στον πίνακα που ακολουθεί φαίνονται οι λειτουργίες που έχουν αυτά τα σημεία διασύνδεσης.
Εμείς χρησιμοποιούμε τα σημεία με Label 1,2 για να συνδέσουμε μία μπαταρία 12V.
Τα σημεία 3 και 4 για να συνδέσουμε την τροφοδοσία του κινητήρα (άσπρο και κόκκινο καλώδιο)
Το σημείο 7 για να συνδέσουμε τον παλμό PWM από το pin του Arduino UNO
Τα σημεία 8 και 9 για να συνδέσουμε την επιλογή της φοράς της κίνησης ΙΝ1 και ΙΝ2 όπως φαίνεται στην εικόνα με τις σημειώσει μου.
Και τα σημεία +5V και GND που βρίσκονται πριν το 7 και μετά το 9 όπως φαίνονται στην εικόνα του κοντρόλερ για να συνδέσουμε την τροφοδοσία στο ψηφιακό κύκλωμα του κοντρόλερ.
Ο πίνακας που ακολουθεί (Control Logic Table) για τον κινητήρα που έχουμε συνδέσει, μας δείχνει τις κινήσεις που θα εκτελεί ο κινητήρας ανάλογα με τις τιμές που θα έχουν οι είσοδοι ΙΝ1 και ΙΝ2. Τη χρήση τους τη βλέπετε στο πρόγραμμα στις συναρτήσεις goForword() και goBackword().
Προγραμματισμός
Ερχόμαστε τώρα στο πρόγραμμα που θα κινήσει την κατασκευή μας.
// Author Manolis Aristovoulidis
// Το πρόγραμμα αυτό κινεί ένα κινητήρα 12V DC με τη χρήση ενός κοντρόλερ
// χρησημοποιεί ένα Infrared τηλεκοντρόλ για να δίνει οδηγίες για την κίνηση
// μετρά και "τυπώνει" την ταχύτητα και την κατεύθυνση της κίνησης.
#include <IRremote.h>
const int RECV_PIN = 12;
IRrecv irrecv(RECV_PIN);
decode_results results;
// Motor A connections
const int enA = 6;
const int in1 = 5;
const int in2 = 4;
//motor A encoder
const byte encoder_pinA = 2; //A pin -> the interrupt pin 2
const byte encoder_pinB = 10; //B pin -> the digital pin 10
int pulses; //the number of the pulses
boolean Direction; //the rotation direction
// Set the speed (0 = off and 255 = max speed)
int motorSpeed = 0;
void setup() {
// Motor control pins are outputs
Serial.begin(57600); //Initialize the serial port
EncoderInit(); //Initialize the module
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results)){
//Serial.println(results.value, HEX);
irrecv.resume();
switch (results.value) {
case 0xFF18E7: //key UP
if(motorSpeed <= 200){
motorSpeed +=50;
}
if(motorSpeed >=0){
// move forword
goForword();
}else{
//move backword
goBackword();
}
analogWrite(enA, abs(motorSpeed));
break;
case 0xFF4AB5: //key DOWN
if(motorSpeed > -250){
motorSpeed -=50;
}
if(motorSpeed >=0){
// move forword
goForword();
}else{
//move backword
goBackword();
}
analogWrite(enA, abs(motorSpeed));
break;
case 0xFF38C7: //key OK
//stop moving
stopMove();
break;
default:
// statements
break;
}
}
Serial.print("Direction:");
if(Direction){
Serial.print("Forword ");
}else{
Serial.print("Backword ");
}
Serial.print("Pulses:");
Serial.println(pulses);
pulses = 0;
delay(100);
}
void EncoderInit()
{
Direction = true; //default -> Forward
pinMode(encoder_pinB,INPUT);
attachInterrupt(digitalPinToInterrupt(encoder_pinA), wheelSpeed, RISING );
}
void wheelSpeed()
{
int val = digitalRead(encoder_pinB);
if(val == LOW ){
Direction = false; //Reverse
pulses--;
}else{
Direction = true; //Forward
pulses++;
}
}
void goForword(){
digitalWrite(in1, HIGH); //1,0 ->Forward
digitalWrite(in2, LOW);
}
void goBackword(){
digitalWrite(in1, LOW); //0,1 ->Backword
digitalWrite(in2, HIGH);
}
void stopMove(){
digitalWrite(in1, LOW); //1,0 ->Forward
digitalWrite(in2, LOW);
motorSpeed = 0;
analogWrite(enA, abs(motorSpeed));
}
Στο βρόχο Loop() του προγράμματος υπάρχει ένα switch - case το οποίο οδηγεί το πρόγραμμα σύμφωνα με την εντολή που δώσαμε από το τηλεκοντρολ. Από το τηλεκοντρόλ δίνουμε τρεις εντολές, άνω βέλος για αύξηση ταχύτητας προ τα εμπρός, κάτω βέλος για μείωση ταχύτητας και εν τέλει αναστροφή της κίνησης και τέλος "ΟΚ" για μηδενισμό της ταχύτητας του μοτέρ.
Η κίνηση προς τα εμπρός γίνεται με τη συνάρτηση goForword()
Η κίνηση προς τα πίσω γίνεται με τη συνάρτηση goBackword()
Το σταμάτημα του μοτέρ γίνεται με τη συνάρτηση stoMove()
Τέλος η ταχύτητα ορίζεται από την εντολή analogWrite(enA, abs(motorSpeed)) που παράγει τον PWM παλμό στο pin enA με Duty Cycle σύμφωνα με την τιμή της μεταβλητής motorSpeed.
Το πρόγραμμα μπορείτε να το κατεβάστε από εδώ.
Στο βίντεο που ακολουθεί βλέπετε την κατασκευή σε λειτουργία. https://youtu.be/4HFExAJxDxY
Κινητήρας συνεχούς ρεύματος με κωδικοποιητή
Στο άρθρο αυτό θα κάνουμε μια απλή κατασκευή για να κατανοήσουμε τη λειτουργία του κωδικοποιητή σε έναν κινητήρα συνεχούς ρεύματος.
Τα υλικά που θα χρειαστούμε για να υλοποιήσουμε την κατασκευή μας είναι
- ένα Arduino Uno,
- ένα τροφοδοτικό συνεχούς ρεύματος για τον κινητήρα,
- έναν κοντρόλερ για την οδήγηση του κινητήρα,
- και έναν κινητήρα συνεχούς ρεύματος με προσαρμοσμένο στην κατασκευή του έναν κωδικοποιητή.
- ένα Arduino UNO Shield, κενή διάτρητη πλακέτα
- κάποια υλικά σύνδεσης, λεπτά καλώδια σε διάφορα χρώματα
Στην κενή πλακέτα θα γίνουν όλες οι απαραίτητες συνδέσεις. Η συνδεσμολογία πλακέτας που παρουσιάζω πιο κάτω αποτελεί έναν καλό οδηγό για την κατασκευή.
Στην παρακάτω φωτογραφία βλέπετε τον κινητήρα DC που διάλεξα να χρησιμοποιήσω. Όπως μπορείτε να δείτε έχει ενσωματωμένο κωδικοποιητή. Από εσάς εξαρτάται εάν θέλετε να τον χρησιμοποιήσετε ως απλό κινητήρα συνεχούς ρεύματος ή αν θέλετε να χρησιμοποιήσετε τον κωδικοποιητή ή τέλος να χρησιμοποιήσετε τον κινητήρα και τον κωδικοποιητή μαζί.
Κινητήρας
Κινητήρας JGB37-520 DC με μηχανικό μειωτήρα στροφών και κωδικοποιητή.
Χρησιμοποιείται κυρίως σε αυτοκίνητα μεταβλητής ταχύτητας, σε αυτοκίνητα αυτοεξισορρόπησης (με δύο τροχούς), σε αγωνιστικά αυτοκίνητα, αυτοκίνητο παρακολούθησης, σε ρομπότ και σε άλλες σχετικες κατασκευές.
Ο κωδικοποιητής ταχύτητας λειτουργεί με τη χρήση φαινομένου Hall .
Καλωδίωση του κινητήρα:
1, κόκκινο: τροφοδοσία κινητήρα + (η εναλλαγή πολικότητας με το λευκό αντιστρέφει την κίνηση του κινητήρα)
2, μαύρο: τροφοδοσία κωδικοποιητή -
3, κίτρινο: γραμμή σήματος, (Α)
4, πράσινο: γραμμή σήματος, (Β)
5, μπλε: τροφοδοσία κωδικοποιητή +
6, λευκό: τροφοδοσία κινητήρα - (η εναλλαγή πολικότητας με το κόκκινο αντιστρέφει την κίνηση του κινητήρα)
Στην πρώτη μας κατασκευή θα χρησιμοποιήσουμε μόνο τον κωδικοποιητή του κινητήρα για να καταλάβουμε τη λειτουργία του. Όπως μπορείτε να δείτε στην εικόνα που ακολουθεί, τα καλώδια τροφοδοσίας του κινητήρα, που είναι τα Κόκκινο και Άσπρο δεν είναι συνδεδεμένα. Συνδεδεμένα είναι μόνο τα καλώδια του κωδικοποιητή. Εμείς θα περιστρέφουμε τον άξονα του κινητήρα με το χέρι και θα παρακολουθούμε τα σήματα που παράγονται.
Ένας κωδικοποιητής λειτουργεί με την παρατήρηση αλλαγών στο μαγνητικό πεδίο που δημιουργείται από έναν μαγνήτη συνδεδεμένο στον άξονα του κινητήρα. Εδώ θα βρείτε την αρχή της λειτουργίας του αισθητήρα που βασίζεται στο φαινόμενο HALL.
Καθώς ο κινητήρας περιστρέφεται οι έξοδοι του κωδικοποιητή θα ενεργοποιούνται περιοδικά. Όταν ο μαγνήτης περιστρέφεται δεξιόστροφα, η έξοδος "Α" θα ενεργοποιηθεί πρώτα και όταν περιστρέφεται αριστερόστροφα, από την άλλη πλευρά, η έξοδος "Β" θα ενεργοποιηθεί πρώτη. Με αυτόν τον τρόπο γνωρίζετε ακριβώς τη φορά που περιστρέφεται ο άξονας του κινητήρα. Αυτό μπορεί να είναι πολύ βολικό για τις περιπτώσεις όπου πρέπει να ελέγχουμε την κίνηση προς τα εμπρός ή προς τα πίσω σε κινητήρα συνεχούς ρεύματος.
Στο διάγραμμα που ακολουθεί φαίνεται η διαφορά φάσεις μεταξύ των εξόδων Α και Β του κωδικοποιητή. Αυτή τη διαφορά φάσης θα εκμεταλλευτούμε προγραμματιστικά για να ελέγξουμε την κίνηση του κινητήρα.
Στην εικόνα που ακολουθεί παρουσιάζεται η συνδεσμολογία για δύο όμοιους κινητήρες σε μία πλακέτα Arduino UNO. Στην πλακέτα αυτή θα συνδεθεί και άλλος εξοπλισμός αργότερα. Εμείς θα χρησιμοποιήσουμε στο παράδειγμα μας αυτό μόνο τον κωδικοποιητή από τον ένα κινητήρα.
Βλέπεται ότι υπάρχουν δύο σύνδεσμοι για κάθε κινητήρα, ένας για το Μοτερ Α και ένας για τον κωδικοποιητή Α. Εμείς θα χρησιμοποιήσουμε σε αυτό το παράδειγμα μόνο το σύνδεσμο Encoder A.
Σε αυτόν τον σύνδεσμο συνδέονται τέσσερα καλώδια. Τα δύο ακριανά είναι για την τροφοδοσία του κωδικοποιητή, GND και VCC. Τα δύο μεσαία συνδέονται το ένα στο pin D2 και το άλλο στο pin D10. Σημειώστε εδώ ότι τα pin D2 και D3 είναι τα μόνα που χρησιμοποιούνται για τη δημιουργία διακοπών (interrupts) στην πλακέτα Arduino UNO. Αυτό θα το συναντήσουμε όταν γράφουμε το πρόγραμμα.
Ας γράψουμε ένα πολύ απλό πρόγραμμα για να κατανοήσουμε πώς λειτουργεί ένας κωδικοποιητής και πώς να διαβάζουμε τις εξόδους του κωδικοποιητή.
Για να διαβάσουμε τον κωδικοποιητή, θα συνδέσουμε τα pin εξόδου του κωδικοποιητή με τους ακροδέκτες 2 και 10 του Arduino. Το pin 2 είναι interrupt pin. Τα καλώδια τροφοδοσίας του κωδικοποιητή θα συνδεθούν με τα 5V και το GND του Arduino.
//Author : Manolis Aristovoulidis
//Περιστρέφω το μοτέρ με το χέρι και μετράω και τυπώνω
// την ταχύτητα και την κατεύθυνση της κίνησης
//θετικοί αριθμοί συμβολίζουν κίνηση δεξιόστροφη,
//αρνητικοί αριθμοί συμβολίζουν αριστερόστροφη κίνηση
const byte encoder_pinA = 2; //A pin -> the interrupt pin 2
const byte encoder_pinB = 10; //B pin -> the digital pin 10
int pulses; //the number of the pulses
boolean Direction; //the rotation direction
void setup()
{
Serial.begin(57600); //Initialize the serial port
EncoderInit(); //Initialize the module
}
void loop()
{
Serial.print("Direction:");
if(Direction){
Serial.print("Forword ");
}else{
Serial.print("Backword ");
}
Serial.print("Pulses:");
Serial.println(pulses);
pulses = 0;
delay(100);
}
void EncoderInit()
{
Direction = true; //default -> Forward
pinMode(encoder_pinB,INPUT);
attachInterrupt(digitalPinToInterrupt(encoder_pinA), wheelSpeed, RISING );
}
void wheelSpeed()
{
int val = digitalRead(encoder_pinB);
if(val == LOW ){
Direction = false; //Reverse
pulses--;
}else{
Direction = true; //Forward
pulses++;
}
}
Στην παρακολούθηση της σειριακής θύρας παρατηρούμε τα παρακάτω αποτελέσματα.
Από εδώ μπορείτε να κατεβάσετε το πρόγραμμα για την κατασκευή
Direction:Forword Pulses:0
Direction:Forword Pulses:0
Direction:Forword Pulses:0
Direction:Forword Pulses:3
Direction:Forword Pulses:17
Direction:Forword Pulses:38
Direction:Forword Pulses:63
Direction:Forword Pulses:85
Direction:Forword Pulses:102
Direction:Forword Pulses:112
Direction:Forword Pulses:117
Direction:Forword Pulses:112
Direction:Forword Pulses:98
Direction:Forword Pulses:86
Direction:Forword Pulses:74
Direction:Forword Pulses:64
Direction:Forword Pulses:53
Direction:Forword Pulses:42
Direction:Forword Pulses:33
Direction:Forword Pulses:25
Direction:Forword Pulses:17
Direction:Forword Pulses:8
Direction:Forword Pulses:0
Direction:Backword Pulses:-3
Direction:Backword Pulses:-17
Direction:Backword Pulses:-39
Direction:Backword Pulses:-54
Direction:Backword Pulses:-67
Direction:Backword Pulses:-79
Direction:Backword Pulses:-88
Direction:Backword Pulses:-92
Direction:Backword Pulses:-97
Direction:Backword Pulses:-89
Direction:Backword Pulses:-77
Direction:Backword Pulses:-66
Direction:Backword Pulses:-56
Direction:Backword Pulses:-45
Direction:Backword Pulses:-35
Direction:Backword Pulses:-27
Direction:Backword Pulses:-19
Direction:Backword Pulses:-12
Direction:Backword Pulses:-6
Direction:Backword Pulses:0
Direction:Backword Pulses:0
Direction:Backword Pulses:0
Με την εκκίνηση του το πρόγραμμα συσχετίζει τη συνάρτηση wheelSpeed() με το interrupt που θα συμβαίνει στο pin 2.
Aυτό το interrupt θα συμβαίνει όποτε ο παλμός στο pin 2 γίνεται ανερχόμενος (από 0 στο 5V) οπότε θα εκτελείται η συνάρτηση wheelSpeed(). Στο pin 2 είναι συνδεμένη η γραμμή σήματος Α του κωδικοποιητή.
Το πρώτο πράγμα που κάνει η συνάρτηση wheelSpeed() είναι να διαβάσει την τιμή που έχει το pin 10 δηλαδή η γραμμή σήματος Β του κωδικοποιητή. Αν η τιμή της είναι 0 (LOW) σημαίνει ότι το σήμα Α προηγείται του Β, η κίνηση δηλαδή είναι προς τα εμπρός. Ταυτόχρονα αυξάνει κατά μία μονάδα την τιμή των παλμών.
Στην άλλη περίπτωση που το Β προηγείται του Α η μεταβλητή Direction γίνεται false και μειώνεται κατά μια μονάδα η τιμή των παλμών. Για το λόγο αυτό έχουμε αρνητικές τιμές για τους παλμούς όταν η κίνηση είναι ανάστροφη.
Ο βρόχος που εκτελεί το πρόγραμμα (δηλαδή η συνάρτηση loop()) κάθε 100 msec στέλνει στη σειριακή θύρα τις τιμές της κατεύθυνσης και των παλμών και μηδενίζει τους παλμούς.
Έτσι καθώς γυρίζουμε τον κινητήρα με το χέρι παράγονται οι τιμές που βλέπουμε στον παρακάτω πίνακα. Αυτές είναι στιγμιότυπα για την κατάσταση του κινητήρα ανά 100 msec.
Κινητήρας συνεχούς ρεύματος
Υπάρχουν διαφορετικοί τύποι από κινητήρες που χρησιμοποιούνται σε μικρά και μεσαίου μεγέθους έργα ρομποτικής. Αυτοί μπορούν να καταταγούν γενικά στις κατηγορίες
- Βηματικοί κινητήρες
- Servo κινητήρες
- DC κινητήρες
Βρίσκονται σε μεγάλη ποικιλία από μεγέθη και δυνατότητες και αντίστοιχα χρησιμοποιούνται σε διαφορετικού μεγέθους εφαρμογές.
Οι βηματικοί κινητήρες και οι σερβοκινητήρες είναι σχεδιασμένοι με τέτοιο τρόπο ώστε να μπορούμε να ελέγχουμε τη θέση τους. Μπορούμε να ελέγξουμε τα βήματα προς τα εμπρός και προς τα πίσω.
Οι σερβοκινητήρες μπορούν εν γένει να μετακινηθούν από 0 έως 180 μοίρες. Επομένως μπορείτε να μετακινήσετε τον κινητήρα σας σε οποιαδήποτε θέση μεταξύ 0 και 180. Όμοια, στους βηματικούς κινητήρες, μπορείτε να ελέγξετε τα βήματα με ακρίβεια. Αυτός είναι ο λόγος που οι βηματικοί κινητήρες χρησιμοποιούνται σε μηχανές CNC, σε τρισδιάστατους εκτυπωτές κ.λ.π.
Εδώ θα μας απασχολήσουν οι κινητήρες συνεχούς ρεύματος (DC motors). Οι κινητήρες συνεχούς ρεύματος χρησιμοποιούνται συχνά σε εφαρμογές ρομποτικής και είναι αρκετά διαφορετικοί από τους βηματικούς (Stepper Motors) και τους σερβοκινητήρες.
Αυτοί οι τρεις τύποι κινητήρων λοιπόν έχουν διαφορετική κατασκευή και διαφορετικό προορισμό χρήσης.
Όταν ένας κινητήρας συνεχούς ρεύματος ενεργοποιείται, αρχίζει αμέσως να περιστρέφεται, και περιστρέφεται συνεχώς. Δεν μπορείτε να ελέγξετε ακριβώς τη θέση του χωρίς να χρησιμοποιήσετε κάποια συγκεκριμένη τεχνική. Και πάλι δεν μπορείτε να ελέγξετε 100% τη θέση του σε έναν κινητήρα συνεχούς ρεύματος όπως γίνετε με το Stepper motor και το Servo. Αν όμως προσθέσετε έναν κωδικοποιητή στον κινητήρα συνεχούς τότε πραγματικά αλλάζει όλο το παιχνίδι. Με την προσθήκη κωδικοποιητή, μπορείτε να παρακολουθείτε τις στροφές του κινητήρα, την απόσταση που έχει διανύσει και με αυτόν τον τρόπο μπορείτε να δημιουργήσετε ένα ωραίο σύστημα ανατροφοδότησης που μπορεί να χρησιμοποιηθεί για τον έλεγχο του κινητήρα DC. Στη συνέχεια, μπορείτε να σταματήσετε τον κινητήρα συνεχούς ρεύματος στη θέση όπου θέλετε να σταματήσει. Σημειώστε εδώ ότι η αναστροφή της πολικότητας στην τροφοδοσία του κινητήρα τον αναγκάζει να κινηθεί προς την αντίθετη κατεύθυνση.
H χρήση ενός κωδικοποιητή για τον έλεγχος του κινητήρα DC δεν είναι μια τόσο απλή υπόθεση. Δεν μπορείτε έτσι απλά προσθέτοντας έναν κωδικοποιητή στον κινητήρα συνεχούς ρεύματος να αρχίσετε να τον ελέγχετε. Για να χρησιμοποιήσετε έναν κωδικοποιητή θα χρειαστείτε έναν ελεγκτή, κι ένα πρόγραμμα που θα καθοδηγεί τον ελεγκτή. Ο ελεγκτής θα διαβάζει τον κωδικοποιητή και στη συνέχεια θα ελέγχει αναλόγως τον κινητήρα DC σύμφωνα με τις προκαθορισμένες οδηγίες που έχει γράψει ο προγραμματιστής.
Ο έλεγχος της ταχύτητας περιστροφής του κινητήρα DC γίνεται συνήθως με την τροφοδότηση του με μια PWM (Pulse-width modulation) κυματομορφή. Μία PWM κυματομορφή, όπως φαίνεται στο επόμενο σχήμα, στην πραγματικότητα αποτελεί μία περιοδική κυματομορφή η οποία έχει δύο τμήματα. Το τμήμα ΟΝ στο οποίο η κυματομορφή έχει την μέγιστη τιμή της και το τμήμα OFF στο οποίο έχει την τιμή μηδέν. To τμήμα ΟΝ ονομάζεται Duty Cycle και μετριέται είτε σε μονάδες χρόνου (ms, us κλπ) είτε σε ποσοστό (%) επί της περιόδου (Period).
Εφαρμόζοντας μία PWM κυματομορφή στην τροφοδοσία ενός φορτίου επιτυγχάνουμε να ελέγξουμε το ποσοστό της ισχύος που πέφτει πάνω στο φορτίο. Για την περίπτωση που το φορτίο είναι ένας κινητήρας αυτό συνεπάγεται έλεγχος στροφών του κινητήρα. Στο παρακάτω σχήμα βλέπετε μία τέτοια συνδεσμολογία τροφοδοσίας DC κινητήρα.
Έλεγχος κινητήρα συνεχούς ρεύματος με κωδικοποιητή:
Οι αρχάριοι στον προγραμματισμό μικροελεγκτών είναι συνήθως πιο άνετοι με τη χρήση του Arduino Uno ή του Arduino mega ή του Arduino Nano. Για αυτό το λόγο στις κατασκευές – παραδείγματα θα χρησιμοποιήσω τον Arduino Uno. Τα ίδια προγράμματα μπορείτε να δοκιμάσετε και στο Arduino Nano και στο Arduino Mega.
Για να ξεκινήσετε, θα χρειαστείτε
- ένα Arduino Uno,
- ένα τροφοδοτικό συνεχούς ρεύματος για τον κινητήρα,
- έναν κοντρόλερ για την οδήγηση του κινητήρα,
- και έναν κινητήρα συνεχούς ρεύματος με προσαρμοσμένο στην κατασκευή του έναν κωδικοποιητή.
Τα βήματα που θα ακολουθήσουμε θα είναι τα εξής.
- Πρώτα θα εξοικειωθούμε με τη χρήση του κωδικοποιητή δίνοντας κίνηση στον κινητήρα με το χέρι.
- Στη συνέχεια θα τροφοδοτήσουμε τον κινητήρα με τη χρήση ενός κοντρόλερ για να ελέγχουμε την φορά της κίνησης και την ταχύτητα του.
Κινητήρας συνεχούς ρεύματος με κωδικοποιητή (Κινητήρας DC - Encoder)
Τι είναι Servo
Servo είναι ένας γενικός όρος για ένα σύστημα ελέγχου κλειστού βρόχου.
Ένα σύστημα κλειστού βρόχου χρησιμοποιεί ένα σήμα ανάδρασης για να ρυθμίσει την ταχύτητα και την κατεύθυνση ενός κινητήρα και για να επιτύχει το επιθυμητό αποτέλεσμα, για παράδειγμα την τοποθέτηση του κινητήρα σε συγκεκριμένη θέση.
Στην αγορά υπάρχουν σερβοκινητήρες πολλών ειδών και μεγεθών, εδώ αναφερόμαστε σε αυτούς που χρησιμοποιούνται στο μοντελισμό και στην ρομποτική. Αυτοί οι σερβοκινητήρες λειτουργούν επίσης με την παραπάνω αρχή. Περιέχουν έναν μικρό κινητήρα DC συνδεδεμένο στον άξονα εξόδου μέσω των γραναζιών, ένα μηχανικό μειωτήρα δηλαδή, ώστε να εξασφαλίζει μεγάλη ροπή με λίγες στροφές στο σερβοκινητήρα. Ο άξονας εξόδου κινεί έναν βραχίονα που είναι συνδεδεμένος με ένα ποτενσιόμετρο (pot) το οποίο είναι τμήμα από το ηλεκτρονικό κύκλωμα ελέγχου (servo driver). Στο παρακάτω σχήμα φαίνεται το λειτουργικό διάγραμμα ενός σερβοκινητήρα.
Σχηματικό διάγραμμα σερβοκινητήρα
Το ποτενσιόμετρο παρέχει την ανάδραση θέσης στη μονάδα ελέγχου όπου η τρέχουσα θέση του κινητήρα συγκρίνεται με τη θέση στόχου.
Σύμφωνα με το σφάλμα, η μονάδα ελέγχου διορθώνει την πραγματική θέση του κινητήρα έτσι ώστε να ταιριάζει με τη θέση - στόχο.
Εσωτερικό σερβοκινητήρα
Πώς λειτουργεί ο σερβοκινητήρας
Στο σχήμα διακρίνετε ένα σερβοκινητήρα. Αυτός συνδέεται με τρεις αγωγούς. Τη γείωση GND, την τάση 5V που είναι συνήθως 5 έως 7 βολτ, και το control που είναι το σήμα ελέγχου.
Σύνδεση σερβοκινητήρα
Μπορείτε να ελέγξετε τον σερβοκινητήρα στέλνοντας μια σειρά παλμών στη γραμμή ελέγχου. Ένας συμβατικός αναλογικός σερβοκινητήρας, όπως π.χ. ο MG995, αναμένει να λαμβάνει παλμό περίπου κάθε 20 χιλιοστά του δευτερολέπτου (δηλαδή το σήμα πρέπει να έχει συχνότητα 50Hz).
Το μήκος του παλμού (Duty Cycle) καθορίζει τη θέση του σερβοκινητήρα. Η παρακάτω εικόνα δίνει τη θέση του κινητήρα σε σχέση με το σήμα ελέγχου.
Οδήγηση σερβοκινητήρα
Εφαρμογή
Ήρθε η στιγμή για να δούμε πως συνδέεται και πώς λειτουργεί ένας σερβοκινητήρας.
Θα χρειαστούν κάποια υλικά:
1. Ένα σερβοκινητήρας π.χ. MG995
Σερβοκινητήρας MG995
2. Μια πλακέτα Arduino UNO ή συμβατό
Arduino UNO
3. Μια πλακέτα Arduino UNO κενή επάνω στην οποία θα γίνει το κύκλωμα των συνδέσεων και στη συνέχεια θα κουμπώσει στην πλακέτα του Arduino.
Arduino Sield
4. Ένα τροφοδοτικό 5-7V DC για να τροφοδοτήσει το σερβοκινητήρα.
5. Ένα ποτενσιόμετρο 10Κ
Θα χρειαστούν επίσης κάποια εργαλεία (κολλητήρι κοφτάκι κλπ), μερικά μέτρα καλώδιο λεπτό και λίγη εμπειρία κατασκευών.
Για να προγραμματίσετε το σύστημα και να λειτουργήσει θα πρέπει να έχετε εγκατεστημένο το Ardouino IDE και μικρή εμπειρία μαζί του. Τόσο το υλικό όσο και το λογισμικό είναι OPEN, βλέπε
https://el.wikipedia.org/wiki/Υλισμικό_ανοικτής_πηγής
https://el.wikipedia.org/wiki/Λογισμικό_ανοικτού_κώδικα
Κατασκευή
Στην κενή πλακέτα Arduino UNO κατασκευάζω το κύκλωμα σύνδεσης των υλικών. Ένα παράδειγμα συνδεσμολογίας βλέπετε στο https://www.arduino.cc/en/Tutorial/Knob στο οποίο έχω κάνει τις απαραίτητες τροποποιήσεις.
Στη φωτογραφία που ακολουθεί βλέπετε τελειωμένη την κατασκευή. Εδώ χρησιμοποιώ δύο σερβοκινητήρες και δύο ποτενσιόμετρα, γιατί η κατασκευή έχει και μελλοντική χρήση. Οι σερβοκινητήρες είναι τοποθετημένοι έτσι ώστε οι κινήσεις να γίνονται σε δύο κάθετα μεταξύ τους επίπεδα. Αυτή τη λεπτομέρεια θα την χρησιμοποιήσουμε σε επόμενη κατασκευή μας.
Στο τέλος του άρθρου σας έχω ένα βίντεο όπου βλέπετε την κατασκευή σε λειτουργία.
Το κάθε ποτενσιόμετρο έχει τρία pin. Τα δύο ακραία συνδέονται στη γείωση GND και στα 5V αντίστοιχα. Ανάλογα με τη θέση περιστροφής του ποτενσιόμετρου το μεσαίο θα έχει δυναμικό μεταξύ 0 και 5V. Το μεσαίο pin του ποτενσιόμετρου συνδέεται στην αναλογική είσοδο Α0 του Arduino. Οι τιμές που θα διαβάζει το πρόγραμμα για την είσοδο Α0 θα είναι μεταξύ 0 και 1023.
Ο σερβοκινητήρας χρειάζεται συνήθως περισσότερο ρεύμα από αυτό μπορεί να δώσει η τροφοδοσία του Arduino από μια USB θύρα. Για το λόγο αυτό χρησιμοποιούμε το πρόσθετο τροφοδοτικό. Η γείωση αυτού του τροφοδοτικού θα συνδεθεί με το GND του Arduino. Καλό θα είναι μεταξύ της γείωσης και του θετικού του τροφοδοτικού να συνδεθεί ένας πυκνωτής 1000μF, που θα εξασφαλίζει τη μεγάλη απαίτηση σε ρεύμα κατά την εκκίνηση του κινητήρα.
Οι σερβοκινητήρες έχουν τρία καλώδια: ρεύμα, γείωση και σήμα. Το καλώδιο τροφοδοσίας είναι συνήθως κόκκινο και θα πρέπει να συνδεθεί στο 5-7V του τροφοδοτικού. Το καλώδιο γείωσης είναι συνήθως μαύρο ή καφέ και θα πρέπει να συνδεθεί σε μια ακίδα γείωσης στην πλακέτα Arduino. Η ακίδα σήματος είναι συνήθως κίτρινη, πορτοκαλί ή λευκή και θα πρέπει να συνδεθεί με μια ψηφιακή ακίδα στην πλακέτα Arduino. Στη δική μας κατασκευή θα συνδεθεί στο ψηφιακό pin 4.
Προγραμματισμός
Το πρόγραμμα που σας παρουσιάζω κινεί δύο σερβοκινητήρες με τη χρήση δύο ποτενσιόμετρων όπως δείχνει και το video. Η κατασκευή έγινε με δύο μηχανισμούς σερβοκινητήρων γιατί θα χρησιμοποιηθεί και σε επόμενο πείραμα.
Το Arduino UNO δίνει τη δυνατότητα για παραγωγή PWM σήματος στα pin 3,5,6,9,10 και 11. Εμείς χρησιμοποιούμε τη βιβλιοθήκη Servo.h για να απλοποιήσουμε τον προγραμματισμό για την παραγωγή του PWM σήματος, επίσης με τον τρόπο που χειρίζεται αυτή η βιβλιοθήκη την παραγωγή PWM σήματος μπορούμε χρησιμοποιήσουμε όλα τα ψηφιακά pin για την δημιουργία PWM σήματος.
/*
έλεγχος της θέσης δύο σερβοκινητήρων με τη χρήση δύο μεταβλητών αντιστάσεων – ποτενσιομέτρων
Μανώλης Αριστοβουλίδης 10/2021
*/
#include <Servo.h>
Servo servo1; // δημιουργία ενός servo object για τον έλεγχο του servo
Servo servo2;
int potpin1 = A0; // αναλογικό pin για τη σύνδεση ποτενσιομέτρου
int potpin2 = A1; // αναλογικό pin για τη σύνδεση ποτενσιομέτρου
int val1; // μεταβλητή για την ανάγνωση της τιμής του αναλογικό pin
int val2; // μεταβλητή για την ανάγνωση της τιμής του αναλογικό pin
void setup() {
servo1.attach(4); // κάνει προσάρτηση του servo στο pin 4 του servo object
servo2.attach(5); //κάνει προσάρτηση του servo στο pin 5 του servo object
Serial.begin(9600); //αρχικοποιεί τη σειριακή επικοινωνία
}
void loop() {
val1 = analogRead(potpin1); // διαβάζει την αναλογική τιμή (τιμές μεταξύ 0 και 1023)
val2 = analogRead(potpin2); // διαβάζει την αναλογική τιμή (τιμές μεταξύ 0 και 1023)
val1 = map(val1, 0, 1023, 0, 180); // μεταροπή σε κλίμακα για το servo (τιμές μεταξύ 0 και 180)
val2 = map(val2, 0, 1023, 0, 180); // μεταροπή σε κλίμακα για το servo (τιμές μεταξύ 0 και 180)
servo1.write(val1); // ρυθμίζει τη θέση του servo στην τιμή της κλίμακας
servo2.write(val2); // ρυθμίζει τη θέση του servo στην τιμή της κλίμακας
Serial.print("val1 : ");
Serial.print(val1);
Serial.print(" - val2 : ");
Serial.println(val2);
delay(20); // περιμένει για την ολοκλήρωση της κίνησης του servo
}
Τον κώδικα μπορείτε να τον κατεβάσετε από εδώ http://www.avlos.gr/index.php/el/lipsis/download/16-servo-knob
Στο video που ακολουθεί βλέπετε το μηχανισμό σε λειτουργία https://youtu.be/BCxv9VGqhQk







