Προγραμματισμός – Βασικές λειτουργίες 

Μετά την εγκατάσταση του Arduino IDE μπορούμε να γράψουμε τα πρώτα μας τμήματα κώδικα. Η λογική του Arduino είναι πολύ απλή – στην ουσία υπάρχουν δύο βασικές συναρτήσεις, η setup() και η loop() οι οποίες δουλεύουν ως εξής: 

  • setup() – εδώ βάζουμε όλες τις εντολές που πρέπει να τρέξουν μία φορά, όταν ενεργοποιείται η μονάδα μας (όταν δηλαδή δίνουμε ρεύμα ή όταν πατηθεί το πλήκτρο reset που υπάρχει). Συνήθως μπαίνουν αρχικοποιήσεις τιμών μεταβλητών και οπωσδήποτε ο χαρακτηρισμός των εισόδων/εξόδων που θα χρησιμοποιήσουμε (αν δηλαδή ένα συγκεκριμένο Pin θα είναι είσοδος ή εξοδος). 
  • loop() – εδώ γράφουμε το πρόγραμμά μας. Οι εντολές που υπάρχουν θα τρέξουν κι όταν φτάσει στο τέλος θα ενεργοποιηθεί ξανά η loop(), συνεχίζοντας από την αρχή της, και ξανά. Αυτό θα συμβαίνει συνεχώς, όσο έχει ρεύμα το Arduino ή μέχρι να πατηθεί το πλήκτρο reset. 

Έτσι, η βασική λειτουργία του Arduino είναι ότι τρέχει η συνάρτηση setup() μία φορά στην αρχή και ακολούθως η loop() ξανά και ξανά μέχρι να το κλείσουμε (να μην τροφοδοτείται με ρεύμα) ή να πατήσουμε το πλήκτρο reset. Στην περίπτωση του Reset ξανατρέχει η συνάρτηση setup() μία φορά και ακολούθως η loop() ξανά και ξανά, όπως δηλαδή ακριβώς και όταν αρχικά ενεργοποιείται με ρεύμα ο μικροελεγκτής. Στην περίπτωση που έχουμε κάνει αλλαγές στο πρόγραμμά μας και το φορτώσουμε στον μικροελεγκτή (θα δούμε παρακάτω τη διαδικασία αυτή) αρκεί να πατήσουμε το πλήκτρο Reset ώστε να φορτώσει το πρόγραμμά μας από την αρχή με τον τρόπο που περιγράφηκε. 

Ένα τυπικό πρόγραμμα έχει την παρακάτω δομή:  

void setup() { /* οι εντολές εδώ θα τρέξουν μόνο στην ενεργοποίηση ή μετά από Reset */ 

void loop() { /* οι εντολές εδώ θα τρέχουν ξανά και ξανά, μέχρι να απενεργοποιηθεί ή να πατηθεί το Reset */ 

Δηλώσεις μεταβλητών 

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

  • boolean, με τιμές το 0 και 1 (ή True – False) 
  • byte, με τιμές από 0 έως και 255 
  • int, ακέραιος με δυνατές τιμές από -32768 έως και 32767 
  • long, ακέραιος με δυνατές τιμές από -2147483648 έως και 2147483647 
  • float, δεκαδικοί αριθμοί • char, ένας χαρακτήρας (μέγεθος ένα Byte) 
  • string, πίνακας χαρακτήρων 

 Ένα παράδειγμα δήλωσης μεταβλητών δίνεται παρακάτω:  

  • int ledPin = 13; // ορίζω ακέραια μεταβλητή ledPin και αρχικοποιώ την τιμή της σε 13 
  • float SinVal; // ορίζω πραγματική μεταβλητή SinVal  

Σχόλια 

Όπως σε όλες τις γλώσσες προγραμματισμού, μπορώ να έχω σχόλια για την ευκολότερη κατανόηση και συντήρηση του κώδικα που γράφω. Μπορώ να χρησιμοποιήσω τις δύο κάθετες // για σχόλιο σε μία γραμμή (ότι ακολουθεί τις // αγνοείται), ή τα /* */ που περικλείουν τα σχόλια που γράφονται σε περισσότερες γραμμές (ότι υπάρχει ανάμεσα στο /* και στο */ αγνοείται). Για παράδειγμα:  

  • int ledPin = 13; // ορίζω τον αριθμό του Pin για το LED /* 

Συναρτήσεις διαχείρισης θυρών εισόδου – εξόδου (Pins) 

Όπως αναφέρθηκε, η κύρια λειτουργία του μικροελεγκτή βασίζεται στο να ελέγχει τις θύρες που διαθέτει και είτε να δίνει ρεύμα είτε να παίρνει ρεύμα από αυτές. Στην αρχικοποίηση κάθε προγράμματος (μέσα στη συνάρτηση setup) θα χρειαστεί να χαρακτηρίσουμε τα Pins που χρησιμοποιούμε ως είσοδο ή ως έξοδο. 

Η συνάρτηση pinMode(Pin, Mode) χρησιμοποιείται με το όνομά της και ορίσματα α) τον αριθμό Pin και β) την κατάσταση λειτουργίας που χαρακτηρίζεται με τη λέξη INPUT (είσοδος) ή OUTPUT(έξοδος). 

