Στο προηγούμενο άρθρο μας είδαμε τα υλικά που θα χρειαστούμε για την κατασκευή μας καθώς και το κύκλωμα μας σχεδιασμένο σε breadboard. Στο σημερινό άρθρο θα εξηγήσουμε το κομμάτι του κώδικα αναλυτικά ώστε να μπορούμε να καταλάβουμε τι κάνει κάθε εντολή και όχι απλά να το φορτώσουμε στο arduino και να πούμε "Έτοιμο!".
Δήλωση μεταβλητών & σταθερών
Δήλωση σταθερών για τους κινητήρες και το L293
Το πίσω μοτέρ (κίνησης) θα το ονομάσουμε motorA και το μπροστά (κατεύθυνσης) motorB. Και τα δύο μοτέρ συνδέονται με το L293 και μέσω αυτού με το Arduino uno με τα pins 5, 6, 9 και 10. Το καθένα απ' αυτά έχει δυο καλώδια εκ των οποίων το ένα έχει θετική πολικότητα, όπως είχαμε ορίσει στο προηγούμενο άρθρο. Άρα το motorA1 και motorB1 δείχνουν το θετικό άκρο και το motorA2 kai
motorB2 το αρνητικό άκρο των DC μοτέρ.
const int motorA1 = 5;
const int motorA2 = 6;
const int motorB1 = 10;
const int motorB2 = 9;
Φωτισμός led (προαιρετικό)
Όπως στο σχηματικό, το θετικό άκρο των leds καταλήγει στο Arduino pin 12.
const int lights = 12;
Ήχος κόρνας (προαιρετικό)
Όπως στο σχηματικό, το θετικό άκρο του ηχείου καταλήγει στο Arduino pin 3.
const int buzzer = 3;
Bluetooth state pin
Το bluetooth module HC-06 JY-MCU έχει ένα led πάνω του το οποίο συνδέεται με τον ακροδέκτη state. Αν παρατηρήσετε, όταν το bluetooth είναι σε σύνδεση, το led είναι μόνιμα αναμμένο, ενώ σε αντίθετη περίπτωση αναβοσβήνει. Αυτό θα μας βοηθήσει στο να καταλάβουμε αν το όχημα βρίσκεται εκτός εμβέλειας. To pin αυτό είναι συνδεδεμένο με το Arduino pin2.
const int BTState = 2;
Calculate Battery Level
Το κομμάτι χρησιμεύει στο να αποστέλλετε το ποσοστό της μπαταρίας στην εφαρμογή μας.
Στην σταθερά maxBattery βάλτε την συνολική τάση της μπαταρίας σας (π.χ. 8volt). H perVolt αποθηκεύει το ποσοστό, η voltage την τάση, και η level την τιμή που αποστέλλετε στην εφαρμογή μας.
const float maxBattery = 8.0;
int perVolt;
float voltage = 0.0;
int level;
Καθυστέρηση
Την καθυστέρηση χωρίς την χρήση της delay() την έχουμε συναντήσει σε προηγούμενο μάθημα και γι' αυτό δεν θα αναφερθούμε περισσότερο σε αυτή. Το κομμάτι αυτό θα βοηθήσει στο να αποστέλλεται η τιμή level (της μπαταρίας) κάθε 10 δευτερόλεπτα.
long previousMillis = -1000*10;
long interval = 1000*10;
unsigned long currentMillis;
Χρήσιμες μεταβλητές
Την i και j θα την χρησιμοποιήσουμε για να διατηρήσουμε μια κατάσταση σταθερή (θα εξηγήσουμε παρακάτω), την state για την αποθήκευση των εντολών που στέλνει η εφαρμογή και την vSpeed για την ρύθμιση της ταχύτητας, την οποία θέτουμε να είναι αρχικά ίση με 200 (PWM 0-255)
int i=0;
int j=0;
int state;
int vSpeed=200;
Το κομμάτι της void setup()
Με την pinMode όπως έχουμε πει στα εισαγωγικά μαθήματα μας, δηλώνουμε ποία pins του Arduino είναι έξοδοι και ποία είναι είσοδοι. Έτσι έχουμε το παρακάτω κομμάτι κώδικα:
pinMode(motorA1, OUTPUT);
pinMode(motorA2, OUTPUT);
pinMode(motorB1, OUTPUT);
pinMode(motorB2, OUTPUT);
pinMode(lights, OUTPUT);
pinMode(BTState, INPUT);
Το κομμάτι της void loop() - Κύριο πρόγραμμα
Το κομμάτι του κώδικα που υπάρχει στην void loop αποτελεί το βασικό μας πρόγραμμα, χρησιμοποιώντας φυσικά και όλες τις παραπάνω πληροφορίες. Με την χρήση της δομής ελέγχου if, ανάλογα με την τιμή που θα παίρνει η μεταβλητή "state", θα εκτελούνται και οι αντίστοιχες λειτουργίες.
Αν το όχημα βρεθεί εκτός εμβέλειας τότε σταματάει, κάνοντας την τιμή της "state" ίση με 'S':
if(digitalRead(BTState)==LOW) { state='S'; }
Αν η τιμή της "state" είναι από 0 έως 4 τότε ρυθμίζει την ταχύτητα ανάλογα:
if (state == '0'){
vSpeed=0;}
else if (state == '1'){
vSpeed=100;}
else if (state == '2'){
vSpeed=180;}
else if (state == '3'){
vSpeed=200;}
else if (state == '4'){
vSpeed=255;}
Κίνηση μπροστά
Αν η τιμή της "state" είναι ίση με 'F' τότε το όχημα θα πάει μπροστά.
(ομοίως και για τα υπόλοιπα)
if (state == 'F') {
analogWrite(motorA1, vSpeed); analogWrite(motorA2, 0);
analogWrite(motorB1, 0); analogWrite(motorB2, 0);
}
Κίνηση μπροστά αριστερά
else if (state == 'G') {
analogWrite(motorA1, vSpeed); analogWrite(motorA2, 0);
analogWrite(motorB1, 200); analogWrite(motorB2, 0);
}
Κίνηση μπροστά δεξιά
else if (state == 'I') {
analogWrite(motorA1, vSpeed); analogWrite(motorA2, 0);
analogWrite(motorB1, 0); analogWrite(motorB2, 200);
}
Κίνηση πίσω
else if (state == 'B') {
analogWrite(motorA1, 0); analogWrite(motorA2, vSpeed);
analogWrite(motorB1, 0); analogWrite(motorB2, 0);
}
Κίνηση πίσω αριστερά
else if (state == 'H') {
analogWrite(motorA1, 0); analogWrite(motorA2, vSpeed);
analogWrite(motorB1, 200); analogWrite(motorB2, 0);
}
Κίνηση πίσω δεξιά
else if (state == 'J') {
analogWrite(motorA1, 0); analogWrite(motorA2, vSpeed);
analogWrite(motorB1, 0); analogWrite(motorB2, 200);
}
Όχημα σταματημένο
else if (state == 'S'){
analogWrite(motorA1, 0); analogWrite(motorA2, 0);
analogWrite(motorB1, 0); analogWrite(motorB2, 0);
}
Ο κώδικας για τα φώτα και την κόρνα είναι παρόμοιος. Ο κώδικας για την μπαταρία διαβάζει την τάση, την μετατρέπει σε ποσοστό και ανάλογα με αυτό στέλνει στην εφαρμογή μας έναν αριθμό απ' το 0 μέχρι το 5, δείχνοντας έτσι το αντίστοιχο επίπεδο της. Την αποστολή αυτή την κάνει κάθε δέκα δευτερόλεπτα.
Δήλωση σταθερών για τους κινητήρες και το L293
Το πίσω μοτέρ (κίνησης) θα το ονομάσουμε motorA και το μπροστά (κατεύθυνσης) motorB. Και τα δύο μοτέρ συνδέονται με το L293 και μέσω αυτού με το Arduino uno με τα pins 5, 6, 9 και 10. Το καθένα απ' αυτά έχει δυο καλώδια εκ των οποίων το ένα έχει θετική πολικότητα, όπως είχαμε ορίσει στο προηγούμενο άρθρο. Άρα το motorA1 και motorB1 δείχνουν το θετικό άκρο και το motorA2 kai
motorB2 το αρνητικό άκρο των DC μοτέρ.
const int motorA1 = 5;
const int motorA2 = 6;
const int motorB1 = 10;
const int motorB2 = 9;
Φωτισμός led (προαιρετικό)
Όπως στο σχηματικό, το θετικό άκρο των leds καταλήγει στο Arduino pin 12.
const int lights = 12;
Ήχος κόρνας (προαιρετικό)
Όπως στο σχηματικό, το θετικό άκρο του ηχείου καταλήγει στο Arduino pin 3.
const int buzzer = 3;
Bluetooth state pin
Το bluetooth module HC-06 JY-MCU έχει ένα led πάνω του το οποίο συνδέεται με τον ακροδέκτη state. Αν παρατηρήσετε, όταν το bluetooth είναι σε σύνδεση, το led είναι μόνιμα αναμμένο, ενώ σε αντίθετη περίπτωση αναβοσβήνει. Αυτό θα μας βοηθήσει στο να καταλάβουμε αν το όχημα βρίσκεται εκτός εμβέλειας. To pin αυτό είναι συνδεδεμένο με το Arduino pin2.
const int BTState = 2;
Calculate Battery Level
Το κομμάτι χρησιμεύει στο να αποστέλλετε το ποσοστό της μπαταρίας στην εφαρμογή μας.
Στην σταθερά maxBattery βάλτε την συνολική τάση της μπαταρίας σας (π.χ. 8volt). H perVolt αποθηκεύει το ποσοστό, η voltage την τάση, και η level την τιμή που αποστέλλετε στην εφαρμογή μας.
const float maxBattery = 8.0;
int perVolt;
float voltage = 0.0;
int level;
Καθυστέρηση
Την καθυστέρηση χωρίς την χρήση της delay() την έχουμε συναντήσει σε προηγούμενο μάθημα και γι' αυτό δεν θα αναφερθούμε περισσότερο σε αυτή. Το κομμάτι αυτό θα βοηθήσει στο να αποστέλλεται η τιμή level (της μπαταρίας) κάθε 10 δευτερόλεπτα.
long previousMillis = -1000*10;
long interval = 1000*10;
unsigned long currentMillis;
Χρήσιμες μεταβλητές
Την i και j θα την χρησιμοποιήσουμε για να διατηρήσουμε μια κατάσταση σταθερή (θα εξηγήσουμε παρακάτω), την state για την αποθήκευση των εντολών που στέλνει η εφαρμογή και την vSpeed για την ρύθμιση της ταχύτητας, την οποία θέτουμε να είναι αρχικά ίση με 200 (PWM 0-255)
int i=0;
int j=0;
int state;
int vSpeed=200;
Το κομμάτι της void setup()
Με την pinMode όπως έχουμε πει στα εισαγωγικά μαθήματα μας, δηλώνουμε ποία pins του Arduino είναι έξοδοι και ποία είναι είσοδοι. Έτσι έχουμε το παρακάτω κομμάτι κώδικα:
pinMode(motorA1, OUTPUT);
pinMode(motorA2, OUTPUT);
pinMode(motorB1, OUTPUT);
pinMode(motorB2, OUTPUT);
pinMode(lights, OUTPUT);
pinMode(BTState, INPUT);
Το κομμάτι της void loop() - Κύριο πρόγραμμα
Το κομμάτι του κώδικα που υπάρχει στην void loop αποτελεί το βασικό μας πρόγραμμα, χρησιμοποιώντας φυσικά και όλες τις παραπάνω πληροφορίες. Με την χρήση της δομής ελέγχου if, ανάλογα με την τιμή που θα παίρνει η μεταβλητή "state", θα εκτελούνται και οι αντίστοιχες λειτουργίες.
Αν το όχημα βρεθεί εκτός εμβέλειας τότε σταματάει, κάνοντας την τιμή της "state" ίση με 'S':
if(digitalRead(BTState)==LOW) { state='S'; }
Αν η τιμή της "state" είναι από 0 έως 4 τότε ρυθμίζει την ταχύτητα ανάλογα:
if (state == '0'){
vSpeed=0;}
else if (state == '1'){
vSpeed=100;}
else if (state == '2'){
vSpeed=180;}
else if (state == '3'){
vSpeed=200;}
else if (state == '4'){
vSpeed=255;}
Κίνηση μπροστά
Αν η τιμή της "state" είναι ίση με 'F' τότε το όχημα θα πάει μπροστά.
(ομοίως και για τα υπόλοιπα)
if (state == 'F') {
analogWrite(motorA1, vSpeed); analogWrite(motorA2, 0);
analogWrite(motorB1, 0); analogWrite(motorB2, 0);
}
Κίνηση μπροστά αριστερά
else if (state == 'G') {
analogWrite(motorA1, vSpeed); analogWrite(motorA2, 0);
analogWrite(motorB1, 200); analogWrite(motorB2, 0);
}
Κίνηση μπροστά δεξιά
else if (state == 'I') {
analogWrite(motorA1, vSpeed); analogWrite(motorA2, 0);
analogWrite(motorB1, 0); analogWrite(motorB2, 200);
}
Κίνηση πίσω
else if (state == 'B') {
analogWrite(motorA1, 0); analogWrite(motorA2, vSpeed);
analogWrite(motorB1, 0); analogWrite(motorB2, 0);
}
Κίνηση πίσω αριστερά
else if (state == 'H') {
analogWrite(motorA1, 0); analogWrite(motorA2, vSpeed);
analogWrite(motorB1, 200); analogWrite(motorB2, 0);
}
Κίνηση πίσω δεξιά
else if (state == 'J') {
analogWrite(motorA1, 0); analogWrite(motorA2, vSpeed);
analogWrite(motorB1, 0); analogWrite(motorB2, 200);
}
Όχημα σταματημένο
else if (state == 'S'){
analogWrite(motorA1, 0); analogWrite(motorA2, 0);
analogWrite(motorB1, 0); analogWrite(motorB2, 0);
}
Ο κώδικας για τα φώτα και την κόρνα είναι παρόμοιος. Ο κώδικας για την μπαταρία διαβάζει την τάση, την μετατρέπει σε ποσοστό και ανάλογα με αυτό στέλνει στην εφαρμογή μας έναν αριθμό απ' το 0 μέχρι το 5, δείχνοντας έτσι το αντίστοιχο επίπεδο της. Την αποστολή αυτή την κάνει κάθε δέκα δευτερόλεπτα.