Η σημερινή εποχή έχει διαμορφώσει καινούριες ιδέες και συμπεριφορές σε πολλές πτυχές της ζωής μας, οι οποίες τελικά, έπρεπε να διέλθουν
μέσα από μια μακροχρόνια εξέλιξη ώστε να μπορέσουμε να κατανοήσουμε την πολυσχιδή έννοια και εφαρμογή τους στην καθημερινή μας ζωή.
Μια τέτοια, είναι η έννοια της ανακύκλωσης. Σε πολλούς τομείς της ζωής μας, έχει πια αποδειχθεί οτι πρέπει να υφίσταται ώστε συγκεντρωτικά,
να έχει οφέλη που διαφαίνονται βραχυπρόθεσμα αλλά και μακροπρόθεσμα.
Για κάποιους που ασχολούνται με την ανάπτυξη λογισμικού είτε απο επαγγελματικής είτε απο ερασιτεχνικής πλευράς, η ανακύκλωση έχει
άριστη εφαρμογή, προσθέτοντας στο έργο τους πλεονεκτήματα εμπορικότητας, μείωσης χρόνου ανάπτυξης και σιγουριάς στη λειτουργία
του τελικού αποτελέσματος.
Στόχος λοιπόν αυτού του θέματος είναι η παράθεση μερικών γραμμών κώδικα που μπορούν να χρησιμοποιηθούν ξανά και ξανά, βασισμένων σε μια
ανώτερη γλώσσα προγραμματισμού όπως η C που μπορούν να χρησιμοποιηθούν απο πολλούς "compilers" μοντέρνων μικροελεγκτών. Για
να είμαι ειλικρινής, επειδή ασχολούμαι τα τελευταία χρόνια με τέτοιους της Atmel, αναφέρομαι ειδικότερα σε αυτούς και ακόμα
πιο ειδικά στις πλατφόρμες και το περιβάλλον του Arduino. Αυτό δεν σημαίνει όμως οτι ξεχνάω τις μεγάλες μου αγάπες της Microchip που
πάνω τους έμαθα.
1. Ήχος με το πάτημα ενός κουμπιού
Πολλές φορές, χρειαζόμαστε για ένα keyboard user interface μια ηχητική επιβεβαίωση όταν πατάμε το πλήκτρο εισαγωγής κάποιας εντολής.
Μπορεί λοιπόν άνετα, να εισαχθεί ένα τμήμα κώδικα που έχει παραμετροποιηθεί κατά συχνότητα και διάρκεια, ώστε όταν η συνάρτησή του
καλείται οπουδήποτε, να προκαλεί την ηχητική επιβεβαίωση:
Κώδικας: Επιλογή όλων
#define BUZZER_PIN xx //όπου χχ ο αριθμός pin (digital)
pinMode(BUZZER_PIN, OUTPUT); //ορισμός του pin σαν ψηφιακή έξοδο.
digitalWrite(BUZZER_PIN, LOW); // καθήλωση της εξόδου σε λογικό 0.
void beepBuzzer(unsigned long hz, unsigned long ms)
{
unsigned long us = (750000 / hz);
unsigned long rep = (ms * 500L) / us;
for (int i = 0; i < rep; i++)
{
digitalWrite(BUZZER_PIN, HIGH);
delayMicroseconds(us);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(us);
}
}
και τη χρονική διάρκεια της ταλάντωσης αυτής σε ms:
beepBuzzer(8000,50); // συχνότητα στα 8KHz και διάρκεια "μπιπ" 50ms.
Σημείωση (αρκετά ενδιαφέρουσα): όλοι οι buzzer του τύπου
...έχουν εκ κατασκευής μια ιδιοσυχνότητα ηχείου στης οποίας τη συχνότητα (σε Hz), το παραγόμενο ηχητικό αποτέλεσμα
είναι το πιο δυνατό. Πρέπει λοιπόν στο όρισμα unsigned long Hz της παραπάνω συνάρτησης, να μπεί (με δοκιμή και σφάλμα)
η συχνότητα αυτή. Τότε λοιπόν θα έχει κάποιος ένα πολύ όμορφο "μπιπ" κάθε φορά που πιέζει ένα κουμπί του πληκτρολογίου του
ή άλλου κουμπιού.
2. Μετατροπή δεκαδικού σε BCD (Binary Coded Decimal)
Σε πολλές συσκευές, όπως για παράδειγμα τα ρολόγια RTC, είναι απαραίτητο τα αποτελέσματα που επεξεργαζόμαστε στον κώδικα
απο πράξεις για τα λεπτά, τα δευτερόλεπτα ή ακόμα τους μήνες, τις ημερομηνίες και γενικά όλους τους χρονικούς καταχωρητές
να το αποθηκεύσουμε σε αυτούς στην απαιτούμενη μορφή που είναι σε κώδικα BCD. Ο BCD κώδικας είναι η έκφραση δεκαδικών
ψηφίων τέτοια ώστε κάθε δεκαδικό ψηφίο να αντιπροσωπεύεται απο έναν προκαθορισμένο αριθμό δυαδικών ψηφίων, συνήθως 4 ή 8.
Κώδικας: Επιλογή όλων
Decimal
Digit BCD
0 0 0 0 0
1 0 0 0 1
2 0 0 1 0
3 0 0 1 1
4 0 1 0 0
5 0 1 0 1
6 0 1 1 0
7 0 1 1 1
8 1 0 0 0
9 1 0 0 1
Κώδικας: Επιλογή όλων
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
εγγράψουμε στον καταχωρητή ωρών ενός M41T80 ρολογιού πραγματικού χρόνου της STM την τιμή 10:
Κώδικας: Επιλογή όλων
Wire.write(decToBcd(hours));
έχει την δεκαδική τιμή που εμείς έχουμε ορίσει.
3. Μετατροπή BCD σε δεκαδικό
Αντίθετα τώρα, όταν πρόκειται να "διαβάσουμε" έναν RTC του παραπάνω τύπου, θα πρέπει -για να κάνουμε τις
πράξεις μας πιο ανθρώπινα- να μετατρέψουμε το περιεχόμενο κάποιου απο τους καταχωρητές του σε δεκαδικό αριθμό.
Εδώ μπορούμε να χρησιμοποιήσουμε την εξής συνάρτηση:
Κώδικας: Επιλογή όλων
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
Κώδικας: Επιλογή όλων
minutes = bcdToDec(Wire.read()); // ο καταχωρητής minutes "φορτώνεται" με την τιμή που επιστρέφει η συνάρτηση bcdToDec
Πολλές φορές, είναι αναγκαίο να "εκτυπώνουμε" διάφορες μεταβλητές σε οθόνες LCD, GLCD, σειριακά τερματικά, ασύρματες συσκευές.
Ειδικότερα για τις μεταβλητές δεκαδικού με υποδιαστολή (floats), πολλοί compilers εμφανίζουν ως και 8 δεκαδικά ψηφία, πράγμα που είναι
μερικές φορές κουραστικό. Η παρακάτω συνάρτηση μπορεί να "εκτυπώσει π.χ. σε μια οθόνη LCD μια float με προκαθορισμένο απο
τον χρήστη αριθμό ψηφίων μετά την υποδιαστολή, ορίζοντας έναν αριθμό σαν όρισμα:
Κώδικας: Επιλογή όλων
void printFloat(float value, int places) //value η τιμή της float, places ο αριθμός δεκαδικών μετά την υποδιαστολή.
{
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;
float d = 0.5;
if (value < 0) d *= -1.0;
for (i = 0; i < places; i++) d/= 10.0;
tempfloat += d;
if (value < 0) tempfloat *= -1.0;
while ((tens * 10.0) <= tempfloat)
{
tens *= 10.0;
tenscount += 1;
}
if (value < 0) lcd.print('-');
if (tenscount == 0) lcd.print(0, DEC);
for (i=0; i< tenscount; i++)
{
digit = (int) (tempfloat/tens);
lcd.print(digit, DEC);
tempfloat = tempfloat - ((float)digit * tens);
tens /= 10.0;
}
if (places <= 0) return;
lcd.print('.');
for (i = 0; i < places; i++)
{
tempfloat *= 10.0;
digit = (int) tempfloat;
lcd.print(digit,DEC);
tempfloat = tempfloat - (float) digit;
}
}
Παράδειγμα χρήσης:
Κώδικας: Επιλογή όλων
printFloat(0.252443, 2)
Εννοείται πως για την εντολή lcd.print(x,y), ισχύει η σειρά και η στήλη που θέλουμε να εμφανιστεί το αποτέλεσμα, η οποία
έχει οριστεί ενωρίτερα στον κώδικα. Το πιο πάνω παράδειγμα θα γίνει ως εκ τούτου:
Κώδικας: Επιλογή όλων
lcd.setCursor(0,0);
printFloat(0.252443, 2)
5. "Σπασιμο" ενός 4ψήφιου αριθμού (integer) σε χιλιάδες, εκατοντάδες, δεκάδες και μονάδες
Η μεταβλητή του αριθμού που θέλουμε να "σπάσουμε": input_number
Οι μεταβλητές thousands, hundrends, tenths, ones θα περιέχουν τον "απο-δομημένο" τετραψήφιο.
Κώδικας: Επιλογή όλων
int input_number, thousands, hundrends, tenths, ones;
ones = (input_number%10);
tens = ((input_number/10)%10);
hundreds = ((input_number/100)%10);
thousands = (input_number/1000);
εις τα "εξ΄ων συνετέθη..."
Κώδικας: Επιλογή όλων
void disassembly_integer(int input_number)
{
ones = (input_number%10);
tens = ((input_number/10)%10);
hundreds = ((input_number/100)%10);
thousands = (input_number/1000);
}
ή αν θέλουμε να ρυθμίσουμε με ξεχωριστό για κάθε ψηφίο τρόπο π.χ. τον αριθμό στον οποίο θέλουμε μια ειδοποίηση, ελέγχοντας
με μια OR για κάθε ψηφίο το μέγεθος.