Έχουμε 14 ψηφιακά Pins, 6 εκ των οποίων είναι PWM, με ονόματα 0..13 και έξι αναλογικά με ονόματα Α0..Α5. 

Για παράδειγμα:

  •  pinMode(12, OUTPUT); pinMode(ledPin, OUTPUT); pinMode(Α2, INPUT);  

Συναρτήσεις εισόδου – εξόδου ρεύματος

Για να μπορέσουμε να δώσουμε ρεύμα προς τα έξω μέσω μιας θύρας (pin) θα πρέπει πρώτα να έχει αυτή οριστεί ως εξόδος. Ακολούθως, με χρήση της κατάλληλης εντολής μπορούμε να δώσουμε κάθε φορά την επιθυμητή τάση προς τα έξω. Αντίστοιχα, για να “διαβάσουμε” από μια είσοδο, θα πρέπει αρχικά να την ορίσουμε ως είσοδο και με χρήση της κατάλληλης κάθε φοράς συνάρτησης να διαβάζουμε την αντίστοιχη τιμή.  

Ψηφιακή έξοδος 

Και τα 14 pins του Arduino μπορούν δουλεύουν ως ψηφιακές έξοδοι, δηλαδή δίνουν έξοδο 0 ή 5V. Αυτό γίνεται με χρήση της συνάρτησης digitalWrite(Pin, Value), όπου το όρισμα Pin αναφέρεται στο νούμερο της θύρας για την οποία θα δώσουμε τάση εξόδου, ενώ η τάση εξόδου μπορεί να είναι 0 V ή 5 V, οι οποίες αναπαρίστανται με προκαθορισμένες τιμές στην παράμετρο value 

  • LOW : θα δώσει 0 V στην έξοδο (pin) 
  •  HIGH : θα δώσει 5 V στην έξοδο (pin) 

Για παράδειγμα:  digitalWrite(ledPin, HIGH);  

Προσοχή: Η αντίστοιχη θύρα θα πρέπει να έχει οριστεί ως εξόδου στη διαδικασία setup(), με χρήση της συνάρτησης pinMode. 

  • Για παράδειγμα:  pinMode(10, OUTPUT);  

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

Και τα 14 ψηφιακά pins του Arduino μπορούν δουλεύουν ως ψηφιακές είσοδοι, δηλαδή να “διαβάσουν” ως είσοδο τάση με τιμή είτε 0 είτε 5V. Αυτό γίνεται με χρήση της συνάρτησης digitalRead(Pin), όπου το όρισμα Pin αναφέρεται στο νούμερο της θύρας για την οποία θα πάρουμε είσοδο, ενώ η συνάρτηση επιστρέφει με το όνομά της την τιμή εισόδου. H τάση εισόδου μπορεί να είναι 0V ή 5V, οι οποίες αναπαρίστανται με προκαθορισμένες τιμές στην τιμή που διαβάζουμε: 

  •  LOW : όταν λάβει τάση 0 V στην είσοδο (pin) 
  •  HIGH : όταν λάβει τάση 5 V στην είσοδο (pin) Για παράδειγμα:  Val = digitalRead(ledPin);  

