3. Ψηφιακή είσοδος και εξοδος

Μπορούμε να υλοποιήσουμε ένα ηλεκτρονικό κύκλωμα με τη χρήση του breadboard. Το breadboard είναι μια πλαστική βάση, με υποδοχές συνδεμένες κάθετα, ενώ επίσης οι οριζόντιες πλευρικές υποδοχές είναι συνδεμένες μεταξύ τους. Τα breadboard παράγονται σε διάφορα μεγέθη, σχήματα και χρώματα, όπως φαίνεται στην ακόλουθη εικόνα:

Παράδειγμα:

Σε αυτή την εργασία θα επιδείξουμε το κυματοειδές αναβόσβημα LEDs, τα οποία είναι σε σειρά συνδεμένα με αντιστάσεις, και αυτές με τα πιν του Arduino. Θα χρησιμοποιήσουμε πέντε LEDs για να προσομοιώσουμε το εφέ που υπάρχει στο μπροστινό μέρος του αυτοκινήτου της δημοφιλής TV σειράς knight rider.

Το  φυσικό διάγραμμα του κυκλώματος, είναι όπως φαίνεται στο επόμενο σχήμα:

Ο κώδικας: Για να πετύχουμε το εφέ εισάγουμε τον ακόλουθο κώδικα στο IDE

// Project 1 – creating a Blinking LED wave
void setup(){
   pinMode(2, OUTPUT);  // LED 1 control pinisset up as an    output
   pinMode(3, OUTPUT);     // same for LED 2 to LED 5
   pinMode(4, OUTPUT);
   pinMode(5, OUTPUT);
   pinMode(6, OUTPUT);
}
void loop()
{
   digitalWrite(2, HIGH);   // Turn LED 1 on
   delay(500);                      // wait half a second
   digitalWrite(2, LOW);      // Turn LED 1 off
   digitalWrite(3, HIGH);     // and repeat for LED 2 to 5
   delay(500);
   digitalWrite(3, LOW);
   digitalWrite(4, HIGH);
   delay(500);
   digitalWrite(4, LOW);
   digitalWrite(5, HIGH);
   delay(500);
   digitalWrite(5, LOW);
   digitalWrite(6, HIGH);
   delay(500);
   digitalWrite(6, LOW);
   digitalWrite(5, HIGH);
   delay(500);
   digitalWrite(5, LOW);
   digitalWrite(4, HIGH);
   delay(500);
   digitalWrite(4, LOW);
   digitalWrite(3, HIGH);
   delay(500);
   digitalWrite(3, LOW);
// the loop will now loop around and start from the top again
}

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

Για να στείλουμε τάση σε ένα ψηφιακό πίν π.χ. το πιν 2, πρέπει πρώτα να το δηλώσουμε σαν OUTPUT με την ακόλουθη εντολή:

pinMode(2, OUTPUT);

Έτσι στην συνάρτηση void setup(), με την εντολή π.χ pinMode(2, OUTPUT), τα ψηφιακά Ι/Ο πινς τίθενται σαν έξοδοι, διότι θέλουμε αυτά να στέλνουν ρεύμα στα επιθυμητά LEDs.

Ορίζουμε πότε ένα LED ανάψει ή σβήσει χρησιμοποιώντας την συνάρτηση digitalWrite() μέσα στην συνάρτηση void loop() του κώδικα.

digitalWrite(2, LOW);  // (turn off) the pin 2 as 0V   
digitalWrite(3, HIGH); // (turn on) the pin 3 as 5V   

Για παράδειγμα όταν χρησιμοποιούμε την συνάρτηση (εντολή) digitalWrite(2, HIGH), μια τάση 5V προκαλεί τη ροή του ρεύματος από το ψηφιακό πιν 2 και δια μέσου από  του LED στην αντίσταση περιορισμού ρεύματος και στη συνέχεια στη γείωση (GND) του Arduino και έτσι το αντίστοιχο LED ανάβει. Όταν χρησιμοποιήσουμε την συνάρτηση digitalWrite(3, LOW) η  έξοδος του πιν 3 γίνεται 0V και έτσι η ροή του ρεύματος σταματά και το LED σβήνει.

