9. Δημιουργώντας functions

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

Δηλώνοντας functions

Πριν χρησιμοποιήσουμε την function μέσα στον κώδικα μας θα πρέπει να την δηλώσουμε στην αρχή του προγράμματος μας. Για να δηλώσουμε μια function, χρησιμοποιούμε την ακόλουθη μορφή:

datatype funcname() {
          // code statements
}

Το όνομα funcname ορίζει το όνομα για την function που θα χρησιμοποιούμε για να αναφερόμαστε σε αυτήν στον κώδικα Arduino. Τα ονόματα που δίνουμε σε μια function θα πρέπει να έχουν τους ίδιους περιορισμούς όπως τα ονόματα μεταβλητών. Ο όρος datatype ορίζει τον τύπο δεδομένων που επιστρέφει η συνάρτηση.

Παράδειγμα: Για την δημιουργία μιας function που δεν επιστρέφει δεδομένα χρησιμοποιούμε τον τύπο δεδομένων void:

void MyFunction() {
       Serial.println(“This is my first function”);
}

Μετά που δηλώσουμε την function είμαστε έτοιμοι να τη χρησιμοποιήσουμε. Για να χρησιμοποιήσουμε την function κάνουμε αναφορά στο όνομα της ακολουθούμενη από παρενθέσεις:

void setup(){
          Serial.begin(9600);
          MyFunction();
          Serial.println(“Now we’ re back to the main program”);
}

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

Επιστρέφοντας μια τιμή

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

return value;

όπου value η τιμή που επιστρέφει η συνάρτηση. Η τιμή value μπορεί να είναι μια αριθμητική τιμή οποιαδήποτε τύπου δεδομένων ή μια τιμή string.

Εάν η συνάρτηση επιστρέφει μια τιμή δεδομένων δια μέσου μιας τοπικής μεταβλητής, ο τύπος δεδομένων της μεταβλητής αυτής, θα πρέπει να είναι του ίδιου τύπου δεδομένων με εκείνου κατά τη δήλωση της συνάρτησης.

float MyFunction3() {
              float result;
              result = 10.0/2.0;
              return result;
}

Για να πάρουμε την τιμή που επιστρέφει η συνάρτηση θα πρέπει να την εκχωρήσουμε σε μια μεταβλητή όπως φαίνεται ακολούθως:

float value;
value = MyFunction3();

Εκχωρώντας τιμές σε συναρτήσεις

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

value = area(10, 20);

Τα ορίσματα 10 και 20 εισάγονται μέσα στις παρενθέσεις δίπλα στο όνομα της συνάρτησης χωρισμένα με κόμμα. Κατά τη δήλωση μιας συνάρτησης, τοποθετούμε παρενθέσεις δίπλα στο όνομα της, όπου οι παράμετροι – μεταβλητές της συνάρτησης παίρνουν τα ορίσματα που εισάγουμε εκεί. Ο τύπος δεδομένων των παραμέτρων της συνάρτησης ορίζεται κατά τη δήλωση της συνάρτησης:

int area(int width, int height){
                 int result = width * height;
                 return result;
}

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

int area(int, int);
void setup() {
          int returnValue;
          Serial.begin(9600);
          Serial.print(“The area of a 10 X 20 size room is”);
          returnValue = area(10, 20);
          Serial.println(returnValue);
}
void loop(){
}
int area(int width, int height){
            int result = width * height;
            return result;
}

Εμβέλεια μεταβλητών

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

1) Καθολικές μεταβλητές
2) Τοπικές μεταβλητές

Καθολικές μεταβλητές είναι εκείνες που μπορούν να προσπελαστούν οπουδήποτε μέσα στον κώδικα. Μια καθολική μεταβλητή δηλώνεται στο κυρίως σώμα του κώδικα, έξω από τις συναρτήσεις όπου μπορούμε να ανακτούμε τις τιμές της μέσα από οποιαδήποτε συνάρτηση του κώδικα.

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

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

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