Προσοχή: Η αντίστοιχη θύρα θα πρέπει να έχει οριστεί ως εισόδου στη διαδικασία setup(), με χρήση της συνάρτησης pinMode. 

  • Για παράδειγμα:  pinMode(10, INPUT);  

Αναλογική έξοδος (PWM pins) 

Κάποια από τα 14 Pins του Arduino έχουν την ένδειξη PWM, δηλαδή μπορούν να προσομοιώσουν την αναλογική έξοδο μέσω παλμοκωδικής διαμόρφωσης. Έτσι, με τιμές από το 0 μέχρι το 255 προσομοιώνουμε (αναλογικά) το διάστημα από 0 έως 5V. Αυτό γίνεται με χρήση της συνάρτησης analogWrite(Pin, Value), όπου το όρισμα Pin αναφέρεται στο νούμερο της θύρας για την οποία θα δώσουμε ρεύμα εξόδου, ενώ η τάση εξόδου κυμαίνεται από 0 V μέχρι και 5 V, οι οποίες τιμές της τάσης αναλογικά αναπαρίστανται με τιμές στη μεταβλητή value. Τιμή 0 δίνει 0V στην έξοδο (pin), τιμή 255 δίνει τάση 5V στην έξοδο (pin), ενώ αναλογικά μπορούμε να δώσουμε ενδιάμεσες τάσεις (π.χ. 122 για τάση 2,5V). 

  • Για παράδειγμα:  analogWrite(ledPin, 122);  

Υπενθύμιση: Τη λειτουργία αυτή μπορούν να υποστηρίξουν μόνο τα PWM pins κι όχι όλα τα ψηφιακά. Τα PWM pins είναι τα 3, 5, 6, 9, 10, 11. 

Προσοχή: Η αντίστοιχη θύρα θα πρέπει να έχει οριστεί ως εξόδου στη διαδικασία setup(), με χρήση της συνάρτησης pinMode. 

  • Για παράδειγμα:  pinMode(10, OUTPUT);  

Αναλογική είσοδος 

To Arduino έχει 6 αναλογικές εισόδους, οι οποίες χαρακτηρίζονται με τα σύμβολα A0, A1, A2, A3, A4, A5. Μπορούμε να συνδέσουμε κάποιο αναλογικό εξάρτημα (π.χ. ένα ποτενσιόμετρο) και να το διαβάσουμε ως είσοδο. Αυτό γίνεται με χρήση της συνάρτησης analogRead(Pin), όπου το όρισμα Pin αναφέρεται στο νούμερο της θύρας για την οποία θα πάρουμε είσοδο, ενώ η συνάρτηση επιστρέφει με το όνομά της την τιμή εισόδου. Η τιμή εισόδου κυμαίνεται από 0 μέχρι και 1023. Συνήθως χρησιμοποιούμε μια μεταβλητή για να καταχωρήσουμε την τιμή. 

Για παράδειγμα:  

  • int r = analogRead(A1);  

Προσοχή: Η αντίστοιχη θύρα θα πρέπει να έχει οριστεί ως εισόδου στη διαδικασία setup(), με χρήση της συνάρτησης pinMode. 

Για παράδειγμα:  

  • pinMode(A1, INPUT);  

Συνάρτηση καθυστέρησης – delay() 

Στο πρόγραμμά μας μπορούμε να ορίσουμε μια καθυστέρηση ώστε να διαρκέσει για το χρόνο που εμείς ορίζουμε ένα γεγονός. Αυτό το επιτυγχάνουμε με χρήση της συνάρτησης delay(time) όπου στη θέση time δίνουμε το χρόνο σε ms (1/1000 sec). Η εντολή delay(time) σημαίνει ότι σταματά στο σημείο αυτό η εκτέλεση του προγράμματός μας για το χρόνο time. 