Για να δούμε πως δουλεύει ο κώδικας, συνδέουμε το Arduino board (εδώ χρησιμοποιούμε το Arduino Uno)  με το PC και στο Arduino IDE επιλέγουμε την σειριακή πόρτα στην οποία είναι συνδεμένο το Arduino, καθώς επίσης επιλέγουμε το board του Arduino που χρησιμοποιούμε. Ανεβάζουμε τον κώδικα στο IDE και τον τρέχουμε. Αν δεν υπάρχουν λάθη, μετά από ένα ή δύο δευτερόλεπτα τα LEDs θα ανάβουν και θα σβήνουν από αριστερά προς δεξιά και ξανά πίσω.

Χρησιμοποιώντας μεταβλητές:

Στα προγράμματα ηλεκτρονικών υπολογιστών χρησιμοποιούμε μεταβλητές για την αποθήκευση δεδομένων. Για παράδειγμα στον κώδικα του προηγούμενου προγράμματος χρησιμοποιούμε τη συνάρτηση delay(500); για να κρατήσουμε τα LEDs αναμμένα για ορισμένο χρονικό διάστημα. Το πρόβλημα με αυτόν τον κώδικα είναι ότι δεν είναι ευέλικτος. Εάν θέλουμε να κάνουμε μια αλλαγή στο χρόνο καθυστέρησης, θα πρέπει να αλλάξουμε την χρονική καθυστέρηση σε κάθε συνάρτηση χειροκίνητα. Για να διευθετήσουμε αυτό το πρόβλημα, θα δημιουργήσουμε μια μεταβλητή που θα αντιπροσωπεύει την τιμή για την delay() συνάρτηση.

Εισάγουμε την επόμενη γραμμή στον προηγούμενο κώδικα, πριν την συνάρτηση void setup() και μόλις μετά το αρχικό σχόλιο.

int d = 250;

Αυτή η έκφραση (εντολή) εκχωρεί τον αριθμό 250 στην μεταβλητή που ονομάζεται d. Τώρα αντικαθιστούμε την τιμή 500 σε κάθε συνάρτηση καθυστέρησης delay() με τη μεταβλητή d. Όταν ανεβάσουμε τον κώδικα μετά που κάναμε αυτές τις αλλαγές, τα LEDs θα αναβοσβήνουν με μεγαλύτερο ρυθμό. Αν θέλουμε να αλλάξουμε τον ρυθμό που αναβοσβήνουν τα LEDs αρκεί μια αλλαγή στην τιμή της μεταβλητής d σε όποια τιμή θέλουμε.

Η λέξη int ορίζει ότι η μεταβλητή περιέχει ένα ακέραιο (ένα ακέραιο αριθμό μεταξύ -32,768 και 32,767). Ακέραια τιμή είναι εκείνη που εξ ορισμού δεν έχει δεκαδικό μέρος. Τώρα για να αλλάξεις την τιμή της καθυστέρησης απλά άλλαξε την τιμή εκχώρησης προς την μεταβλητή στην αρχή του κώδικα μας. Για παράδειγμα η εισαγωγή όπως

int d=100;

ορίζει καθυστέρηση 0,1 δευτερόλεπτα σε όλες τις συναρτήσεις καθυστέρησης delay(d); Πειραματίσου με αυτό τον κώδικα για διάφορες τιμές καθυστέρησης στην εντολή delay(d), Επίσης πειραματίσου και με την σειρά των σταθερών HIGH και LOW.

Ο βρόγχος επανάληψης for:

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

Για να δούμε πώς ένας βρόγχος for λειτουργεί, εισάγουμε και τρέχουμε τον ακόλουθο κώδικα:

// Project 2 – Repeating with for loops
int d=100;
void setup()
{
    for(byte i = 2; i<=6; i++)
        pinMode(i, OUTPUT);
}
void loop()
{
    for(byte a=2; a<=6; a++)
    {
         digitalWrite(a, HIGH);
         delay(d);
         digitalWrite(a, LOW);
         delay(d);
    }
}

Η εντολή for επαναλαμβάνει τον κώδικα που βρίσκεται μέσα στις αγκύλες του βρόγχου και το κάνει εφόσον η συνθήκη μέσα στην παρένθεση είναι αληθής. Εδώ έχουμε χρησιμοποιήσει μια καινούργια ακέραια μεταβλητή, που αρχίζει με την τιμή 2. Κάθε φορά που ο κώδικας μέσα στον βρόγχο εκτελείται, στο τέλος, η έκφραση a++ προσθέτει τον αριθμό 1 στην τιμή της μεταβλητής a. Ο βρόγχος επαναλαμβάνεται με τον ίδιο τρόπο όσο η τιμή της μεταβλητής a είναι μικρότερη ή ίση από τον αριθμό 6. Μόλις η τιμή της a γίνει μεγαλύτερη ή ίση από 7, το Arduino ξεπερνά τον βρόγχο και συνεχίζει με τις εντολές που ακολουθούν τον βρόγχο for.

Παράδειγμα: 

Σε αυτή την εργασία έχουμε ένα διακόπτη, ο οποίος ανάβει ένα LED για μισό δευτερόλεπτο όταν πατηθεί.

Το σχηματικό κύκλωμα: Πρώτα σχηματίζουμε το κύκλωμα πάνω στο breadboard όπως στο σχηματικό διάγραμμα της παρακάτω εικόνας. Δώσε προσοχή στο πως η αντίσταση 10kΩ συνδέεται μεταξύ GND και στο ψηφιακό πιν 7. Ονομάζουμε αυτή την αντίσταση pull-down γιατί “τραβά” την τάση του ψηφιακού πιν σχεδόν στο μηδέν. Περεταίρω, με την τοποθέτηση ενός πυκνωτή 100nF παράλληλα στην αντίσταση 10kΩ δημιουργούμε ένα κύκλωμα απαλλαγμένο από αναπηδήσεις.

Όταν ο διακόπτης πιέζεται το ψηφιακό πιν τίθεται αμέσως σε δυναμικό HIGH. Αλλά όταν ο διακόπτης απελευθερώνεται, το ψηφιακό πιν 7, “τραβιέται κάτω στο GND δια μέσου της αντίστασης 10kΩ και μαζί με τον πυκνωτή 100nF δημιουργούν μια πολύ μικρή καθυστέρηση. Με αυτό τον τρόπο εξαλείφονται οι αναπηδήσεις και αποτρέπονται οι λάθος τιμές τάσεων.

Ο κώδικας

//Project 3 -Demonstrating a Digital Input
#define LED 12
#define BUTTON 7
void setup()
{
    pinMode(LED, OUTPUT);  // output for the LED
    pinMode(BUTTON, INPUT);  //input for the button
}
void loop()
{
     if(digitalRead(BUTTON)==HIGH)
     {
           digitalWrite(LED, HIGH);  // turn on the LED
           delay(500);
           digitalWrite(LED, LOW);  // turn off the LED
     }
}

Μετά που ανεβάσουμε τον κώδικα πατούμε στιγμιαία το μπουτόν και παρατηρούμε το LED να ανάβει για μισό δευτερόλεπτο.

Δημιουργώντας σταθερές με την #define:

Πριν την συνάρτηση void setup() έχουμε χρησιμοποιήσει την έκφραση #define για την δημιουργία σταθερών τιμών. Καθώς ο κώδικας μεταφράζεται από τον compiler, το περιβάλλον IDE αντικαθιστά κάθε υπόδειγμα που ορίζεται από την define με τον αριθμό που ακολουθεί στην έκφραση αυτή. Για παράδειγμα, στον παραπάνω κώδικα, όταν το IDE βλέπει τη λέξη LED στην έκφραση digitalWrite(LED, LOW) τη αντικαθιστά με τον αριθμό 12.

