Η σημερινή εποχή έχει διαμορφώσει καινούριες ιδέες και συμπεριφορές σε πολλές πτυχές της ζωής μας, οι οποίες τελικά, έπρεπε να διέλθουν
μέσα από μια μακροχρόνια εξέλιξη ώστε να μπορέσουμε να κατανοήσουμε την πολυσχιδή έννοια και εφαρμογή τους στην καθημερινή μας ζωή.
Μια τέτοια, είναι η έννοια της ανακύκλωσης. Σε πολλούς τομείς της ζωής μας, έχει πια αποδειχθεί οτι πρέπει να υφίσταται ώστε συγκεντρωτικά,
να έχει οφέλη που διαφαίνονται βραχυπρόθεσμα αλλά και μακροπρόθεσμα.
Για κάποιους που ασχολούνται με την ανάπτυξη λογισμικού είτε απο επαγγελματικής είτε απο ερασιτεχνικής πλευράς, η ανακύκλωση έχει
άριστη εφαρμογή, προσθέτοντας στο έργο τους πλεονεκτήματα εμπορικότητας, μείωσης χρόνου ανάπτυξης και σιγουριάς στη λειτουργία
του τελικού αποτελέσματος.
Στόχος λοιπόν αυτού του θέματος είναι η παράθεση μερικών γραμμών κώδικα που μπορούν να χρησιμοποιηθούν ξανά και ξανά, βασισμένων σε μια
ανώτερη γλώσσα προγραμματισμού όπως η C που μπορούν να χρησιμοποιηθούν απο πολλούς "compilers" μοντέρνων μικροελεγκτών. Για
να είμαι ειλικρινής, επειδή ασχολούμαι τα τελευταία χρόνια με τέτοιους της Atmel, αναφέρομαι ειδικότερα σε αυτούς και ακόμα
πιο ειδικά στις πλατφόρμες και το περιβάλλον του Arduino. Αυτό δεν σημαίνει όμως οτι ξεχνάω τις μεγάλες μου αγάπες της Microchip που
πάνω τους έμαθα.
1. Ήχος με το πάτημα ενός κουμπιού
Πολλές φορές, χρειαζόμαστε για ένα keyboard user interface μια ηχητική επιβεβαίωση όταν πατάμε το πλήκτρο εισαγωγής κάποιας εντολής.
Μπορεί λοιπόν άνετα, να εισαχθεί ένα τμήμα κώδικα που έχει παραμετροποιηθεί κατά συχνότητα και διάρκεια, ώστε όταν η συνάρτησή του
καλείται οπουδήποτε, να προκαλεί την ηχητική επιβεβαίωση:
Code: Select all
#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.
Code: Select all
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
Code: Select all
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
εγγράψουμε στον καταχωρητή ωρών ενός M41T80 ρολογιού πραγματικού χρόνου της STM την τιμή 10:
Code: Select all
Wire.write(decToBcd(hours));
έχει την δεκαδική τιμή που εμείς έχουμε ορίσει.
3. Μετατροπή BCD σε δεκαδικό
Αντίθετα τώρα, όταν πρόκειται να "διαβάσουμε" έναν RTC του παραπάνω τύπου, θα πρέπει -για να κάνουμε τις
πράξεις μας πιο ανθρώπινα- να μετατρέψουμε το περιεχόμενο κάποιου απο τους καταχωρητές του σε δεκαδικό αριθμό.
Εδώ μπορούμε να χρησιμοποιήσουμε την εξής συνάρτηση:
Code: Select all
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
Code: Select all
minutes = bcdToDec(Wire.read()); // ο καταχωρητής minutes "φορτώνεται" με την τιμή που επιστρέφει η συνάρτηση bcdToDec
Πολλές φορές, είναι αναγκαίο να "εκτυπώνουμε" διάφορες μεταβλητές σε οθόνες LCD, GLCD, σειριακά τερματικά, ασύρματες συσκευές.
Ειδικότερα για τις μεταβλητές δεκαδικού με υποδιαστολή (floats), πολλοί compilers εμφανίζουν ως και 8 δεκαδικά ψηφία, πράγμα που είναι
μερικές φορές κουραστικό. Η παρακάτω συνάρτηση μπορεί να "εκτυπώσει π.χ. σε μια οθόνη LCD μια float με προκαθορισμένο απο
τον χρήστη αριθμό ψηφίων μετά την υποδιαστολή, ορίζοντας έναν αριθμό σαν όρισμα:
Code: Select all
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;
}
}
Παράδειγμα χρήσης:
Code: Select all
printFloat(0.252443, 2)
Εννοείται πως για την εντολή lcd.print(x,y), ισχύει η σειρά και η στήλη που θέλουμε να εμφανιστεί το αποτέλεσμα, η οποία
έχει οριστεί ενωρίτερα στον κώδικα. Το πιο πάνω παράδειγμα θα γίνει ως εκ τούτου:
Code: Select all
lcd.setCursor(0,0);
printFloat(0.252443, 2)
5. "Σπασιμο" ενός 4ψήφιου αριθμού (integer) σε χιλιάδες, εκατοντάδες, δεκάδες και μονάδες
Η μεταβλητή του αριθμού που θέλουμε να "σπάσουμε": input_number
Οι μεταβλητές thousands, hundrends, tenths, ones θα περιέχουν τον "απο-δομημένο" τετραψήφιο.
Code: Select all
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);
εις τα "εξ΄ων συνετέθη..."
Code: Select all
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 για κάθε ψηφίο το μέγεθος.