Για παράδειγμα:  

  • delay(1000); //σταματά την εκτέλεση του προγράμματος για 1000 ms = 1 sec 
  • delay(500); //σταματά την εκτέλεση στο σημείο αυτό για 500 ms = 0.5 sec  

Συνάρτηση καταγραφής χρόνου – millis() 

Το Arduino έχει ενσωματωμένο ρολόι, το οποίο μετράει το χρόνο από τη στιγμή που ενεργοποιείται (ή του γίνεται reset). Η πληροφορία αυτή μας είναι διαθέσιμη σε κάθε σημείο με κλήση της συνάρτησης millis(), η οποία μας επιστρέφει το χρόνο σε milliseconds (1/1000 sec) που έχει περάσει από την ενεργοποίηση της μονάδας μας. Αυτό μας βοηθά να μετράμε το χρόνο στα προγράμματά μας, ειδικά στις περιπτώσεις που θέλουμε να “θυμόμαστε” πράγματα. 

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

  • Για παράδειγμα:  lastPress = millis(); if (lastPress – millis() > 1000) {…}  

Η σειριακή θύρα επικοινωνίας (Serial) 

To Arduino παρέχει μια σειριακή θύρα επικοινωνίας μεταξύ της πλακέτας και του υπολογιστή ή κάποιας συσκευής που θέλουμε. Για το σκοπό αυτό χρησιμοποιείται η σύνδεση με καλώδιο USB (όταν πρόκειται για τον υπολογιστή) ή τα pins 0 και 1 όταν θέλουμε κάποια πιο εξειδικευμένη σύνδεση (π.χ. με κάποια άλλη συσκευή). Για το λόγο αυτό προτείνεται, αν δεν είναι απαραίτητο στις εφαρμογές μας, να μην χρησιμοποιούνται τα pins αυτά. Για να ενεργοποιήσουμε τη σειριακή θύρα επικοινωνίας αρκεί να δώσουμε στη διαδικασία setup() την εντολή Serial.begin(BaudRate), όπου το BaudRate εκφράζει το ρυθμό με τον οποίο θα μεταδίδονται τα bits (μια τιμή στα 9600 είναι συνήθως αρκετή). 

  • Για παράδειγμα:  Serial.begin(9600);  

Μπορούμε να χρησιμοποιήσουμε τη σειριακή θύρα στις εφαρμογές για αμφίδρομη επικοινωνία, δηλαδή να στείλουμε και να λάβουμε δεδομένα. Μία απλή περίπτωση χρήση της επικοινωνίας αυτής είναι για εκσφαλμάτωση (debugging) των προγραμμάτων μας, να μπορούμε δηλαδή να δούμε τί τιμές μας δίνουν μετρητές και τι τιμές έχουν οι μεταβλητές μας μέσω της οθόνης σειριακής επικοινωνίας. 

Μια εντολή που μας βοηθάει σε αυτό είναι η print(), που εκτυπώνει ένα μήνυμα ή τιμές ή η println() που λειτουργεί ακριβώς το ίδιο αλλά εκτυπώνοντας με αλλαγή γραμμής κάθε φορά. 

Για παράδειγμα:  

  • Serial.print(“H epikoinwnia ksekinhse”); /* Θα εμφανίσει το μήνυμα αυτό στην οθόνη χωρίς να αλλάξει γραμμή μετά */ 
  • Serial.println(distance); /* Θα εμφανίσει την τιμή της μεταβλητής distance σε μια γραμμή */  

Όταν έχετε συνδέσει το Arduino σας με τη θύρα USB στον υπολογιστή, η σειριακή οθόνη ενεργοποιείται από το εικονίδιο πάνω δεξιά “Σειριακή Οθόνη”, και στο παράθυρο που ανοίγει μπορείτε να βλέπετε όλα τα μηνύματα που στέλνονται από τον κώδικα που έχει φορτωθεί ήδη και τρέχει στην πλακέτα.