Βασικά χρησιμοποιούμε την εντολή #define για να δώσουμε όνομα στα ψηφιακά πινς στα οποία είναι συνδεμένα το LED και το BUTTON. Ας σημειώσουμε ότι δεν χρησιμοποιούμε ερωτηματικό στο τέλος της #define. Είναι καλή τακτική να δίνομε ετικέτες στα ψηφιακά πινς και στις άλλες σταθερές τιμές (όπως στη χρονική καθυστέρηση). Με αυτό τον τρόπο, η ίδια η σταθερά χρησιμοποιείται επαναλαμβανόμενα στο κώδικα, και έχει σταθερή τιμή. Σε αυτό το παράδειγμα  ο όρος LED χρησιμοποιείται τρεις φορές στο κώδικα και για να επέμβουμε στην τιμή της απλά αλλάζουμε την τιμή στην έκφραση #define.

Διάβασμα πιν ψηφιακής εισόδου:

Για το διάβασμα της κατάστασης ενός διακόπτη, πρέπει να δηλώσουμε ως INPUT το πίν στο οποίο είναι συνδεδεμένος ο διακόπτης, μέσα στη συνάρτηση  void setup() χρησιμοποιώντας την ακόλουθη έκφραση

pinMode(BUTTON, INPUT);

Για να δούμε εάν ο διακόπτης που είναι συνδεμένος σε ένα ψηφιακό πιν, είναι πατημένος χρησιμοποιούμε, την εντολή

digitalRead(pin) ;

όπου pin είναι ο αριθμός του πιν που η ψηφιακή είσοδος πρόκειται να διαβαστεί. Η συνάρτηση επιστρέφει είτε HIGH (τάση κοντά στα 5V) ή LOW (τάση κοντά στα 0V) για την κατάσταση του ψηφιακού πιν

Κάνοντας επιλογές με την εντολή if:

Χρησιμοποιώντας την εντολή if μπορούμε να κάνουμε επιλογές στον κώδικα μας και να πούμε στο Arduino να τρέξει διαφορετικό κώδικα, ανάλογα με την συνθήκη της εντολής if. Για παράδειγμα  στον κώδικα

if(digitalRead(BUTTON) == HIGH)
{
   digitalWrite(LED, HIGH);   // turn on the LED
   delay(500);
   digitalWrite(LED, LOW);    // turnoff the LED
}

Η πρώτη γραμμή στον κώδικα ξεκινά με την εντολή if η οποία ελέγχει μια συνθήκη. Εάν η συνθήκη είναι αληθείς (δηλαδή η τάση είναι HIGH), αυτό σημαίνει ότι το μπουτόν έχει πατηθεί με αποτέλεσμα ο κώδικας που ακολουθεί μέσα στις αγκύλες θα τρέξει. Για να ορίσουμε εάν το μπουτόν έχει πατηθεί χρησιμοποιούμε την ακόλουθη έκφραση σαν συνθήκη της εντολής if.

digitalRead(BUTTON) == HIGH

Αυτή η συνθήκη επιστρέφει LOW ή HIGH αν η τάση στην είσοδο BUTTON είναι 0 volts ή 5 Volts αντίστοιχα. Προσέξτε το διπλό ίσον (==) που είναι ο λογικός τελεστής ισότητας. Εάν στον κώδικα αντικαταστήσουμε το == με != (όχι ίσο με), τότε το LED θα σβήσει όταν το μπουτόν πατηθεί.

Δεν θα πρέπει να συγχέουμε το απλό σύμβολο ισότητας (=)που σημαίνει “κάνε ίσο με” με τον τελεστή σύγκρισης (==) που σημαίνει “έλεγξε εάν είναι ίσο με”.