Υλοποίηση της επικοινωνίας και του γραφικού περιβάλλοντος χειρισμών στη σύνδεση υπολογιστή με τον μικροελεγκτή του συστήματος ελέγχου ανεμογεννήτριας

Σχετικά έγγραφα
Συνοπτικό εγχειρίδιο χρήσης του Microsoft Visual Studio 2010

Ελεύθερο Λογισμικό. Η αρχή της ιστορίας Κιαγιαδάκης Γιώργος (το labάκι)

Hase οδηγίες χρήσης.

Συνοπτικό εγχειρίδιο χρήσης του Microsoft Visual Studio 2010

Linux με τη χρήση κονσόλας

Πως θα κατασκευάσω το πρώτο πρόγραμμα;

Tο περιβάλλον Code::Blocks

Ένωση Ελλήνων Χρηστών και Φίλων ΕΛ/ΛΑΚ

Tο περιβάλλον Code::Blocks

Οδηγίες εγκατάστασης και χρήσης Java σε προσωπικό υπολογιστή

Εγκατάσταση του εκτυπωτή από το CD λογισμικού και τεκμηρίωσης

Λειτουργικό Σύστημα Linux ~ Μια σύντομη εισαγωγή

Βρίγκας Μιχαήλ Α.Μ.744 Μπράχος Χ. Ευάγγελος Α.Μ.795

Δημιουργία μιας εφαρμογής Java με το NetBeans

Hase οδηγίες χρήσης.

ΚΕΦΑΛΑΙΟ 1. Εισαγωγή στην Python. 1.1 Εισαγωγή

Αντικειμενοστρεφής Προγραμματισμός

Tο περιβάλλον Code::Blocks

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

ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ ΠΡΟΓΡΑΜΜΑ ΜΕΤΑΠΤΥΧΙΑΚΩΝ ΣΠΟΥΔΩΝ

Ανάπτυξη και διανομή ενός έργου Ελεύθερου Λογισμικού

Οδηγός γρήγορης εκκίνησης

Εφαρμογές Υπολογιστών. Κεφάλαιο 4 Λογισμικό Συστήματος

ΟΔΗΓΙΕΣ ΕΓΚΑΤΑΣΤΑΣΗΣ & ΧΡΗΣΗΣ ΟΛΟΚΛΗΡΩΜΕΝΟΥ ΠΕΡΙΒΑΛΛΟΝΤΟΣ ΑΝΑΠΤΥΞΗΣ BloodShed Dev-C++

Ιστορική Αναδρομή Λειτουργικών Συστημάτων (ΛΣ) Εισαγωγή : ο πυρήνας (kernel) / ο φλοιός (shell) Β ΕΠΑΛ

Hase οδηγίες χρήσης.

Τεχνολογία Διοίκησης Επιχειρησιακών Διαδικασιών

6 Εισαγωγή στο Wordpress 3.x

Οδηγός Εγκατάστασης

Υπηρεσία διαμοιρασμού αρχείων

Οδηγίες για την εγκατάσταση του πακέτου Cygwin

Σύντομη εισαγωγή στο λειτουργικό σύστημα Linux

Οδηγός ρυθμίσεων Wi-Fi

Μια εισαγωγή στο Linux με την διανομή Fedora. Βάιος Κολοφωτιάς MSc Informational Systems

Κεφάλαιο 3.1: Λειτουργικά Συστήματα. Επιστήμη ΗΥ Κεφ. 3.1 Καραμαούνας Πολύκαρπος

UTECO ABEE ΒΙΟΜΗΧΑΝΙΚΟΣ & ΝΑΥΤΙΛΙΑΚΟΣ ΑΥΤΟΜΑΤΙΣΜΟΣ

Εισ. Στην ΠΛΗΡΟΦΟΡΙΚΗ. Διάλεξη 4 η. Βασίλης Στεφανής

Ενημερώσεις λογισμικού Οδηγός χρήσης

Οδηγίες Εγκατάστασης και χρήσης προγραμμάτων για την γλώσσα C

Εγκατάσταση του Lazarus

ΚΕΦΑΛΑΙΟ 2 - ΛΟΓΙΣΜΙΚΟ

Εγχειρίδιο συμπίεσης / αποσυμπίεσης αρχείων με το λο ογισμικό WinRAR Υπηρεσία Πληροφορικών Συστημάτων Τομέας Συστημάτων ΥΠΣ ΕΔ/70 21/11/2012

ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΕΣ ΤΕΧΝΙΚΕΣ Σύντομη εισαγωγή στο εργαστήριο

Εγκατάσταση Joomla 1. Στο Π.Σ.Δ. ( 2. Τοπικά 3. Σε δωρεάν Server

ΠΑΝΕΠΙΣΤΗΜΙΟ ΠΑΤΡΩΝ ΠΟΛΥΤΕΧΝΙΚΗ ΣΧΟΛΗ ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ Η/Υ ΚΑΙ ΠΛΗΡΟΦΟΡΙΚΗΣ ΠΜΣ ΕΠΙΣΤΗΜΗ ΚΑΙ ΤΕΧΝΟΛΟΓΙΑ Η/Υ

Ελεύθερο Λογισμικό. Γιάννης Γαϊδαρτζής ΠΕ19 Υπεύθυνος ΚΕ.ΠΛΗ.ΝΕ.Τ. Ρεθύμνου

Οδηγίες εγκατάστασης Δορυφορικής κάρτας Technisat

Ελεύθερο Ανοικτό Λογισμικό

CYGWIN Οδηγίες Χρήσης (Συγγραφέας: Γιώργος ούκας)

Open eclass Πλατφόρμα Ασύγχρονης Τηλεκπαίδευσης

POWERPOINT Είναι το δημοφιλέστερο πρόγραμμα παρουσιάσεων.

ΕΡΓΑΣΤΗΡΙΟ 3: Προγραμματιστικά Περιβάλλοντα και το Πρώτο Πρόγραμμα C

Εγκατάσταση και δοκιμή προγραμμάτων για προγραμματισμό στη C

Εγκατάσταση IIS (Internet Information Server) 7.0 / 7.5 / 8.0

Περιεχόμενα. Περιβάλλον ηλεκτρονικού υπολογιστή...9 Επιφάνεια εργασίας...12 Διαχείριση αρχείων...15 Ιοί Η/Υ...21 Διαχείριση εκτυπώσεων...

Microsoft PowerPoint 2010 Πανεπιστήμιο Κύπρου

Αναπαραγωγή με αρχεία ήχου

Εγκατάσταση του PiNet για διαχείριση εργαστηρίου με Raspberry Pi. Συγγραφέας: Τριχόπουλος Γιώργος Δεκέμβριος 2016

ΟΔΗΓΟΣ ΧΡΗΣΗΣ(ΜΑΝUΑL) ΔΙΑΧΕΙΡΙΣΤΗ-ΧΡΗΣΤΗ.

Σύντομος οδηγός χρήσης Vodafone Mobile Broadband USB Stick Κ4607-Ζ. Σχεδιάστηκε από τη Vodafone

ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ. Δρ. Π. Νικολαΐδου

ΑΣΚΗΣΗ 1: TO ΠΕΡΙΒΑΛΛΟΝ ΕΡΓΑΣΙΑΣ DEV-C++

To περιβάλλον Ανάπτυξης εφαρμογών της Visual Basic 2008 Express Edition

Περιεχόμενα. Κεφάλαιο 1 Εισαγωγή στην Access...9. Κεφάλαιο 2 Χειρισμός πινάκων... 25

Οδηγίες Εγκατάστασης της εφαρμογής Readium και Readium για μαθητές με αμβλυωπία για την ανάγνωση βιβλίων epub σε Υπολογιστή.

ANDROID Προγραμματισμός Εφαρμογών

Σύντομη περιγραφή 5. Για να ξεκινήσετε 6. Οι οθόνες του προγράμματος 8. Εγκατάσταση προγράμματος 6 Δημιουργία κωδικών χρήστη 7

Περιεχόμενα ΓΕΩΠΥΛΗ ΟΔΗΓΙΕΣ ΧΡΗΣΗΣ ΚΕΝΤΡΙΚΟ SITE. ΧΑΡΤΗΣ... 2 Είσοδος στην εφαρμογή «Χάρτης»... 2 Λειτουργίες εφαρμογής «Χάρτης»...

ΕΡΓΑΣΤΗΡΙΟ 3: Προγραμματιστικά Περιβάλλοντα και το Πρώτο Πρόγραμμα C

Στο παράθυρο που θα εµφανιστεί πατήστε το κουµπί Unzip.

Τι χρειάζεται ένας φοιτητής για τη σωστή παρακολούθηση και συμμετοχή στο μαθημα;

Android Studio για Windows

Ενηµερώσεις λογισµικού Οδηγός χρήσης

Κλιμάκιο Πληροφορικής Σεμινάρια για τα λογισμικά κλειστού τύπου Κύκλος Α

Εισαγωγή στην Πληροφορική

Visual Flowchart Γενικά

Οδηγός Βήμα-Βήμα για να εγκαταστήσετε τα Windows 7 στον Η/Υ σας

Εισαγωγή στο προγραμματιστικό περιβάλλον ANSI

Προγραμματισμός Διαχείρισης Συστημάτων Ι

Εισαγωγή στους Υπολογιστές

Εργαστήριο Λειτουργικών Συστημάτων. Minix Overview

ΕΓΚΑΤΑΣΤΑΣΗ ΕΦΑΡΜΟΓΩΝ ΓΙΑ ΠΡΟΣΩΠΙΚΟ ΥΠΟΛΟΓΙΣΤΗ (MS WINDOWS, LINUX, MACOS)

Οδηγίες Εγκατάστασης της MySQL

Ελεύθερο Λογισμικό. Ερευνητική Εργασία Τμήμα Α2-3 ου ΓΕΛ Κομοτηνής Ιανουάριος 2014

Εισαγωγή στην Python. Διάλεξη 0

Η-Υ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ. Εργαστήριο 1 Εισαγωγή στη C. Σοφία Μπαλτζή s.mpaltzi@di.uoa.gr

Εγκατάσταση αρχείων βιβλιοθήκης VHOPE και VHOPE

Εισαγωγικές έννοιες. Ιωάννης Γ. Τσούλος 2014

Ενηµερώσεις λογισµικού Οδηγός χρήσης

Εγκατάσταση του Arduino IDE

Εργαστήριο 1-1 η Άσκηση - Ανάλυση

ΠΛΗΡΟΦΟΡΙΚΗ Ι Εργαστήριο 1 MATLAB ΠΛΗΡΟΦΟΡΙΚΗ Ι ΕΡΓΑΣΤΗΡΙΟ 1. Θέμα εργαστηρίου: Εισαγωγή στο MATLAB και στο Octave

Εγχειρίδιο εγκατάστασης και βασικής παραμετροποίησης σεναρίου εστίασης

Προγραμματισμός Διαχείρισης Συστημάτων Ι

ΜΕΤΑΦΟΡΑ ΑΡΧΕΙΩΝ FTP

1. Τα τμήματα της επιφάνειας εργασίας των Windows

Κεφάλαιο 4: Λογισμικό Συστήματος

Οδηγός Εγκατάστασης και Χρήσης του Arebas Easy

1 η Εργαστηριακή Άσκηση MATLAB Εισαγωγή

ΤΕΧΝΟΛΟΓΙΑ ΛΟΓΙΣΜΙΚΟΥ

Transcript:

ΑΡΙΣΤΟΤΕΛΕΙΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΟΝΙΚΗΣ ΠΟΛΥΤΕΧΝΙΚΗ ΣΧΟΛΗ ΤΜΗΜΑ ΗΛΕΚΤΡΟΛΟΓΩΝ ΜΗΧΑΝΙΚΩΝ ΚΑΙ ΜΗΧΑΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ Υλοποίηση της επικοινωνίας και του γραφικού περιβάλλοντος χειρισμών στη σύνδεση υπολογιστή με τον μικροελεγκτή του συστήματος ελέγχου ανεμογεννήτριας Διπλωματική εργασία του: Ζαμπούρ Νικόλαος Επιβλέπων Καθηγητής: Μαδεμλής Χρήστος ΘΕΣΣΑΛΟΝΙΚΗ 2012

ΑΡΙΣΤΟΤΕΛΕΙΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΟΝΙΚΗΣ ΠΟΛΥΤΕΧΝΙΚΗ ΣΧΟΛΗ ΤΜΗΜΑ ΗΛΕΚΤΡΟΛΟΓΩΝ ΜΗΧΑΝΙΚΩΝ ΚΑΙ ΜΗΧΑΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ Υλοποίηση της επικοινωνίας και του γραφικού περιβάλλοντος χειρισμών στη σύνδεση υπολογιστή με τον μικροελεγκτή του συστήματος ελέγχου ανεμογεννήτριας Διπλωματική εργασία του: Ζαμπούρ Νικόλαος Επιβλέπων Καθηγητής: Μαδεμλής Χρήστος ΘΕΣΣΑΛΟΝΙΚΗ 2012

ΠΡΟΛΟΓΟΣ Η παρούσα διπλωματική εργασία έχει θέμα την «Υλοποίηση της επικοινωνίας και του γραφικού περιβάλλοντος χειρισμών στη σύνδεση υπολογιστή με τον μικροελεγκτή του συστήματος ελέγχου ανεμογεννήτριας». Μετά την ολοκλήρωση της εργασίας αισθάνομαι την ανάγκη να ευχαριστήσω τον κ. Χ. Μαδεμλή, Επίκουρο Καθηγητή της πολυτεχνικής σχολής του Α.Π.Θ., ο οποίος μου εμπιστεύτηκε την εκπόνηση της, και τον κ. Νεκτάριο Καρακάση, υποψήφιο διδάκτορα, για την πολύτιμη βοήθεια του σε όλα τα στάδια της παρούσας διπλωματικής. Τέλος, θα ήθελα να ευχαριστήσω την οικογένεια μου για την συνεχή συμπαράσταση της κατά την εκπόνηση της διπλωματικής εργασίας. i

ΠΕΡΙΛΗΨΗ Το αντικείμενο της παρούσας διπλωματικής χωρίζεται σε δύο μέρη. Πρώτος σκοπός είναι η υλοποίηση της επικοινωνίας μεταξύ του μικροελεγκτή και του υπολογιστή και δεύτερος σκοπός η υλοποίηση ενός γραφικού περιβάλλοντος διεπαφής χρήστη. Για την υλοποίηση της επικοινωνίας χρειάστηκε να δημιουργηθεί μια συμφωνία μεταξύ μικροελεγκτή και υπολογιστή. Η συμφωνία αυτή, που χαρακτηρίζεται και σαν πρωτόκολλο επικοινωνίας, εξασφαλίζει άριστη διαδικασία ανταλλαγής δεδομένων σε προκαθορισμένα χρονικά διαστήματα. Για την υλοποίηση του γραφικού περιβάλλοντος διεπαφής χρήστη, που εξασφαλίζει τον εποπτικό έλεγχο όλου του συστήματος, χρησιμοποιήθηκε το περιβάλλον Qt. Το Qt κάνει χρήση της γλώσσας αντικειμενοστραφούς προγραμματισμού C++ και για αυτό το λόγο ολόκληρη η υλοποίηση του γραφικού περιβάλλοντος διεπαφής χρήστη στηρίχτηκε σε αυτή τη γλώσσα. Αρχικά, γίνεται αναφορά σε ορισμούς βασικών εννοιών που θα χρησιμοποιηθούν σε μεγάλο βαθμό σε όλο το εύρος της διπλωματικής. Έπειτα, κρίθηκε σκόπιμο να γίνουν κάποιες ιστορικές αναδρομές για να μπορέσει ο αναγνώστης να αντιληφθεί την εξέλιξη των εργαλείων και των εννοιών. Ακολουθεί μια εκτενής αναφορά στους τρόπους με τους οποίους γίνεται εγκατάσταση του περιβάλλοντος Qt και των χρήσιμων βιβλιοθηκών της, Qwt και QextSerialPort, σε διάφορες πλατφόρμες. Οι συγκεκριμένες βιβλιοθήκες χρησιμοποιήθηκαν στην τελική υλοποίηση. Στη συνέχεια, πραγματοποιείται μια εισαγωγή σε βασικές μεθόδους προγραμματισμού σε περιβάλλον Qt καθώς και σε βασικά εργαλεία του. Αυτή η εισαγωγή απευθύνεται κυρίως σε αναγνώστες που δεν είναι εξοικειωμένοι με το προγραμματιστικό περιβάλλον του Qt. Σημαντική αναφορά γίνεται και στο κομμάτι της σειριακής επικοινωνίας του μικροελεγκτή TC1798 της Infineon που χρησιμοποιήθηκε στην υλοποίηση. Επίσης, αναπτύσσεται το θεωρητικό υπόβαθρο για την σειριακή επικοινωνία και ο πηγαίος κώδικας μέσω του οποίου ρυθμίστηκε η επικοινωνία για να υπακούει στο πρωτόκολλο επικοινωνίας που δημιουργήθηκε. Τέλος, πριν από τα συμπεράσματα του συνόλου της εργασίας παρουσιάζεται αναλυτικά, μέσω εικόνων αλλά και κομματιών πηγαίου κώδικα, η υλοποίηση της επικοινωνίας από πλευράς υπολογιστή αλλά και η δημιουργία του γραφικού περιβάλλοντος διεπαφής χρήστη σε περιβάλλον Qt. ii

Περιεχόμενα ΚΕΦΑΛΑΙΟ 1... 3 1.1 Εισαγωγή... 3 1.2 Ορισμός του Qt framework... 3 1.3 Σύντομη Ιστορική Αναδρομή για το Qt... 5 1.4 Λογισμικό Ανοιχτού Κώδικα... 8 1.4.1 Ορισμός Λογισμικού Ανοιχτού Κώδικα... 8 1.4.3 Ιστορία εξέλιξης Λογισμικού Ανοιχτού Κώδικα... 10 ΚΕΦΑΛΑΙΟ 2- Εγκατάσταση Περιβάλλοντος και Βιβλιοθηκών Qt... 15 2.1 Εγκατάσταση Qt και βιβλιοθήκης Qwt σε πλατφόρμα Unix... 15 2.1.1 Εγκατάσταση Περιβάλλοντος Qt σε πλατφόρμα Unix... 15 2.1.2 Εγκατάσταση Βιβλιοθήκης Qwt σε πλατφόρμα Unix... 18 2.2 Εγκατάσταση του Qt και της Βιβλιοθήκης Qwt σε Windows Xp/7... 23 2.2.1 Εγκατάσταση του Περιβάλλοντος Qt σε Windows Xp/7... 23 2.2.2 Εγκατάσταση της Βιβλιοθήκης Qwt σε Windows Xp/7... 27 2.3 Χρήση Βιβλιοθήκης QextSerialPort... 31 ΚΕΦΑΛΑΙΟ 3-Γνωριμία με το Qt... 32 3.1 Hello Qt... 32 3.2 Δημιουργώντας Συνδέσεις... 35 3.3 Διαχείριση της Γεωμετρίας και της Θέσης των Widgets... 37 3.4 Εγχειρίδιο Χρήσης... 42 3.5 Δημιουργία Dialogs... 44 3.6 Μηχανισμός Signals and Slots... 54 ΚΕΦΑΛΑΙΟ 4 Ο Μικροελεγκτής... 58 4.1 Γενικά για τον Μικροελεγκτή... 59 4.2 Ασύγχρονη Σειριακή Διεπαφή του TC1798... 61 4.2.1 Περιγραφή του Πυρήνα ASC... 61 4.2.2 Ασύγχρονη Λειτουργία... 62 4.2.3 Πλαίσια Δεδομένων στην Ασύγχρονη Λειτουργία... 63 4.2.3 Γεννήτρια Baud Rate... 64 4.2.4 Διακοπές... 68 1

4.2.5 Διεπαφές των Μονάδων ASC... 70 4.2.6 Εξωτερικοί Καταχωρητές Σχετιζόμενοι με μονάδα ASC0/ASC1... 71 4.2.7 Χάρτης Διευθύνσεων... 76 ΚΕΦΑΛΑΙΟ 5-Η Υλοποίηση... 78 5.1 Γενικά... 79 5.2 Επικοινωνία Υπολογιστή-Μικροελεγκτή... 81 5.2.1 Σύνδεση υπολογιστή μικροελεγκτή... 81 5.2.2 Πρωτόκολλο Επικοινωνίας... 83 5.2.3 Αρχικοποίηση της ασύγχρονης σειριακής επικοινωνίας στο Qt... 86 5.2.3 Υλοποίηση της Λήψεις Δεδομένων από τον Μικροελεγκτή... 88 5.2.4 Υλοποίηση της Αποστολής Δεδομένων προς τον Μικροελεγκτή... 92 5.2.5 Υλοποίηση της Επικοινωνίας του Συστήματος στον Μικροελεγκτή... 98 5.3 Διαδικασία Ανάπτυξης των Διαγραμμάτων... 106 5.4 Ανανέωση Γεωμετρίας του Βασικού Παραθύρου... 112 5.5 Απεικόνιση Δεδομένων σε Οθόνες LCD... 114 5.6 Λειτουργία Πλήκτρων Απεικόνισης Διαγραμμάτων... 115 5.7 Διαδικασία Καθορισμού των Κερδών... 117 ΚΕΦΑΛΑΙΟ 6 - ΣΥΜΠΕΡΑΣΜΑΤΑ... 119 ΒΙΒΛΙΟΓΡΑΦΙΑ... 120 2

ΚΕΦΑΛΑΙΟ 1 1.1 Εισαγωγή Από την αρχαιότητα η αιολική ενέργεια ήταν μια από τις κύριες εκμεταλλεύσιμες μορφές ενέργειες. Η αρχαιότερη μορφή εκμετάλλευσης της αιολικής ενέργειας ήταν τα ιστία (πανιά) των πρώτων ιστιοφόρων πλοίων και πολύ αργότερα οι ανεμόμυλοι στην ξηρά. Ονομάζεται αιολική γιατί στην ελληνική μυθολογία ο Αίολος ήταν ο θεός του ανέμου. Η αιολική ενέργεια αποτελεί σήμερα μια ελκυστική λύση στο πρόβλημα της ηλεκτροπαραγωγής. Το «καύσιμο» είναι άφθονο, αποκεντρωμένο και δωρεάν. Δεν εκλύονται αέρια θερμοκηπίου και άλλοι ρύποι, και οι επιπτώσεις στο περιβάλλον είναι μικρές σε σύγκριση με τα εργοστάσια ηλεκτροπαραγωγής από συμβατικά καύσιμα. Όσο περνάει ο καιρός όλο και περισσότερο γίνεται χρήση αιολικών πάρκων και η αιολική ενέργεια κερδίζει συνεχώς έδαφος σε σχέση με τους συμβατικούς τρόπους παραγωγής ηλεκτρικής ενέργειας. Έτσι έχει δημιουργηθεί η ανάγκη βελτιστοποίησης του ελέγχου συστημάτων ανεμογεννήτριας. Σε αυτό συμβάλλουν σε μεγάλο βαθμό οι μικροελεγκτές. Οι εταιρίες παραγωγής μικροελεγκτών με την πάροδο των χρόνων έχουν δημιουργήσει μικροελεγκτές που είναι προσανατολισμένοι στην οδήγηση κινητήρων. Για να ολοκληρωθεί όμως το κομμάτι του ελέγχου απαιτείται και ένας εύκολος τρόπος εποπτείας του ελέγχου από το χρήστη. Αυτό επιτυγχάνεται με την δημιουργία στοχευμένου γραφικού περιβάλλοντος διεπαφής. Η εξέλιξη των εταιριών ανοιχτού λογισμικού για δημιουργία γραφικού περιβάλλοντος διεπαφής κάνει πλέον την ολοκλήρωση ενός συστήματος ελέγχου πιο προσιτή και πιο ανταγωνιστική. 1.2 Ορισμός του Qt framework Το Qt είναι ένα cross-platform framework που χρησιμοποιείται ευρέως για την ανάπτυξη τόσο γραφικών όσο και μη γραφικών διεπαφών. Κατασκευάστηκε από την Nokia και χρησιμοποιείται σε πολλά προϊόντα μεγάλων εταιριών όπως Philips, Samsung, Siemens κ.α.. 3

Εικόνα 1: Περιβάλλον Qt Το Qt είναι βασισμένο στην γλώσσα προγραμματισμού C++. Αξιοποιεί μια ειδική γεννήτρια κώδικα (code generator) που ονομάζεται Meta Object Compiler ή MOC που μαζί με μακροεντολές προσφέρουν τη δυνατότητα επιπρόσθετου εμπλουτισμού της γλώσσας. Τρέχει σε όλες τις σημαντικές πλατφόρμες ενώ πέρα των γραφικών δυνατοτήτων της, παρέχει την δυνατότητα πρόσβασης σε βάσεις δεδομένων, XML parsing, υποστήριξη δικτυακής επικοινωνίας καθώς και ένα cross-platform API για τον χειρισμό αρχείων. Το περιβάλλον είναι ανοιχτού κώδικα και υποστηρίζεται από πολλούς compilers όπως τον GCC C++ και τον Visual Studio Suite. 4

Εικόνα 2: Λογότυπο του Qt Το Qt είναι συμβατό με τις ακόλουθες πλατφόρμες: Windows Windows CE, Mobile Symbian OS X X11 Embedded Linux Maemo, MeeGo Wayland 1.3 Σύντομη Ιστορική Αναδρομή για το Qt Το Qt framework για πρώτη φορά έγινε διαθέσιμο τον Μάιο του 1995. Η δημιουργία του οφείλεται σε δύο ανθρώπους τον Haavard Nord (Trolltech's CEO) και τον Eirik Chambe-Eng (Trolltech's Chief Troll). Το ενδιαφέρον του Haavard στη δημιουργία γραφικού περιβάλλοντος χρήστη με χρήση της γλώσσας προγραμματισμού C++ ξεκίνησε το 1988 όπου μια Σουηδική εταιρία του ανέθεσε την δημιουργία ενός C++ GUI framework. Δυο χρόνια αργότερα το 1990, ο Haavard και ο Eirik δούλεψαν μαζί για την δημιουργία μιας εφαρμογής βάσεων δεδομένων με χρήση της γλώσσας προγραμματισμού C++ για εικόνες υπερήχων. Το σύστημα που δημιούργησαν χρειαζόταν ένα γραφικό περιβάλλον διεπαφής χρήστη το οποίο θα μπορούσε να τρέξει τόσο σε Windows όσο και σε 5

Macintosh, καθώς και σε Linux. Έτσι αποφάσισαν να ξεκινήσουν την δημιουργία ενός αντικειμενοστραφούς cross-platform GUI framework. Το 1991, ο Haavard, σε συνεργασία με τον Eirik για τον σχεδιασμό, ξεκίνησε να γράφει τις κλάσεις που αργότερα έγιναν το Qt. Μέχρι το 1993, ο Haavard και ο Eirik είχαν καταφέρει να δημιουργήσουν τον πυρήνα γραφικών και είχαν την δυνατότητα να δημιουργήσουν τα δικά τους πρότυπα widgets. Το γράμμα Q του ονόματος Qt προέκυψε λόγω του ότι άρεσε στον Haavard το πως φαινόταν το γράμμα στον emacs του ενώ το γράμμα t βγήκε από το Xt, που είναι τα αρχικά του X toolkit. Η σύσταση της εταιρίας έγινε στις 4 Μαρτίου του 1994, αρχικά ως Quasar Technologies, έπειτα ως Troll tech, και σήμερα ως Trolltech. Το Μάιο του 1995, το Qt 0.90 ανέβηκε στην ιστοσελίδα sunsite.unc.edu. Έξι μέρες αργότερα, η έκδοση αναρτήθηκε και για Linux ως comp.os.linux.announce. Αυτές οι δύο ήταν οι πρώτες εκδόσεις του Qt. Το Qt μπορούσε να χρησιμοποιηθεί σε Windows και Linux, προσφέροντας την ίδια διεπαφή προγραμματισμού εφαρμογών (API) και στις δύο πλατφόρμες. Το Qt ήταν διαθέσιμο με δύο διαφορετικές άδειες: μια εμπορική άδεια που ήταν απαραίτητη για εμπορική ανάπτυξη, και μια ελεύθερου λογισμικού έκδοση που ήταν διαθέσιμη για ανάπτυξη ανοιχτού λογισμικού. Το Μάρτιο του 1996, ο Ευρωπαϊκός Οργανισμός Διαστήματος αγόρασε δέκα εμπορικές άδειες Qt. O Eirik και ο Haavard προσέλαβαν έναν ακόμα προγραμματιστή και στα τέλη του Μάη το Qt 0.97 είχε κυκλοφορήσει ενώ στις 24 Σεπτεμβρίου του ίδιου χρόνου κυκλοφόρησε και η έκδοση 1.0. Μέχρι το τέλος του χρόνου, το Qt έφτασε στην έκδοση 1.1 και οι πελάτες της εταιρίας συνεχώς πλήθαιναν. Το Qt 1.2 ανακοινώθηκε τον Απρίλιο του 1997. Η απόφαση του Matthias Ettrich να χρησιμοποιήσει το Qt για να δημιουργήσει KDE, βοήθησε το Qt να γίνει η συνηθέστερη λύση για δημιουργία γραφικού περιβάλλοντος χρήστη με χρήση γλώσσας προγραμματισμού C++ σε Linux. Το Qt 1.3 εκδόθηκε το Σεπτέμβριο του 1997. Ο Matthias Ettrich έγινε μέλος της εταιρίας Trolltech το 1998 και η τελευταία έκδοση του Qt 1, η 1.40, ανακοινώθηκε το Σεπτέμβριο του ίδιου έτους. Το Qt 2.0 ανακοινώθηκε τον Ιούνιο του 1999. Το Qt 2 είχε μια νέα ανοιχτού λογισμικού άδεια, Q Public License (QPL), η οποία πληρεί τις προϋποθέσεις Open Source Definition. Τον Αύγουστο του 1999, το Qt κέρδισε το βραβείο LinuxWorld για την καλύτερη βιβλιοθήκη/εργαλείο. 6

Το 2000, η Trolltech ανακοίνωσε την έκδοση Qt/Embedded Linux. Σχεδιάστηκε για να τρέχει σε συσκευές που έχουν σαν λειτουργικό σύστημα τα Embedded Linux και παρείχε σύστημα παραθύρων (windows systems) πιο ελαφρύ από το σύστημα παραθύρων X11. Τόσο το Qt/X11 όσο και το Qt/Embedded Linux πλέον προσφέρονταν ευρέως με την άδεια GNU General Public License (GPL) καθώς και με την εμπορική άδεια. Το 2000, η Trolltech ίδρυσε την Trolltech Inc. (USA) και ανακοίνωσε την πρώτη έκδοση της Qtopia, η οποία είναι μια εφαρμογή για κινητά τηλέφωνα και PDAs. Το Qt/Embedded Linux κέρδισε το βραβείο του LinuxWorld " Best Embedded Linux Solution " και το 2001 και το 2002, ενώ το Qtopia Phone κέρδισε το ίδιο βραβείο το 2004. Το Qt 3.0 ανακοινώθηκε το 2001. Το Qt πλέον είναι διαθέσιμο για Windows, Mac OS X, Unix και Linux (desktop και embedded). Το Qt 3 παρείχε 42 νέες κλάσεις και ο κώδικας τους περιλαμβάνει 500000 γραμμές κώδικα. Το Qt 3 ήταν σαφώς καλύτερο σε σχέση με το Qt 2, περιλαμβάνοντας αισθητές βελτιώσεις σε σχέση με την τοπική (local) αλλά και Unicode υποστήριξη. Το καλοκαίρι του 2005, ανακοινώθηκε το Qt 4.0. με περίπου 500 κλάσεις και πάνω από 9000 συναρτήσεις. Το Qt 4 είναι πλέον μεγαλύτερο και πλουσιότερο σε σχέση με τις προηγούμενες εκδόσεις και έχει χωριστεί σε διαφορετικές βιβλιοθήκες, ούτως ώστε οι προγραμματιστές να χρησιμοποιούν μόνο τα κομμάτια που χρειάζονται. Επίσης την ίδια χρονιά, η Trolltech άνοιξε ένα γραφείο εκπροσώπησης στην πρωτεύουσα της Κίνας για να παρέχει υπηρεσίες και τεχνική υποστήριξη στους πελάτες της για τα Qt/Embedded Linux και το Qtopia. Από την ίδρυση της εταιρίας Trolltech, η φήμη του Qt μεγάλωνε και συνεχίζει να μεγαλώνει με αμείωτους ρυθμούς. Αυτή η τόσο μεγάλη επιτυχία οφείλεται στην ποιότητα με την οποία έχει δημιουργηθεί το περιβάλλον του Qt καθώς και στο πόσο απολαυστική είναι η χρήση του. Κατά την τελευταία δεκαετία, το Qt έχει περάσει από το να είναι ένα προϊόν που χρησιμοποιείται από εξειδικευμένους και λίγους προγραμματιστές σε ένα προϊόν που χρησιμοποιείται καθημερινά από χιλιάδες απλούς χρήστες και δεκάδες χιλιάδες προγραμματιστές ανοικτού κώδικα σε όλο τον κόσμο. 7

1.4 Λογισμικό Ανοιχτού Κώδικα Το Qt, όπως αναφέρθηκε στο προηγούμενο υποκεφάλαιο, είναι ένα περιβάλλον ανοιχτού κώδικα. Κρίθηκε σκόπιμο, στο παρόν υποκεφάλαιο, να γίνει αναφορά στον ορισμό του λογισμικού ανοιχτού κώδικα καθώς και στην ιστορική εξέλιξη του. 1.4.1 Ορισμός Λογισμικού Ανοιχτού Κώδικα Το λογισμικό ανοικτού κώδικα (Open Source Software, που συχνά αναφέρεται με τα αρχικά στα αγγλικά OSS) είναι λογισμικό υπολογιστών, μαζί με το οποίο χορηγείται μια άδεια χρήσης, που είναι πολύ διαφορετική από τις άδειες του εμπορικού λογισμικού, όπως του Office Suite της Microsoft ή του λειτουργικού συστήματος Windows. Η άδεια χρήσης ανοιχτού λογισμικού επιτρέπει στον χρήστη να διαβάζει, να αλλάζει καθώς και να βελτιώνει το λογισμικό, ενώ σε ορισμένες περιπτώσεις επιτρέπεται στον χρήστη να πραγματοποιεί και διανομή του λογισμικού. Η Πρωτοβουλία Ανοικτού Κώδικα (Open Source Initiative ή σε συντομογραφία OSI) είναι ένας οργανισμός αφιερωμένος στην προώθηση λογισμικού ανοιχτού κώδικα. Χρησιμοποίησε τους κανονισμούς Debian για το ελεύθερο λογισμικό, απαλλαγμένους από τις ειδικές διατυπώσεις που αφορούσαν το έργο Debian, για τη διαμόρφωση της έκδοσης 1.0 του ορισμού του ανοικτού κώδικα (Open Source Initiative, 2003c). Ο ορισμός του ανοικτού κώδικα στην έκδοση 1.9 αναφέρει τις εξής δέκα προϋποθέσεις, για να μπορεί ένα λογισμικό να ονομάζεται λογισμικό ανοικτού κώδικα: 1. Ελεύθερη διανομή: Η άδεια χρήσης δεν επιτρέπεται να περιορίζει τη διανομή (δωρεά ή πώληση) του λογισμικού σε πακέτα προγραμμάτων, που προέρχονται από διαφορετικές πηγές το καθένα. Για τη διανομή δεν επιτρέπεται να απαιτηθούν δασμοί. 2. Πηγαίος κώδικας: Η διανομή του λογισμικού πρέπει να επιτρέπεται τόσο στη μορφή του πηγαίου κώδικα όσο και σε μεταγλωττισμένη μορφή. Εάν ο πηγαίος κώδικας δεν συμπεριλαμβάνεται στη διανομή, τότε πρέπει να υπάρχει η δυνατότητα να τον αποκτήσει κανείς δωρεάν (π.χ., μέσω του διαδικτύου) ή με δικά του έξοδα. Ο πηγαίος κώδικας δεν επιτρέπεται να έχει γραφεί με 8

ακατανόητο τρόπο ή να βρίσκεται σε κάποια ενδιάμεση μορφή (π.χ., προμεταγλωττισμένος). 3. Παραγόμενο λογισμικό: Αλλαγές και παράγωγα πρέπει να επιτρέπονται. Αυτά θα πρέπει να μπορούν να δημοσιοποιούνται με την ίδια άδεια χρήσης. 4. Ακεραιότητα του πηγαίου κώδικα του συγγραφέα: Η αναδιανομή του τροποποιημένου πηγαίου κώδικα επιτρέπεται μόνο με τον περιορισμό ότι η άδεια χρήσης προβλέπει τη χρησιμοποίηση των επονομαζόμενων patches. Η άδεια χρήσης επιτρέπεται να προστατεύει το όνομα του προγράμματος και να επιτρέπει τη διανομή του τροποποιημένου πηγαίου κώδικα μόνο κάτω από διαφορετικό όνομα. 5. Καμία διάκριση σε βάρος ατόμων ή ομάδων: Η άδεια χρήσης δεν επιτρέπεται να βλάπτει κάποιο άτομο ή κάποια ομάδα ατόμων. 6. Κανένας περιορισμός ως προς το πεδίο εφαρμογής: Το πεδίο εφαρμογής του λογισμικού δεν επιτρέπεται να περιορίζεται από την άδεια χρήσης. 7. Διανομή της άδειας χρήσης: Τα δικαιώματα που αποκτούνται πρέπει να περιέρχονται σε όλα τα άτομα που αποκτούν το λογισμικό, χωρίς αυτά να χρειάζεται να εφοδιαστούν με επιπρόσθετη άδεια χρήσης. 8. Η άδεια χρήσης δεν επιτρέπεται να περιορίζεται σε ένα ορισμένο πακέτο λογισμικού: Τα δικαιώματα που αποκτούνται από ένα πρόγραμμα δεν πρέπει να εξαρτούνται από το αν το πρόγραμμα είναι μέρος ενός πακέτου λογισμικού. Αν το πρόγραμμα αφαιρεθεί από το πακέτο τότε αυτό σαν επακόλουθο δεν πρέπει να έχει τον περιορισμό των δικαιωμάτων. 9. Η άδεια χρήσης δεν επιτρέπεται να εμποδίζει τη συνδιανομή του λογισμικού μαζί με άλλα λογισμικά: Η άδεια χρήσης δεν πρέπει να περιορίζει τη διανομή του λογισμικού μαζί με άλλα προγράμματα (π.χ., να μην αναγκάζει τα άλλα προγράμματα να είναι ανοικτού κώδικα). 10. Η άδεια χρήσης πρέπει να είναι ουδέτερης τεχνολογίας: Κανένας όρος της άδειας χρήσης δεν πρέπει να βασίζεται σε μια ορισμένη τεχνολογία, τρόπο ή διεπαφή. Κάθε άδεια χρήσης που υποβάλλεται στην Πρωτοβουλία Ανοικτού Κώδικα εξετάζεται αν είναι σύμφωνη με τον ορισμό του ανοικτού κώδικα. Αν η άδεια χρήσης 9

συμφωνεί με τον ορισμό, τότε γίνεται δεκτή στον κατάλογο των επονομαζόμενων αδειών χρήσης που είναι πιστοποιημένες από την OSI. 1.4.3 Ιστορία εξέλιξης Λογισμικού Ανοιχτού Κώδικα Στα τέλη του 1970 με αρχές 1980, δημιουργήθηκαν δύο διαφορετικές ομάδες, οι οποίες συντέλεσαν στη δημιουργία του σημερινού κινήματος λογισμικού ανοικτού κώδικα. Στην ανατολική ακτή των Ηνωμένων Πολιτειών, ένας προγραμματιστής του MIT AI Lab, και στη συνέχεια ιδρυτής της μη κερδοσκοπικής εταιρείας Ίδρυμα Ελεύθερου Λογισμικού (Free Software Foundation, FSF), ο Richard Stallman, ανακοίνωσε το 1983 το GNU Project. Το έργο GNU είχε ως στόχο να δημιουργήσει ένα ελεύθερο λειτουργικό σύστημα, και χρησιμοποίησε το GNU General Public License (GPL) ως άδεια χρήσης λογισμικού επιτρέποντας την αναδιανομή και την τροποποίηση του. Εικόνα 3: Το λογότυπο του GNU Project Στη δυτική ακτή των Ηνωμένων Πολιτειών, η Ερευνητική Ομάδα της Επιστήμης της Πληροφορικής (CSRG) του πανεπιστημίου Berkeley στην Καλιφόρνια, βελτίωνε το λειτουργικό σύστημα Unix, και δημιούργησε πολλές εφαρμογές που σύντομα έγιναν μέρος του λειτουργικού συστήματος BSD Unix. Η προσπάθεια χρηματοδοτήθηκε κυρίως από την DARPA Contracts (οργανισμός του Υπουργείου 10

Αμύνης των Ηνωμένων Πολιτειών, που είναι υπεύθυνος για τη δημιουργία νέων τεχνολογιών για στρατιωτική χρήση) αλλά και από ένα στενό κύκλο χάκερ από όλο τον κόσμο, που βοηθούσαν στην εύρεση των προγραμματιστικών σφαλμάτων, στη συντήρηση και στην εξέλιξη του συστήματος. Για αρκετό καιρό το λογισμικό δεν αναδιανεμόταν σε χρήστες εκτός της κοινότητας που δεν είχαν την άδεια της AT&T για το UNIX. Αυτό άλλαξε στα τέλη της δεκαετίας του 1980 όπου το BSD UNIX διανεμήθηκε υπό τη νέα (εκείνη την εποχή) BSD άδεια, που ήταν μία από τις πρώτες άδειες για το ελεύθερο λογισμικό. Δυστυχώς όμως, όποιος ήθελε να χρησιμοποιήσει το BSD UNIX έπρεπε να έχει στην κατοχή του και την άδεια της AT&T καθώς τμήματα του πυρήνα και μερικά απαραίτητα για το λειτουργικό σύστημα προγράμματα, ήταν ιδιόκτητα. Κατά τη διάρκεια του 1991-1992, δύο πολύ σημαντικά γεγονότα συνέβαιναν: i. Στην Καλιφόρνια, ο Bill Jolitz σχεδίαζε τα ελλείποντα τμήματα για την ολοκλήρωση της διανομής Net/2, που χρειάζονταν για να είναι έτοιμη να λειτουργήσει σε μηχανήματα αρχιτεκτονικής i386. Το Net/2 ήταν αποτέλεσμα της προσπάθειας της Ερευνητικής Ομάδας της Επιστήμης της Πληροφορικής (CSRG) να φτιάξει μια έκδοση του BSD UNIX που δε θα περιλαμβάνει τον κατοχυρωμένο κώδικα της AT&T και κατά συνέπεια θα είναι πλήρως ελεύθερο. Ο Jolitz ονόμασε τη δουλειά του 386BSD, η οποία γρήγορα εκτιμήθηκε ανάμεσα στις κοινότητες του BSD και του UNIX. Δεν περιλάμβανε μόνο τον πυρήνα, αλλά και πληθώρα εφαρμογών, συγκροτώντας ένα πλήρες λειτουργικό σύστημα. Το 386BSD διανεμήθηκε υπό την άδεια BSD, το οποίο σήμαινε ότι είναι μια πλήρως ελεύθερη πλατφόρμα λογισμικού. ii. Στην Φινλανδία, ο Linus Torvalds, ένας φοιτητής της επιστήμης των υπολογιστών, που ήταν δυσαρεστημένος με την άδεια της διανομής Minix (η διανομή Minix χρησιμοποιούταν για εκπαιδευτικούς σκοπούς με στόχο την εκμάθηση δημιουργίας λειτουργικών συστημάτων και η άδεια του, επέτρεπε μόνο ακαδημαϊκή χρήση και όχι εμπορική) άρχισε να σχεδιάζει τις πρώτες εκδόσεις του δικού του πυρήνα, που ονομάστηκε Linux. Σύντομα, πολλοί άνθρωποι συνεργάστηκαν για να κάνουν τον πυρήνα όλο και πιο χρηστικό, και πρόσθεσαν πολλές εφαρμογές GNU, 11

δημιουργώντας ένα πλήρες λειτουργικό σύστημα, που ονομάστηκε GNU/Linux. Ο πυρήνας του Linux και οι εφαρμογές του GNU παρέχονταν υπό την άδεια GPL. Το 1993, οι πλατφόρμες GNU/Linux και 386BSD ήταν αρκετές σταθερές. Την ίδια περίοδο, μέλη της κοινότητας 386BSD εξέλιξαν την πλατφόρμα σε μια οικογένεια λειτουργικών συστημάτων βασισμένων στο BSD (NetBSD και FreeBSD). Επιπλέον, ο πυρήνας του Linux επίσης εξελισσόταν και υιοθετήθηκε από πολλές GNU/Linux διανομές όπως το Slackware, το Debian, το Red Hat, το Suse, το Mandrake και πολλές άλλες. Η σημαντικότερη στιγμή για τη διάδοση του ελεύθερου λογισμικού ήρθε το 1998 όταν η Netscape Communications αποφάσισε να ανοίξει τον κώδικα του προγράμματος περιήγησης της, Netscape Communicator. Το πρόγραμμα μπορούσε να αναπτυχθεί εκτός από τους λίγους προγραμματιστές της εταιρείας, και από προγραμματιστές από όλο τον κόσμο. Αυτή η κίνηση αφύπνισε εταιρείες κολοσσούς, όπως η Apple, η Corel και η IBM και τις έκανε να αντιληφθούν τη σοβαρότητα και τα οφέλη του ανοικτού λογισμικού. Εκείνη την περίοδο επίσης, επινοήθηκε ο όρος λογισμικό ανοικτού κώδικα και ιδρύθηκε ο οργανισμός Πρωτοβουλία Ανοικτού Κώδικα (Open Source Initiative, OSI). Μέχρι τότε χρησιμοποιούταν ο όρος ελεύθερο λογισμικό ο οποίος δεν άρεσε στις εταιρείες γιατί παρερμηνευόταν ως δωρεάν λογισμικό και δεν εμπιστεύονταν την ποιότητα του. Σαν αποτέλεσμα, πολλές εταιρείες όλων των μεγεθών, άρχισαν να αναζητούν νέα οικονομικά μοντέλα για να αντεπεξέλθουν στην ανταγωνιστική αγορά της δημιουργίας λογισμικού. Τα μέσα μαζικής ενημέρωσης άρχισαν να δίνουν προσοχή στο μέχρι προηγουμένως περιθωριακό κίνημα του λογισμικού ανοικτού κώδικα, μιας και τώρα αποτελείται όχι μόνο από ιδιώτες και μη κερδοσκοπικές οργανώσεις, αλλά και από μικρές και μεσαίες επιχειρήσεις. 12

Εικόνα 4: Το λογότυπο του OSI Στις μέρες μας, είτε οι υπολογιστές οικιακής χρήσης είτε οι υπερυπολογιστές χρησιμοποιούν λογισμικό ανοιχτού κώδικα. Λειτουργικά συστήματα όπως το GNU/Linux, που είναι λογισμικό ανοιχτού κώδικα, κερδίζουν καθημερινά όλο και μεγαλύτερο μερίδιο στην αγορά. Αιτία αυτού του κέρδους είναι η εύκολη χρήση, η ποιότητα, η πληθώρα προγραμμάτων που είναι διαθέσιμα στην διανομή GNU/Linux Ubuntu καθώς και η μεγάλη κοινότητα που έχει δημιουργηθεί από τους χρήστες του GNU/Linux η οποία βοηθά άμεσα και δωρεάν όποιον χρήστη έχει πρόβλημα με το λογισμικό. Τα σημαντικά ορόσημα της ιστορίας του λογισμικού ανοιχτού κώδικα παρουσιάζονται ακολούθως: 1972: Ο πηγαίος κώδικας αναπαράγεται ελεύθερα στους ακαδημαϊκούς κύκλους. 1976: Ο Καθηγητής Donald E. Knuth από το Stanford διανέμει ελεύθερα το πρόγραμμα μορφοποίησης κειμένου TeX. 1984: Το έργο GNU ιδρύθηκε από τον Richard Stallman. 1985: Δημοσιοποιήθηκε το Μανιφέστο του GNU. 1985: Ιδρύθηκε το Ίδρυμα Ελεύθερου Λογισμικού (Free Software Foundation). 1991: Δημιουργία του ελεύθερου λειτουργικού συστήματος BSD και του Linux. 13

1995: Έγινε διαθέσιμη η πρώτη δημόσια έκδοση του ελεύθερου εξυπηρετητή του παγκόσμιου ιστού Apache. 1996: Πρώτο συνέδριο του λογισμικού ελεύθερης διανομής στο Cambridge, Massachusetts, ΗΠΑ. 1998: Η Netscape δημοσιοποιεί τον κώδικα του φυλλομετρητή της. 1998: Η Christine Peterson και άλλοι εισάγουν την έννοια του ανοικτού κώδικα. 1998: Ιδρύθηκε η Πρωτοβουλία Ανοικτού Κώδικα (Open Source Initiative). 14

ΚΕΦΑΛΑΙΟ 2- Εγκατάσταση Περιβάλλοντος και Βιβλιοθηκών Qt Πριν ξεκινήσει η δημιουργία μιας Qt εφαρμογής χρειάζεται εγκατάσταση του περιβάλλοντος Qt. Μπορεί να χρησιμοποιηθεί η ελεύθερου λογισμικού έκδοση του Qt που είναι διαθέσιμη δωρεάν για όλους. Αν είναι διαθέσιμη η εμπορική έκδοση του Qt, με την αντίστοιχη άδεια, τότε θα περιλαμβάνονται και οδηγίες εγκατάστασης. Η διαδικασία εγκατάστασης διαφέρει ανάλογα με την πλατφόρμα που θα λειτουργήσει το περιβάλλον Qt. Τα Mac Os X και τα Linux είναι βασισμένα στα Unix και για αυτό το λόγο η διαδικασία εγκατάστασης είναι η ίδια. Από την άλλη, τα Windows δεν είναι βασισμένα σε πλατφόρμα Unix οπότε διαφέρουν στην εγκατάσταση. 2.1 Εγκατάσταση Qt και βιβλιοθήκης Qwt σε πλατφόρμα Unix 2.1.1 Εγκατάσταση Περιβάλλοντος Qt σε πλατφόρμα Unix Η εγκατάσταση σε πλατφόρμα Unix μπορεί να πραγματοποιηθεί με δύο τρόπους. Παρακάτω θα αναπτυχθούν αναλυτικά και οι δυο τρόποι εγκατάστασης, διότι είναι πολύ χρήσιμο να υπάρχει εναλλακτικός τρόπος εγκατάστασης σε περίπτωση προβλήματος. Εγκατάσταση μέσω συμπιεσμένου αρχείου: Όλες οι πλατφόρμες εκτός από τα Windows μπορούν να ονομαστούν πλατφόρμες Unix. Παρόλα αυτά, τα Mac OS X διαφέρουν από τα υπόλοιπα διότι δεν χρησιμοποιούν το X Windows System, δημοφιλέστερο ως X11, για την διαχείριση των γραφικών. Έτσι, τα Mac OS X χρειάζονται μια διαφορετική έκδοση Qt. Το απαραίτητο αρχείο(qt- 15

mac-opensource-src-version.tar.gz) μπορεί να κατέβει από την ιστοσελίδα της Trolltech(www.trolletech.com/products /qt/downloads). 1 Όταν το αρχείο έχει κατέβει, η διαδικασία έχει ως εξής: unpack, configure και compile. Ο ευκολότερος τρόπος για να γίνουν αυτά είναι μέσω της κονσόλας εντολών(command prompt). Για την αποσυμπίεση του αρχείου,αφού έχει κατέβει και έχει τοποθετηθεί σε ένα προορισμό (directory), μέσω της κονσόλας εντολών γίνεται αναζήτηση αυτού του προορισμού (με εντολές cd). Έπειτα, γίνεται πληκτρολόγηση στο command prompt της εξής εντολής: tar xvfz qt-edition-opensource-src-version.tar.gz Αυτή η γραμμή κώδικα αποσυμπιέζει και τοποθετεί τα αρχεία που περιέχει το συμπιεσμένο αρχείο σε ένα φάκελο με όνομα qt-edition-opensource-src-version. Έπειτα γίνεται είσοδος στον φάκελο μέσω της εντολής cd: cd qt-edition-opensource-src-version Πριν δημιουργηθούν τα αρχεία εγκατάστασης(building) και γίνει η εγκατάσταση του Qt, χρειάζεται να τρέξει ένα configure script και να γίνουν κάποιες ρυθμίσεις. Το script τρέχει μέσω της εντολής:./configure options Υπάρχουν πολλές επιλογές και ρυθμίσεις για να επιλεγούν. Ο καλύτερος τρόπος για να ξεκινήσει κάποιος είναι να γίνει επιλογή του help, το οποίο παρουσιάζει μία λίστα με τις διαθέσιμες επιλογές. Οι περισσότερες επιλογές συνήθως, πρέπει να οριστούν ως έχουν (default), αλλά καλό είναι να επιλεγεί η prefix επιλογή. Μπορεί να γίνει απευθείας εγκατάσταση του Qt σε φάκελο τοποθετώντας τον προορισμό (path) μετά από την επιλογή. Για παράδειγμα, για να γίνει εγκατάσταση στον προορισμό inst/qt4, που βρίσκεται στο φάκελο home, θα πρέπει να χρησιμοποιηθεί η εντολή: 1 Το Qt εξαρτάται και από άλλα στοιχεία όπως οι compilers και οι βιβλιοθήκες. Οι απαιτήσεις αλλάζουν ανάλογα με το πακέτο της Qt, οπότε αν αντιμετωπιστούν προβλήματα πρέπει να μελετηθεί το αρχείο αναφοράς που είναι διαθέσιμο στη ιστοσελίδα της Qt. 16

./configure prefix ~/inst/qt4 Για την Mac OS X πλατφόρμα είναι κρίσιμο να τονιστούν και δύο επιπλέον επιλογές. Αρχικά, πρέπει να προστεθεί η επιλογή universal που δημιουργεί universal binaries χρησιμοποιώντας το Qt. Αν στα πλάνα του χρήστη είναι να χρησιμοποιηθεί PowerPC-based computer, πρέπει να προστεθεί και η επιλογή sdk. Το configure script αναγκάζει τον χρήστη να δεχτεί το συμβόλαιο ανοιχτού λογισμικού. Όταν τελειώσει το script μπορεί να γίνει build του Qt μέσω της εντολής: make Αυτή η διαδικασία ίσως διαρκέσει αρκετό χρόνο. Αφού ολοκληρωθεί μπορεί να γίνει η εγκατάσταση του Qt μέσω της εντολής 2 : make install Όταν η τελειώσει η εγκατάσταση είναι αναγκαίο να προστεθεί το Qt στο PATH των μεταβλητών περιβάλλοντος (environment variable). Αν έχει χρησιμοποιηθεί ένας compiler που δεν υποστηρίζει rpath, τότε θα πρέπει να γίνει ανανέωση της μεταβλητής περιβάλλοντος (environment variable) LD_LIBRARY_PATH. Αν έγινε χρήση του $HOME/inst/qt4 prefix όταν έτρεξε το configuration script, πρέπει να προστεθεί ο προορισμός $HOME/inst/qt4/bin στο PATH. Αν έγινε χρήση του bash shell τότε θα πρέπει να γίνει αλλαγή της μεταβλητής μέσω της εντολής: export PATH=$HOME/inst/qt4/bin:$PATH Όταν είναι εγκατεστημένες περισσότερες από μία εκδόσεις του Qt τότε η έκδοση που θέλει ο χρήστης να χρησιμοποιήσει πρέπει να είναι πρώτη στο PATH environment variable γιατί το qmake του Qt πρέπει να γνωρίζει που είναι εγκατεστημένο το Qt. 2 Η εντολή εγκατάστασης ίσως χρειαστεί δικαιώματα διαχειριστή (root) για να γίνει εγκατάσταση εκτός φακέλου home. 17

Εγκατάσταση μέσω εκτελέσιμου αρχείου: Η παραπάνω διαδικασία είναι σχετικά πολύπλοκη για χρήστες οι οποίοι δεν είναι εξοικειωμένοι με την πλατφόρμα των Unix. Για αυτόν ακριβώς το λόγο, η ιστοσελίδα του Qt δίνει τη δυνατότητα στους χρήστες να κατεβάσουν το αρχείο Qt_SDK_Lin32_online_v1_2_en.run ή το αρχείο Qt_SDK_Lin32_offline_v1_2_en.run. Αυτά τα αρχεία έχουν κατάληξη.run και αναγνωρίζονται από την πλατφόρμα των Unix ως εκτελέσιμα. Έτσι ο χρήστης επιλέγοντας ένα από τα δύο αρχεία μπορεί να κάνει εγκατάσταση του περιβάλλοντος Qt με ένα απλό διπλό κλικ που παράγει μια πιο τυποποιημένη διαδικασία εγκατάστασης που μοιάζει με την εγκατάσταση οποιουδήποτε απλού λογισμικού. Μέσα σε αυτή τη διαδικασία θα ρωτηθεί ο χρήστης για το αν συμφωνεί με την εγκατάσταση όλων των πακέτων και με τις προϋποθέσεις χρήσης του περιβάλλοντος. Η απάντηση του χρήστη θα πρέπει να είναι καταφατική για να μπορέσει να δοκιμάσει τις δυνατότητες του Qt περιβάλλοντος. Το αρχείο Qt_SDK_Lin32_offline_v1_2_en.run είναι πολύ μεγαλύτερο σε μέγεθος σε σχέση με το αρχείο Qt_SDK_Lin32_online_v1_2_en.run, διότι περιέχει όλα τα αρχεία και τις πληροφορίες σχετικά με την εγκατάσταση του Qt χωρίς να χρειάζεται σύνδεση με το διαδίκτυο για την εγκατάσταση του λογισμικού. Από την άλλη το αρχείο Qt_SDK_Lin32_online_v1_2_en.run κατεβάζει δυναμικά την ώρα της εγκατάστασης αρχεία και πληροφορίες σχετικά με την εγκατάσταση του Qt. Αυτό που πρέπει να τονιστεί είναι πως είτε με το ένα είτε με το άλλο αρχείο το αποτέλεσμα της εγκατάστασης θα είναι το ίδιο και ως προς το περιβάλλον αλλά και ως προς τις δυνατότητες του. 2.1.2 Εγκατάσταση Βιβλιοθήκης Qwt σε πλατφόρμα Unix Η Qwt είναι μία βιβλιοθήκη για τo Qt, η οποία δεν είναι διαθέσιμη στο αρχικό πακέτο βιβλιοθηκών του Qt. Η βιβλιοθήκη Qwt περιέχει κάποια έτοιμα γραφικά καθώς και κλάσεις που είναι κυρίως χρήσιμες για προγράμματα με τεχνικό υπόβαθρο. Εκτός από 2 διαστάσεων διαγράμματα περιέχει εργαλεία και έτοιμα γραφικά όπως θερμόμετρα, καντράν, πυξίδες, ρόδες και κουμπιά για τον έλεγχο ή και την ένδειξη τιμών κ.α.. 18

Η διαδικασία εγκατάστασης αυτής της βιβλιοθήκης είναι σχετικά πολύπλοκη και για αυτό πρέπει να δοθεί ιδιαίτερη προσοχή και δεν πρέπει να παραληφθεί καμιά εντολή. Αρχικά, στην κονσόλα εντολών θα πρέπει να εισαχθεί η εξής εντολή: svn co https://qwt.svn.sourceforge.net/svnroot/qwt/branches/qwt-5.2 Μέσω αυτής της εντολής γίνεται το κατέβασμα του πακέτου εγκατάστασης της βιβλιοθήκης Qwt. Όταν ολοκληρωθεί η παραπάνω διαδικασία γίνεται αναζήτηση του φακέλου qwt- 5.2 μέσω εντολών κονσόλας : cd qwt-5.2./ Σε αυτό το φάκελο υπάρχει ένα αρχείο κειμένου που σχετίζεται με την εγκατάσταση της Qwt σε κάθε λειτουργικό σύστημα ξεχωριστά. Για την ανάγνωση αυτού του κειμένου πληκτρολογείται η γραμμή εντολών: gedit INSTALL Αφού τελειώσει η ανάγνωση του κειμένου πρέπει να κλείσει το αρχείο ούτως ώστε να συνεχιστεί η διαδικασία. Όντας στο φάκελο qwt-5.2, γίνεται εισαγωγή στην κονσόλα εντολών των εξής εντολών: qmake make Οι παραπάνω δύο εντολές δημιουργούν τα αρχεία εγκατάστασης της βιβλιοθήκης Qwt. Μετά το πέρας της διαδικασίας δημιουργίας αρχείων εγκατάστασης γίνεται η εγκατάσταση του Qwt. Για την άρτια εκτέλεση της εντολής αυτού του σκοπού χρειάζονται δικαιώματα διαχειριστή: sudo make install 19

Η εγκατάσταση της Qwt δεν τελειώνει εδώ αλλά χρειάζονται κάποιες ρυθμίσεις για να μπορέσει η βιβλιοθήκη να χρησιμοποιηθεί από το Qt. Όσον αφορά τα παραδείγματα της Qwt ακολουθούν τρεις εντολές: cd examples qmake make Αναγκαία είναι και η δημιουργία νέου αρχείου κειμένου που πρέπει να τοποθετηθεί στον φάκελο ld.so.conf.d. Αυτό το αρχείο κειμένου θα περιέχει τον προορισμό (path) του φακέλου lib του Qwt. cd etc/ld.so.conf.d/ sudo gedit qwt.conf Με την παραπάνω εντολή ανοίγει το νέο αρχείο κειμένου το οποίο είναι κενό. Έτσι πρέπει με μια νέα κονσόλα εντολών να αναζητηθεί ο προορισμός του φακέλου lib. Αυτό γίνεται με τρεις εντολές: cd usr/local/qwt-5.2.2-svn/ cd lib/ pwd Κάτω από την εντολή pwd υπάρχει πλέον ένας προορισμός. Γίνεται αντιγραφή αυτού του προορισμού και επικόλληση μέσα στο αρχείο κειμένου που δημιουργήθηκε παραπάνω όπως φαίνεται στην Εικόνα 5. 20

Εικόνα 5 Αφού γίνει αποθήκευση του αρχείου πρέπει να κλείσει για να συνεχιστεί η διαδικασία. Έπειτα, ακολουθούν δύο ακόμα εντολές : sudo ldconfig ldconfig p grep qwt Κάτω από την παραπάνω εντολή θα πρέπει να εμφανιστούν οι εξής δύο γραμμές: libqwt.so.5 (libc6) => usr/local/qwt-5.2.2-svn/lib/libqwt.so.5 libqwt.so. (libc6) => usr/local/qwt-5.2.2-svn/lib/libqwt.so. Για να μπορέσει να γίνει έλεγχος αν μέχρι στιγμής η διαδικασία κινείται στα σωστά πλαίσια, μπορεί να γίνει χρήση των παραδειγμάτων που περιέχει το πακέτο εγκατάστασης της Qwt βιβλιοθήκης. Έτσι, μέσω των παρακάτω εντολών θα πρέπει να ανοίξει ένα παράθυρο όπως αυτό που απεικονίζεται στην Εικόνα 6. Cd ~/qwt-5.2/ Cd examples/ Cd./bin/./bode 21

Εικόνα 6: Διάγραμμα παραδείγματος Bode Τέλος για να εισάγουμε τα plugins του Qwt στον Qt Creator χρειάζεται να αντιγράψουμε ένα αρχείο με κατάληξη.so στον designer φάκελο του Qt. Cd qwt-5.2/designer/plugins/designer/ Sudo cp lib qwt_designer_plugin.so /opt/qtcreator-2.1.81/bin/designer/ Έτσι, με την ολοκλήρωση των προηγούμενων εντολών θα υπάρχει η δυνατότητα χρήσης των απαραίτητων plugins της Qwt και γενικά όλων των εργαλείων που χρειάζεται για να δημιουργηθεί μια εφαρμογή με τεχνικό υπόβαθρο. 22

2.2 Εγκατάσταση του Qt και της Βιβλιοθήκης Qwt σε Windows Xp/7 2.2.1 Εγκατάσταση του Περιβάλλοντος Qt σε Windows Xp/7 Όπως και στην εγκατάσταση του Qt σε πλατφόρμα Unix έτσι και εδώ η εγκατάσταση του περιβάλλοντος Qt μπορεί να πραγματοποιηθεί με δυο τρόπους. Ο πρώτος τρόπος εγκατάστασης, με σειρά αναφοράς, μπορεί να χαρακτηριστεί ως πιο εύκολος ενώ ο δεύτερος ενδείκνυται σε περιπτώσεις συμπληρωματικής εγκατάστασης της βιβλιοθήκης Qwt. Πρώτος τρόπος: Qt SDK Το πακέτο Qt SDK περιλαμβάνει όλα τα εργαλεία που χρειάζονται για την δημιουργία μιας εφαρμογής για υπολογιστές, για κινητά τηλέφωνα και για ενσωματωμένα συστήματα. Αυτός ο τρόπος εγκατάστασης είναι και ο προτεινόμενος από την εταιρεία διανομής του λογισμικού. Το πακέτο SDK περιλαμβάνει αυτόματη ενημέρωση με τις τελευταίες εκδόσεις του Qt. Το πακέτο SDK περιέχει τα εξής: Qt libraries version 4.8.1 Qt Creator IDE version 2.4.1 Qt development tools Simulator for Symbian phones and the Nokia N9 Qt Mobility version 1.2 Remote compilers Για την έναρξη της διαδικασίας εγκατάστασης θα πρέπει να κατέβει από την επίσημη ιστοσελίδα του Qt (http://qt.nokia.com/downloads/ ) το εκτελέσιμο αρχείο που αντιστοιχεί σε πλατφόρμα Windows. Εκεί μπορεί να παρατηρηθεί πως υπάρχουν δύο διαφορετικά αρχεία. Το αρχείο QtSdk-online-win-x86-v1_2_1.exe, που είναι και το μικρότερο σε μέγεθος, έχει ως απαραίτητη προϋπόθεση την ύπαρξη δικτύου για την επιτυχή εγκατάσταση του λογισμικού. Από την άλλη, το αρχείο QtSdk-offline-win-x86- v1_2_1.exe είναι μεγαλύτερο σε μέγεθος αλλά δεν απαιτεί ύπαρξη δικτύου για την 23

ολοκλήρωση της εγκατάστασης. Η διαδικασία εγκατάστασης και των δύο αρχείων είναι το ίδιο εύκολη και δεν υπάρχει ανάγκη κάποιων επιπλέον ρυθμίσεων αρκεί να ακολουθηθούν οι οδηγίες. Αυτό που οφείλεται να τονιστεί είναι πως είτε με το ένα είτε με το άλλο αρχείο το αποτέλεσμα της εγκατάστασης θα είναι το ίδιο και ως προς το περιβάλλον αλλά και ως προς τις δυνατότητες που προσφέρονται στο χρήστη. Δεύτερος τρόπος Αυτός ο τρόπος εγκατάστασης είναι λίγο πιο πολύπλοκος αλλά αξίζει να αναφερθεί διότι αργότερα διευκολύνει αρκετά την διαδικασία εγκατάστασης της βιβλιοθήκης Qwt. Αρχικά θα πρέπει να κατέβουν και πάλι από την επίσημη ιστοσελίδα του Qt(http://qt.nokia.com/downloads/) τα αρχεία εγκατάστασης: Γίνεται επιλογή του "Qt libraries 4.8.0 for Windows (mingw 4.4, 354 MB)", όπου και πρέπει να κατέβουν δύο αρχεία το qt-everywhere-opensource-src- 4.8.0.zip (350 MB) και το MinGW-gcc440_1.zip (30 MB). Γίνεται η επιλογή του "Qt Creator 2.4.0 for Windows (53 MB)" και κατεβαίνει το αρχείο qt-creator-win-opensource-2.4.0.exe. Αφού πλέον όλα τα αρχεία είναι διαθέσιμα για την εγκατάσταση πρέπει να εφαρμοστούν τα εξής πέντε βήματα: 1. Αποσυμπιέζεται το αρχείο MinGW-gcc440_1.zip και τοποθετείται στον προορισμό C:\minigw. 2. Σε αυτό το βήμα θα πρέπει να τοποθετηθεί ο προορισμός C:\mingiw\bin στη μεταβλητή συστήματος Path. Για να υλοποιηθεί αυτό θα πρέπει να ακολουθηθεί ο εξής προορισμός Control Panel/System and Security/System. Εκεί επιλέγεται το Advanced System Settings και μετά το Enviromental Variables. Στην λίστα με τα System Variables γίνεται διπλό κλικ στη επιλογή PATH και προστίθεται ο προορισμός ";C:\minigw\bin" χωρίς τα εισαγωγικά όπως φαίνεται στην Εικόνα 7. 24

Εικόνα 7: Ρύθμιση μεταβλητών συστήματος 3. Επανεκκίνηση του υπολογιστή. 4. Εγκατάσταση του εκτελέσιμου αρχείου qt-win-opensource-4.8.0- mingw.exe. 5. Εγκατάσταση του εκτελέσιμου αρχείου qt-creator-win-opensource- 2.4.0.exe. Σε αυτό το βήμα υπάρχει μια πολύ σημαντική λεπτομέρεια. Θα πρέπει στην διαδικασία εγκατάστασης να μην επιλεγεί η εγκατάσταση του πακέτου mingw. Μετά από την πραγματοποίηση της εγκατάστασης του Qt θα πρέπει να γίνει εκκίνηση του προγράμματος Qt Creator, το οποίο πλέον έχει προστεθεί στη λίστα προγραμμάτων. Στα μενού που υπάρχουν, αναζητείται ο προορισμός 25

tools/options/build & run/ και επιλέγεται η ετικέτα Tool chains. Στην επιλογή Manual που υπάρχει επιλέγεται το Add και έπειτα το MinGW. Στον προορισμό που εμφανίζεται κάτω στην οθόνη τοποθετείται ο προορισμός C:\mingw\bin\gcc.exe όπως φαίνεται στην Εικόνα 8. Εικόνα 8: Ρύθμιση Tool Chains Τέλος, θα πρέπει να γίνει μια τελευταία ρύθμιση στο Qt Creator. Πάλι θα γίνει αναζήτηση του προορισμού tools/options/build & run/ με τη διαφορά ότι τώρα θα επιλεγεί η ετικέτα Qt Versions. Στην επιλογή Manual που υπάρχει επιλέγεται το Add και προστίθεται ο προορισμός C:\qt\4.8.0\bin\qmake.exe όπως φαίνεται στην Εικόνα 9. Μετά από όλα αυτά τα βήματα και τις ρυθμίσεις ο χρήστης μπορεί να δοκιμάσει τις δυνατότητες του Qt. 26

Εικόνα 9: Ρύθμιση qmake 2.2.2 Εγκατάσταση της Βιβλιοθήκης Qwt σε Windows Xp/7 Η διαδικασία εγκατάστασης που θα περιγραφεί στην παρούσα παράγραφο έχει ως προϋπόθεση πως υπάρχει ήδη εγκατεστημένο πακέτο Qt. Αυτό το πακέτο πρέπει επίσης να εγκαταστάθηκε σύμφωνα με τις οδηγίες του δεύτερου τρόπου της προηγούμενης υποπαραγράφου. Το πρώτο βήμα για να ξεκινήσει η εγκατάσταση είναι να κατέβει από την ιστοσελίδα του Qwt (http://qwt.sourceforge.net/) η εκάστοτε έκδοση της βιβλιοθήκης Qwt σε συμπιεσμένη μορφή (έστω Qwt-6.0.1). Όταν η διαδικασία κατεβάσματος της βιβλιοθήκης Qwt ολοκληρωθεί πρέπει να ακολουθηθούν τα παρακάτω 15 βήματα: 1. Αποσυμπίεση του συμπιεσμένου αρχείου που κατέβηκε σε έναν προσωρινό φάκελο. Για το παρόν σύγγραμμα επιλέχτηκε ο προορισμός C:\temp. 2. Άνοιγμα του Qt Command Prompt μέσω του προορισμού start/programs/qt by Nokia v4.8.0 (MinGW OpenSource)/Qt 4.8.0 Command Prompt. 27

3. Όντας στο παράθυρο εντολών (command prompt) γίνεται αναζήτηση του προορισμού C:\temp\qwt-6.0.1 μέσω της εντολής cd και πληκτρολογείται η εντολή: qmake qwt.pro. 4. Στο παράθυρο εντολών εισάγεται η εντολή: mingw32-make. 5. Όταν τελειώσει το compile που πραγματοποιείται λόγω της παραπάνω εντολής εισάγεται στο παράθυρο εντολών η εντολή εγκατάστασης: mingw32-make install. 6. Αφού ολοκληρωθεί η εντολή εγκατάστασης θα πρέπει να έχει δημιουργηθεί ο φάκελος Qwt-6.0.1 στον προορισμό C:\Qwt-6.0.1. 7. Πάλι, όντας στο παράθυρο εντολών γίνεται εισαγωγή της εντολής: qmake -set QMAKEFEATURES C:\Qwt-6.0.1\features. 8. Μετά τα παραπάνω βήματα έχει ολοκληρωθεί το κομμάτι που αφορά το παράθυρο εντολών του Qt οπότε μπορεί να κλείσει. 9. Θα πρέπει να ακολουθηθεί ο εξής προορισμός Control Panel/System and Security/System. Εκεί επιλέγεται το Advanced System Settings και μετά το Enviromental Variables. 10. Στο πλαίσιο User variables επιλέγεται New. Το κενό με όνομα variable name συμπληρώνεται με το: QT_PLUGIN_PATH και το κενό variable value συμπληρώνεται με το: C:\Qwt-6.0.1\plugins όπως στην Εικόνα 10. Εικόνα 10: Νέο User Variable 28

11. Γίνεται προσθήκη προορισμού ;C:\Qwt-6.0.1\lib στη μεταβλητή συστήματος PATH όπως φαίνεται στην Εικόνα 11. Μετά επιλέγουμε OK για να κλείσουν όλα τα ανοιχτά παράθυρα. Εικόνα 11: Εισαγωγή προορισμού στο PATH για την λειτουργία του Qwt. 12. Σε αυτό το σημείο πρέπει να ανοίξει το αρχείο qtvars.bat, που βρίσκεται στον προορισμό C:\Qt\4.3.4\bin με χρήση κάποιου επεξεργαστή κειμένου. 13. Στο αρχείο qtvars.bat εισάγεται κάτω από τις εντολές set PATH η εντολή: set PATH=%PATH%;C:\Qwt-6.0.1\lib.(Εικόνα 12) 14. Στο αρχείο qtvars.bat κάτω από τις εντολές echo η εντολή: echo -- adding C:\Qwt-6.0.1\lib.(Εικόνα 12) 29

Εικόνα 12: Αρχείο qtvars.bat 15. Αποθήκευση και κλείσιμο του αρχείου qtvars.bat. Έπειτα από τα παραπάνω δεκαπέντε βήματα υπάρχει η δυνατότητα ανάπτυξης εφαρμογής χρησιμοποιώντας και τα εργαλεία που διαθέτει η βιβλιοθήκη Qwt. Σημαντική σημείωση είναι πως πρέπει μετά την δημιουργία οποιουδήποτε project να εισάγεται στο αρχείο.pro η εντολή CONFIG +=qwt. Με αυτή την εντολή γίνεται και τελειωτικά διαθέσιμη η βιβλιοθήκη Qwt στο εκάστοτε project. 30

2.3 Χρήση Βιβλιοθήκης QextSerialPort Η Βιβλιοθήκη QextSerialPort παρέχει διεπαφή μέσω σειριακών θυρών στις εφαρμογές που σχεδιάζονται στο περιβάλλον Qt. Η συγκεκριμένη βιβλιοθήκη είναι η καλύτερη Όσον αφορά την σειριακή επικοινωνία σε σχέση με άλλες παρόμοιες και υποστηρίζει Mac OS X, Windows, FreeBSD. και Linux. Το πακέτο της βιβλιοθήκης μπορεί να κατέβει σε συμπιεσμένη μορφή μέσω της ιστοσελίδας: http://code.google.com/p/qextserialport/. Το αρχείο θα πρέπει να αποσυμπιεστεί σε ένα προορισμό, π.χ. Temp, ούτως ώστε να είναι δυνατή η χρήση του φακέλου που περιέχει. Μέσα στο φάκελο μπορεί κανείς να διακρίνει ένα αρχείο κειμένου με λεπτομερείς οδηγίες χρήσης της βιβλιοθήκης. Η ευκολότερη αλλά και η καλύτερη μέθοδος χρήσης της βιβλιοθήκης είναι η εξής: Τοποθετείται ο φάκελος qextserialport-1.2beta2 που δημιουργήθηκε μετά την αποσυμπίεση σε προορισμό όπως C:\Users\UserName\Desktop\ 3. Εισάγεται η εντολή include(c:\users\username\desktop\qextserialport- 1.2beta2\src\qextserialport.pri) στο αρχείο.pro του project που θέλουμε να χρησιμοποιήσουμε την βιβλιοθήκη QextSerialPort. Μετά από αυτά τα βήματα υπάρχει πλέον η δυνατότητα χρήσης όλων των εργαλείων της βιβλιοθήκης QextSerialPort. Ο παραπάνω τρόπος χρήσης της βιβλιοθήκης QextSerialPort μπορεί να χρησιμοποιηθεί στα λειτουργικά συστήματα που αναφέρθηκαν παραπάνω και να είναι αξιόπιστος. 3 Το UserName είναι το όνομα του εκάστοτε υπολογιστή. 31

ΚΕΦΑΛΑΙΟ 3-Γνωριμία με το Qt Σε αυτό το κεφάλαιο θα γίνει μια παρουσίαση του πως συνδυάζεται η γλώσσα προγραμματισμού C++ με την λειτουργικότητα που παρέχεται από το Qt για την δημιουργία μικρών εφαρμογών με γραφική διεπαφή χρήστη (GUI). Επιπροσθέτως, το παρόν κεφάλαιο θα κάνει μια εισαγωγή σε δύο πολύ βασικές έννοιες του Qt το signals and slots και το layouts. 3.1 Hello Qt Στον χώρο του προγραμματισμού η πρώτη εφαρμογή που συνήθως εκτελείται σε πρώτη φάση από έναν νέο προγραμματιστή όταν βρίσκεται σε νέο προγραμματιστικό περιβάλλον είναι το Hello World. Έτσι σε αυτή την παράγραφο θα γίνει παρουσίαση της πιο απλής εφαρμογής Hello Qt. Αρχικά, θα γίνει μία σειρά προς σειρά ανάλυση του κώδικα και έπειτα θα γίνει αναφορά στον τρόπο που γίνεται το compile και το run. 1 #include <QApplication> 2 #include <QLabel> 3 int main(int argc, char *argv[]) 4 { 5 QApplication app(argc, argv); 6 QLabel *label = new QLabel("Hello Qt!"); 7 label->show(); 8 return app.exec(); 9 } Στις γραμμές 1 και 2 διακρίνονται οι ορισμοί των κλάσεων QApplication και QLabel. Για κάθε κλάση Qt υπάρχει και ένα αντίστοιχο αρχείο header με το ίδιο όνομα και κεφαλοποίηση. Μετά τον ορισμό ενός header σε ένα πρόγραμμα είναι δυνατό να χρησιμοποιηθεί η έτοιμη από το Qt αντίστοιχη κλάση για δημιουργία αντικειμένων. 32

Στη γραμμή 5 του κώδικα ορίζεται το αντικείμενο app της κλάσης QApplication που χειρίζεται το σύνολο των πόρων της εφαρμογής. Ο constructor της κλάσης QApplication χρειάζεται τα argc και argv για την υποστήριξη κάποιων ορισμάτων της γραμμής εντολών του Qt. Στην γραμμή 6 δημιουργείται ένα widget της κλάσης QLabel που εμφανίζει το μήνυμα Hello Qt!. Στο Qt καθώς και στην ορολογία της πλατφόρμας των Unix, το widget είναι ένα στοιχείο μιας γραφικής διεπαφής χρήστη (GUI) που εμφανίζει μια διάταξη πληροφοριών ευμετάβλητη από το χρήστη, όπως ένα παράθυρο ή ένα πλαίσιο κειμένου. Ο όρος προέρχεται από το window gadget και είναι το ισοδύναμο των δύο control και container στην ορολογία των Windows. Τα κουμπιά (buttons), τα μενού (menus) καθώς και οι μπάρες κύλισης (scroll bars) είναι κάποια άλλα παραδείγματα των widgets. Τα widgets μπορούν να περιέχουν και άλλα widgets. Για παράδειγμα, ένα βασικό παράθυρο μιας εφαρμογής (window application) συνήθως περιλαμβάνει ένα QMenuBar, που είναι κλάση που εμφανίζει γραμμές μενού, κάποια QToolBars που είναι γραμμές εργαλείων και κάποια άλλα widgets. Οι περισσότερες εφαρμογές χρησιμοποιούν το QMainWindow ή το QDialog ως βασικό παράθυρο της εφαρμογής (window application), αλλά το Qt είναι τόσο ευέλικτο που μπορεί να χρησιμοποιήσει οποιοδήποτε widget σαν παράθυρο. Η γραμμή 7 κάνει ορατή την ετικέτα (label) με το μήνυμα. Όταν δημιουργείται κάποιο widget δεν είναι ορατό ούτως ώστε ο προγραμματιστής να κάνει τις ρυθμίσεις που χρειάζονται και έπειτα με δική του εντολή να γίνει ορατό ή να παραμείνει ως έχει. Στην γραμμή 8 η εφαρμογή περνάει τον έλεγχο στο ίδιο το Qt. Σε αυτό το σημείο η εφαρμογή μπαίνει σε μιας μορφής κατάσταση αναμονής, όπου το πρόγραμμα περιμένει από τον χρήστη να ενεργήσει με κάποιον τρόπο. Ένας από αυτούς τους τρόπους είναι να πατήσει ένα κουμπί στο πληκτρολόγιο ή να κάνει κάποιο κλικ με το ποντίκι του. Οι ενέργειες του χρήστη παράγουν σήματα, στα οποία ανταποκρίνεται το πρόγραμμα, συνήθως εκτελώντας μία ή περισσότερες συναρτήσεις. Για παράδειγμα, όταν ο χρήστης πιέζει το πλήκτρο του ποντικιού και έπειτα το αφήνει προκαλεί μία δράση στην οποία πρέπει να αντιδράσει το πρόγραμμα. Από αυτή την άποψη, οι GUI εφαρμογές διαφέρουν δραστικά από τα συμβατικά προγράμματα, στα οποία συνήθως γίνεται είσοδος των δεδομένων, παράγονται τα αποτελέσματα και τερματίζεται η εφαρμογή χωρίς ανθρώπινη παρέμβαση. 33

Για την απλότητα του προγράμματος, δεν χρειάζεται να γίνει delete του αντικειμένου QLabel στο τέλος της main (). Αυτή η διαρροή μνήμης είναι αβλαβής σε ένα τόσο μικρό πρόγραμμα, αφού η μνήμη θα πρέπει να ανακτηθεί από το λειτουργικό σύστημα όταν το πρόγραμμα τερματίσει. Έπειτα από την σωστή εγκατάσταση του Qt, είναι δυνατόν ο παραπάνω κώδικας να τρέξει και να παράγει το αποτέλεσμα που φαίνεται στην Εικόνα 13. Οι παραπάνω γραμμές κώδικα θα πρέπει να εισαχθούν σε ένα αρχείο κειμένου. Αυτό το αρχείο κειμένου θα πρέπει να αποθηκευτεί με το όνομα hello.cpp και να εισαχθεί μέσα σε ένα φάκελο με το όνομα hello. Εικόνα 13: Hello στα Linux. Με την χρήση του Qt command promt θα πρέπει να αναζητηθεί ο προορισμός του φακέλου hello μέσω της εντολής cd. Εκεί θα ακολουθήσει η εξής εντολή που δημιουργεί ένα ανεξάρτητης πλατφόρμας αρχείο project (hello.pro): qmake project Για την δημιουργία ενός makefile αρχείου συγκεκριμένης πλατφόρμας γίνεται εισαγωγή της εξής εντολής: qmake hello.pro Αφού έχουν δημιουργηθεί τα παραπάνω αρχεία η διαδικασία συνεχίζει πληκτρολογώντας την εντολή make που κάνει build το πρόγραμμα. Για να μπορεί να τρέξει το πρόγραμμα θα πρέπει να αναζητηθεί ο φάκελος debug που περιέχει το εκτελέσιμο αρχείο και να πληκτρολογηθεί η εντολή hello στα Windows,./hello στα Unix και open hello.ap στα Mac OS X. Για να τερματιστεί το πρόγραμμα μπορεί να πατηθεί το εικονίδιο κλεισίματος του παραθύρου που υπάρχει στην μπάρα του τίτλου. 34

Πριν από το κλείσιμο της συγκεκριμένης παραγράφου καλό θα ήταν να γίνει μια επίδειξη χρήσης εντολών HTML στο Qt. Μπορεί να γίνει αντικατάσταση της γραμμής εντολών 6: QLabel *label = new QLabel("Hello Qt!"); με την γραμμή εντολών: QLabel *label = new QLabel("<h2><i>Hello</i> " "<font color=red>qt!</font></h2>"); Όταν ξαναγίνει build της εφαρμογής και ξανατρέξει το πρόγραμμα το αποτέλεσμα θα πρέπει να μοιάζει με την Εικόνα 14. Όπως φαίνεται από αυτή την εικόνα ο προγραμματιστής μπορεί να αλλάξει την φωτεινότητα, την γραμματοσειρά και το πάχος των γραμμάτων όπως γίνεται και σε ένα HTML αρχείο. Εικόνα 14: Hello μετά από HTML formatting 3.2 Δημιουργώντας Συνδέσεις Σε αυτή τη παράγραφο θα αναλυθεί ένα παράδειγμα που σχετίζεται με το πώς ανταποκρίνεται το πρόγραμμα σε ενέργειες του χρήστη. Η εφαρμογή αποτελείται από ένα κουμπί που ο χρήστης μπορεί να κάνει κλικ για να κλείσει το πρόγραμμα. Ο πηγαίος κώδικας έχει πολλές ομοιότητες με εκείνον της προηγούμενης παραγράφου, εκτός από το ότι εδώ χρησιμοποιείται ένα QPushButton αντί του QLabel ως κύριο widget, και ότι υπάρχει μια σύνδεση μιας ενέργειας του χρήστη (το πάτημα ενός κουμπιού), με ένα κομμάτι του κώδικα. 35

1 #include <QApplication> 2 #include <QPushButton> 3 int main(int argc, char *argv[]) 4 { 5 QApplication app(argc, argv); 6 QPushButton *button = new QPushButton("Quit"); 7 QObject::connect(button, SIGNAL(clicked()), 8 &app, SLOT(quit())); 9 button->show(); 10 return app.exec(); 11 } Εικόνα 15: Εφαρμογή Quit Τα widgets του Qt εκπέμπουν σήματα για να δείξουν ότι μια ενέργεια του χρήστη ή μια αλλαγή της κατάστασης έχει συμβεί.. 4 Για παράδειγμα, το QPushButton εκπέμπει ένα σήμα clicked() όταν ο χρήστης κάνει κλικ στο κουμπί. Ένα σήμα μπορεί να συνδέεται με μια συνάρτηση (που ονομάζεται slot), έτσι ώστε όταν το σήμα εκπέμπεται, το slot εκτελείται αυτόματα. Στο παρόν παράδειγμα, γίνεται σύνδεση του σήματος clicked() του κουμπιού με το slot quit() του αντικειμένου της κλάσης QApplication. Το SIGNAL() και το SLOT() είναι μακροεντολές που αποτελούν μέρος της σύνταξης του προγράμματος. Για να γίνει το build της εφαρμογής χρειάζονται ορισμένες εντολές στο command promt του Qt. Αρχικά αποθηκεύεται ο παραπάνω κώδικας σε ένα αρχείο κειμένου. Αυτό το αρχείο κειμένου θα πρέπει να αποθηκευτεί με το όνομα quit.cpp και να εισαχθεί μέσα σε ένα φάκελο με το όνομα quit. Έπειτα θα πρέπει να τρέξει η εντολή 4 Τα σήματα του Qt δεν έχουν σχέση με τα σήματα της πλατφόρμας των Unix. 36

qmake μέσω του command prompt του Qt μέσα στο φάκελο quit. Οι εντολές που ακολουθούν είναι απαραίτητες για την δημιουργία των αρχείων και για την εκτέλεση της εφαρμογής. qmake project qmake quit.pro Αφού τρέξει το πρόγραμμα θα εμφανιστεί ένα παράθυρο που μοιάζει με την Εικόνα 15. Αν πατηθεί το κουμπί Quit, ή αν πατηθεί από το πληκτρολόγιο το πλήκτρο Space, τότε θα τερματιστεί η εφαρμογή. 3.3 Διαχείριση της Γεωμετρίας και της Θέσης των Widgets Σε αυτό το τμήμα, θα δημιουργήσουμε μια μικρή εφαρμογή-παράδειγμα, που δείχνει πώς να χρησιμοποιούνται σχεδιαγράμματα για τη διαχείριση της γεωμετρίας των widgets σε ένα παράθυρο και πώς να χρησιμοποιούνται τα σήματα και τα slot για το συγχρονισμό δύο widgets. Η εφαρμογή, που φαίνεται και στην Εικόνα 16, ζητά την ηλικία του χρήστη, την οποία μπορεί ο χρήστης να εισάγει με δύο τρόπους, είτε μέσω μπάρας είτε μέσω του spin box. Εικόνα 16: Η εφαρμογή εισαγωγής ηλικίας Η εφαρμογή περιλαμβάνει τρία widgets: το QSpinBox, το QSlider, και το QWidget. Το QWidget είναι το βασικό παράθυρο της εφαρμογής. Το QSpinBox και το QSlider είναι εσωτερικά widget του QWidget, δηλαδή είναι παιδιά widget του QWidget. Εναλλακτικά, μπορεί να αναφερθεί ο ορισμός πως το QWidget είναι widget 37

γονιός του QSpinBox και του QSlider. Το QWidget δεν έχει κάποιο άλλο widget γονιό, διότι χρησιμοποιείται σαν το υψηλότερου επιπέδου παράθυρο. Οι constructors για το QWidget και όλες οι υποκλάσεις παίρνουν την παράμετρο QWidget * που ορίζει το widget γονιό. Ο κώδικας του συγκεκριμένου παραδείγματος είναι ο ακόλουθος: 1 #include <QApplication> 2 #include <QHBoxLayout> 3 #include <QSlider> 4 #include <QSpinBox> 5 int main(int argc, char *argv[]) 6 { 7 QApplication app(argc, argv); 8 QWidget *window = new QWidget; 9 window->setwindowtitle("enter Your Age"); 10 QSpinBox *spinbox = new QSpinBox; 11 QSlider *slider = new QSlider(Qt::Horizontal); 12 spinbox->setrange(0, 130); 13 slider->setrange(0, 130); 14 QObject::connect(spinBox, SIGNAL(valueChanged(int)), 15 slider, SLOT(setValue(int))); 16 QObject::connect(slider, SIGNAL(valueChanged(int)), 17 spinbox, SLOT(setValue(int))); 18 spinbox->setvalue(35); 19 QHBoxLayout *layout = new QHBoxLayout; 20 layout->addwidget(spinbox); 21 layout->addwidget(slider); 22 window->setlayout(layout); 23 window->show(); 24 return app.exec(); 25 } Στην γραμμή 8 του παραπάνω κώδικα γίνεται ο ορισμός του αντικειμένου window της κλάσης QWidget, το οποίο λειτουργεί ως το βασικό παράθυρο της εφαρμογής. Στην 38

γραμμή 9 χρησιμοποιείται η συνάρτηση setwindowtitle() που θέτει σαν τίτλο του παραθύρου το περιεχόμενο του κειμένου που είναι ανάμεσα από τις αποστρόφους. Όπως μπορεί εύκολα να παρατηρηθεί, στις γραμμές 10 και 11 δημιουργούνται αντίστοιχα αντικείμενα των κλάσεων QSpinBox και QSlider, ενώ στις γραμμές 12 και 13 ορίζεται το εύρος των τιμών τους. Μπορεί μετά βεβαιότητας να απορριφτεί πως κάποιος χρήστης θα έχει ηλικία μεγαλύτερη των 130 χρόνων οπότε δε χρειάζεται να συμπεριληφθούν τόσο μεγάλες τιμές. Θα μπορούσε να εισαχθεί το αντικείμενο window στους constructors των αντικειμένων των QSpinBox και QSlider για να οριστεί πως το window είναι το widget γονιός των δύο άλλων αντικειμένων, αλλά αυτή η δουλειά θα γίνει αυτόματα από το σύστημα layout. Οι δύο συναρτήσεις QObject::connect() που ορίζονται από την γραμμή 14 μέχρι την γραμμή 17 συγχρονίζουν το spin box με το slider ούτως ώστε να έχουν πάντα την ίδια τιμή. Όποτε αλλάζει η τιμή του ενός widget, το σήμα valuechanged(int) πυροδοτείται, και το slot setvalue(int) του άλλου widget καλείται με την νέα πλέον τιμή. Στην γραμμή 18 το πρόγραμμα θέτει σαν προεπιλεγμένη τιμή του spin box την τιμή 35. Όταν αυτό συμβαίνει, το QSpinBox ενεργοποιεί το σήμα valuechanged(int) και στη θέση της μεταβλητής int τοποθετείται η τιμή 35. Αυτή η τιμή της int μεταβλητής περνάει μέσω του slot setvalue(int) στο αντικείμενο του QSlider's, και θέτει και σε αυτόν την τιμή ολίσθησης 35. Το slider έπειτα, εκπέμπει ένα σήμα valuechanged(int) λόγω του ότι άλλαξε η δική του αξία, πυροδοτώντας το slot του spin box setvalue(int). Από αυτή τη στιγμή, δεν εκπέμπεται κανένα σήμα, μέχρι η τιμή του spin box να γίνει 35. Αυτό αποτρέπει την άπειρη αναδρομή. Η Εικόνα 17 συνοψίζει την κατάσταση. 39

Εικόνα 17: Σύνδεση αλλαγών τιμών μεταξύ δύο widgets Ο κώδικας που περιλαμβάνεται μεταξύ της γραμμής 19 και της γραμμής 22, έχει ως σκοπό τον κατάλληλο σχεδιασμό και γεωμετρική τοποθέτηση των widgets και αυτός ο μηχανισμός ονομάζεται διαχειριστής διάταξης( layout manager). Ο διαχειριστής διάταξης είναι ένα αντικείμενο που ορίζει το μέγεθος και την θέση των widgets που βρίσκονται υπό την ευθύνη του. Το Qt έχει τρεις διαφορετικές κλάσεις για διαχειριστές διάταξης: QHBoxLayout: τοποθετεί τα widget οριζόντια από αριστερά προς τα δεξιά. QVBoxLayout: τοποθετεί τα widget κάθετα από πάνω προς τα κάτω. QGridLayout: τοποθετεί τα widget σε ένα πλέγμα. 40

Εικόνα 18: Προκαθορισμένα στυλ διαφορετικών λειτουργικών συστημάτων Το κάλεσμα της συνάρτησης QWidget::setLayout() στην γραμμή 22 εισάγει τον διαχειριστή διάταξης (layout manager) στο παράθυρο. Έτσι παρασκηνιακά, το αντικείμενο του QSpinBox και το αντικείμενο του QSlider γίνονται παιδιά του window μέσω του διαχειριστή διάταξης. Αυτός είναι ο λόγος για τον οποίο δεν ορίστηκε εξ αρχής το window ως γονέας κατά το κάλεσμα των constructors. Παρόλο που προγραμματιστικά δεν έγινε καμία ακριβής ρύθμιση ως προς την θέση και το μέγεθος των widgets, τα QSpinBox και QSlider εμφανίστηκαν με άρτιο τρόπο το ένα δίπλα στο άλλο. Αυτό έγινε διότι το QHBoxLayout αυτόματα τοποθέτησε σε λογικές θέσεις και σε λογικά μεγέθη τα widgets για τα οποία ήταν υπεύθυνο. 41

Εικόνα 19: Εφαρμογή ηλικίας με widget και layout Η προσέγγιση του Qt για την δημιουργία διεπαφών χρήστη είναι αρκετά απλή στην κατανόηση και πολύ ευέλικτη. Το πιο κοινό μοτίβο που ακολουθούν οι προγραμματιστές Qt είναι να δημιουργούν τις υποστάσεις των απαραίτητων widgets και μετά να ορίζουν τις ρυθμίσεις τους. Οι προγραμματιστές εισάγουν τα widgets σε layouts, τα οποία αυτόματα αναλαμβάνουν την ρύθμιση του μεγέθους και της τοποθέτησης τους. Η συμπεριφορά της διεπαφής χρήστη ρυθμίζεται από την σύνδεση των widgets μέσω του μηχανισμού signals and slots που θα αναπτυχθεί περισσότερο σε επόμενη παράγραφο. 3.4 Εγχειρίδιο Χρήσης Το εγχειρίδιο χρήσης του Qt είναι πολύ σημαντικό εργαλείο για έναν Qt Developer, διότι περιλαμβάνει όλες τις κλάσεις και τις συναρτήσεις του Qt. Στο παρόν βιβλίο γίνεται χρήση αρκετών κλάσεων και συναρτήσεων του Qt, αλλά δεν τις καλύπτει όλες ούτε και παρέχονται όλες οι λεπτομέρειες αυτών που χρησιμοποιούνται. Για να μπορέσει ένας Qt Developer να κατανοήσει όλο το φάσμα των εργαλείων του Qt θα πρέπει να αποκτήσει οικειότητα με το εγχειρίδιο χρήσης του Qt. Το εγχειρίδιο χρήσης είναι διαθέσιμο σε μορφή HTML στο φάκελο doc/html του Qt και μπορεί να αναγνωστεί μέσω οποιουδήποτε προγράμματος περιήγησης Web. Επιπροσθέτως, μπορεί να γίνει χρήση του Qt Assistant, και συγκεκριμένα του Qt help browser, το οποίο έχει τεράστιες δυνατότητες αναζήτησης χαρακτηριστικών κάνοντας τη χρήση του γρηγορότερη και ευκολότερη σε σχέση με την χρήση του προγράμματος περιήγησης Web. Για την εκκίνηση του Qt Assistant, θα πρέπει να γίνει επιλογή του Qt by Nokia v4.x.y Assistant στο μενού έναρξης των Windows, ή να εισαχθεί η εντολή assistant 42

στην κονσόλα εντολών των Unix, ή να γίνει διπλό κλικ στο Assistant έπειτα από αναζήτηση στο Mac OS X Finder της λέξης Assistant. Το παράθυρο που εμφανίζεται έπειτα από τα παραπάνω φαίνεται στην Εικόνα 20. Εικόνα 20: Εγχειρίδιο χρήσης Qt στο Qt Assistant σε Windows. Σημαντική σημείωση είναι πως οι συναρτήσεις που κληρονομούνται αναλύονται στην βασική κλάση. Για παράδειγμα, το QPushButton έχει μια δική της συνάρτηση show() η οποία όμως κληρονομείται από το QWidget. Έτσι η ανάλυση των λειτουργιών της συγκεκριμένης συνάρτησης γίνεται στο κομμάτι του QWidget. Η Εικόνα 21 δείχνει κάποιες συσχετίσεις μεταξύ των κλάσεων. 43

Εικόνα 21: Συσχετίσεις κλάσεων Τέλος, το εγχειρίδιο χρήσης για την τρέχουσα έκδοση του Qt καθώς και για προηγούμενες εκδόσεις είναι διαθέσιμο στην ιστοσελίδα της trolltech: http://doc.trolltech.com/. Ο ιστότοπος περιέχει και επιλεγμένα άρθρα σχετικά με το Qt, που στέλνονται σε προγραμματιστές Qt με εμπορικές άδειες. 3.5 Δημιουργία Dialogs Σε αυτή την παράγραφο θα γίνει μια σχετικά σύντομη αναφορά στη δημιουργία των dialog boxes χρησιμοποιώντας το Qt. Τα Dialog boxes προσφέρουν στους χρήστες διάφορες ρυθμίσεις και επιλογές, επιτρέποντας τους να κάνουν τις αλλαγές που επιθυμούν. Καλούνται dialog boxes, ή απλά "dialogs", επειδή παρέχουν ένα μέσο με το οποίο οι χρήστες και οι εφαρμογές μπορούν να μιλούν μεταξύ τους. Οι περισσότερες εφαρμογές γραφικού περιβάλλοντος χρήστη περιέχουν ένα βασικό παράθυρο με μπάρα μενού, μπάρα εργαλείων και πολλά άλλα dialogs για να συμπληρωθεί το βασικό παράθυρο. Είναι επίσης δυνατό να δημιουργηθούν dialog εφαρμογές που ανταποκρίνονται άμεσα στις επιλογές του χρήστη, εκτελώντας τα κατάλληλα μέτρα (π.χ., μια εφαρμογή υπολογιστή τσέπης). Για να μπορέσει να γίνει πιο εύκολη η παρουσίαση του Dialog, κρίθηκε σκόπιμο να γίνει χρήση ενός παραδείγματος. Το παράδειγμα αυτό, έχει ως σκοπό την δημιουργία ενός προγράμματος αναζήτησης στοιχείων όπως αυτό που φαίνεται στην Εικόνα 22. Το 44

πρόγραμμα αυτό έχει σαν όνομα το Find Dialog και είναι γραμμένο αποκλειστικά σε γλώσσα C++. Η δημιουργία του Dialog θα γίνει ως αυτόνομη κλάση. Με αυτόν τον τρόπο, παράγεται μια αυτόνομη και ανεξάρτητη συνιστώσα με τον δικό της μηχανισμό signals and slots. Εικόνα 22: Find Dialog Ο κώδικας υλοποίησης της παραπάνω εφαρμογής χωρίζεται σε δύο αρχεία: το finddialog.h και το finddialog.cpp. Αρχικά, θα γίνει η ανάλυση του πηγαίου κώδικα του αρχείου finddialog.h: 1 #ifndef FINDDIALOG_H 2 #define FINDDIALOG_H 3 #include <QDialog> 4 class QCheckBox; 5 class QLabel; 6 class QLineEdit; 7 class QPushButton; Οι γραμμές κώδικα 1 και 2 (καθώς και η γραμμή κώδικα 27) προστατεύουν το αρχείο τύπου header από τις πολλαπλές συμπεριλήψεις. Η γραμμή κώδικα 3 45

περιλαμβάνει τον ορισμό του QDialog, η οποία είναι και η βασική κλάση για τα dialogs στο Qt. Από την γραμμή κώδικα 4 μέχρι την 7 δηλώνονται οι κλάσεις Qt που θα αποτελέσουν το dialog. Η δήλωση των κλάσεων σε αυτό το αρχείο του κώδικα και με τον συγκεκριμένο τρόπο αποτελεί μια δήλωση forward declaration. Η δήλωση forward declaration δίνει την πληροφορία στον C++ compiler πως αυτή η κλάση υπάρχει, χωρίς όμως να δίνονται όλες τις λεπτομέρειες που παρέχει ο ορισμός της κλάσης. Στις επόμενες γραμμές του πηγαίου κώδικα, ορίζεται το FindDialog ως υποκλάση του QDialog: 8 class FindDialog : public QDialog 9 { 10 Q_OBJECT 11 public: 12 FindDialog(QWidget *parent = 0); Η μακροεντολή Q_OBJECT είναι απαραίτητο να οριστεί εξ αρχής σε κάθε κλάση που θα ορίσει σήματα ή slots. Ο constructor FindDialog της γραμμής εντολών 12 είναι τυπικός για κλάσεις των widget της Qt. Η παράμετρος parent προσδιορίζει το widget γονιό. Η προεπιλεγμένη επιλογή της παραμέτρου είναι ένας null pointer, το οποίο σημαίνει ότι το dialog δεν έχει γονιό. 13 signals: 14 void findnext(const QString &str, Qt::CaseSensitivity cs); 15 void findprevious(const QString &str, Qt::CaseSensitivity cs); Στο τμήμα των σημάτων δηλώνονται δύο σήματα που το dialog πυροδοτεί όταν ο χρήστης πιέσει το κουμπί Find. Αν η επιλογή Search backward (αναζήτηση προς τα πίσω) είναι ενεργοποιημένη, τότε ο κώδικας που τρέχει είναι αυτός της συνάρτησης findprevious(), αλλιώς τρέχει ο κώδικας της συνάρτησης findnext(). Το 46

Qt::CaseSensitivity είναι ένας τυποποιημένος τύπος μεταβλητών του Qt που μπορεί να πάρει τις εξής δυο τιμές: Qt::CaseSensitive και Qt::CaseInsensitive. 16 private slots: 17 void findclicked(); 18 void enablefindbutton(const QString &text); 19 private: 20 QLabel *label; 21 QLineEdit *lineedit; 22 QCheckBox *casecheckbox; 23 QCheckBox *backwardcheckbox; 24 QPushButton *findbutton; 25 QPushButton *closebutton; 26 }; 27 #endif Στο private (ιδιωτικό) τμήμα της κλάσης, μπορούν να διακριθούν δύο slots. Σε αυτό το κομμάτι του κώδικα, αρκεί να οριστούν μόνο οι δείκτες(pointers) των slots. Οι λέξεις κλειδιά (keyword) των slots, όπως και τα σήματα, είναι μακροεντολές που μετατρέπονται σε μια άλλη μορφή που μπορεί ο compiler της C++ να επεξεργαστεί. Για τις ιδιωτικές μεταβλητές, γίνεται χρήση του forward declarations για τις κλάσεις. Αυτό είναι δυνατόν να συμβαίνει διότι οι συγκεκριμένες μεταβλητές είναι pointers και δεν πραγματοποιείται πρόσβαση σε αυτές στο αρχείο header, έτσι δεν είναι απαραίτητο για τον compiler να έχει τους πλήρεις ορισμούς των κλάσεων. Θα μπορούσαν να είχαν συμπεριληφθεί και τα σχετικά αρχεία headers (<QCheckBox>, <QLabel>, κ.α.), αλλά χρησιμοποιώντας forward declarations, όπου είναι δυνατό, γίνεται γρηγορότερο το compiling. Ολοκληρώνοντας την ανάλυση του πηγαίου κώδικα του αρχείου finddialog.h μπορεί πλέον να γίνει αναφορά στον πηγαίο κώδικα του αρχείου finddialog.cpp που περιλαμβάνει την υλοποίηση της κλάσης FindDialog. 47

1 #include <QtGui> 2 #include "finddialog.h" Αρχικά, συμπεριλαμβάνεται στην υλοποίηση το <QtGui> ένα αρχείο header που περιλαμβάνεται τον ορισμό των κλάσεων γραφικού περιβάλλοντος χρήστη του Qt. Το Qt περιέχει αρκετά modules, κάθε ένα από τα οποία έχει την δικιά του βιβλιοθήκη. Τα πιο σημαντικά modules είναι τα QtCore, QtGui, QtNetwork, QtOpenGL, QtScript, QtSql, QtSvg, and QtXml. Το header αρχείο <QtGui> περιέχει τους ορισμούς όλων των κλάσεων που είναι μέρη των modules QtCore και QtGui. Συμπεριλαμβάνοντας αυτό το header στο αρχείο, απελευθερώνεται ο προγραμματιστής από το να συμπεριλαμβάνει κάθε κλάση ξεχωριστά. Στο αρχείο finddialog.h, αντί να συμπεριληφθεί το <QDialog> και να γίνει χρήση του forward declarations για τα QCheckBox, QLabel, QLineEdit, και QPushButton, θα μπορούσε απλά να συμπεριληφθεί το <QtGui>. Παρά ταύτα, το να συμπεριληφθεί ένα τόσο μεγάλο αρχείο θεωρείται προγραμματιστικά κακό, ειδικά για μεγάλες εφαρμογές. 3 FindDialog::FindDialog(QWidget *parent) 4 : QDialog(parent) 5 { 6 label = new QLabel(tr("Find &what:")); 7 lineedit = new QLineEdit; 8 label->setbuddy(lineedit); 9 casecheckbox = new QCheckBox(tr("Match &case")); 10 backwardcheckbox = new QCheckBox(tr("Search &backward")); 11 findbutton = new QPushButton(tr("&Find")); 12 findbutton->setdefault(true); 13 findbutton->setenabled(false); 14 closebutton = new QPushButton(tr("Close")); 48

Στη γραμμή 4, περνάει η παράμετρος γονιός στον constructor της βασικής κλάσης. Έπειτα δημιουργούνται τα widgets παιδιά. Η συνάρτηση tr() είναι υπεύθυνη για την μετάφραση του κειμένου που είναι ανάμεσα στα εισαγωγικά σε άλλες γλώσσες. Η συνάρτηση δηλώνεται στο QObject και σε κάθε συνάρτηση που περιέχει την μακροεντολή Q_OBJECT. Καλό είναι να συμπεριλαμβάνεται σε ορατά string από το χρήστη η συνάρτηση tr(), ακόμα και αν δεν υπάρχουν απευθείας πλάνα για μετάφραση της εφαρμογής σε άλλες γλώσσες. Για την λειτουργία συντομεύσεων (shortcut keys) χρησιμοποιείται το σύμβολο &. Για παράδειγμα, στην γραμμή 11 που δημιουργείται το Find button, ο χρήστης πιέζοντας το Alt+F σε ορισμένες πλατφόρμες που υποστηρίζουν συντομεύσεις ενεργοποιείται το κουμπί Find button. Σε ορισμένες περιπτώσεις τα σύμβολα μπορούν να χρησιμοποιηθούν για να κάνουν ενεργό κάποιο widget. Στην γραμμή 6 δηλώνεται το label με συντόμευση (shortcut key) το Alt+W, και στην γραμμή 8 μέσω της συνάρτησης setbuddy() ορίζεται ως buddy της ετικέτας το line editor. Το buddy είναι ένα widget που τίθεται ενεργό όταν γίνει χρήση της συντόμευσης. Έτσι όταν χρησιμοποιηθεί η συντόμευση Alt+W, απευθείας ο κέρσορας είναι ενεργοποιημένος στο εσωτερικό του line editor. Στην γραμμή 12 ορίζεται σαν προεπιλεγμένο κουμπί το Find button καλώντας την συνάρτηση setdefault(true). Το προεπιλεγμένο κουμπί είναι το κουμπί που ενεργοποιείται όταν ο χρήστης πιέσει το πλήκτρο Enter. Η γραμμή κώδικα 13, απενεργοποιεί το Find button. Όταν το widget απενεργοποιείται εμφανίζεται με γκρι χρώμα και δεν αλληλεπιδρά με το χρήστη. 15 connect(lineedit, SIGNAL(textChanged(const QString &)), 16 this, SLOT(enableFindButton(const QString &))); 17 connect(findbutton, SIGNAL(clicked()), 18 this, SLOT(findClicked())); 19 connect(closebutton, SIGNAL(clicked()), 20 this, SLOT(close())); Το ιδιωτικό (private) slot enablefindbutton(const QString &) καλείται όποτε το κείμενο του line editor αλλάζει. Το ιδιωτικό (private) slot findclicked() καλείται όταν ο 49

χρήστης κάνει κλικ στο Find button. Το dialog κλείνει από μόνο του όταν πιεστεί το Close. Το slot close() κληρονομείται από το QWidget, και η προεπιλεγμένη συμπεριφορά του είναι να κρύβει το widget χωρίς να το σβήνει. Η αναφορά του κώδικα για τα slot enablefindbutton() και findclicked() θα γίνει αργότερα. 21 QHBoxLayout *topleftlayout = new QHBoxLayout; 22 topleftlayout->addwidget(label); 23 topleftlayout->addwidget(lineedit); 24 QVBoxLayout *leftlayout = new QVBoxLayout; 25 leftlayout->addlayout(topleftlayout); 26 leftlayout->addwidget(casecheckbox); 27 leftlayout->addwidget(backwardcheckbox); 28 QVBoxLayout *rightlayout = new QVBoxLayout; 29 rightlayout->addwidget(findbutton); 30 rightlayout->addwidget(closebutton); 31 rightlayout->addstretch(); 32 QHBoxLayout *mainlayout = new QHBoxLayout; 33 mainlayout->addlayout(leftlayout); 34 mainlayout->addlayout(rightlayout); 35 setlayout(mainlayout); Τα Layouts μπορούν να συμπεριλαμβάνουν widgets αλλά και άλλα layouts. Με τον συνδυασμό των διαφορετικών layouts που είναι το QHBoxLayouts, το QVBoxLayouts και το QGridLayouts μπορεί να παραχθούν εξελιγμένα dialogs. Στο Find dialog, χρησιμοποιήθηκαν μόνο δύο QHBoxLayouts και δύο QVBoxLayouts, όπως φαίνεται στην Εικόνα 23. Το εξωτερικό layout είναι και το βασικό layout. Η εισαγωγή του στο FindDialog γίνεται στην γραμμή εντολών 35 και είναι υπεύθυνο για όλη την περιοχή του dialog. Τα άλλα τρία layouts είναι sub-layouts του βασικού. Η γραμμή που χαρακτηρίζεται σαν spacer έχει σαν αποστολή να αφήσει 50

έναν ορισμένο κενό χώρο κάτω από τα πλήκτρα σύμφωνα με το ζητούμενο αποτέλεσμα που φαίνεται στην Εικόνα 23. Εικόνα 23: Το layout του Find dialog Μια λεπτή πτυχή του διαχειριστή διάταξης (layout manager) είναι ότι δεν είναι widget. Στην εικόνα, τα widgets εκπροσωπούνται από περιγράμματα με συνεχή γραμμή και τα layout εκπροσωπούνται από διακεκομμένες γραμμές για να τονιστεί η διαφορά μεταξύ τους. Σε μια εφαρμογή που εκτελείται, τα layout είναι αόρατα. Όταν τα sublayouts εισαχθούν σε ένα layout γονέα (γραμμές 25, 33 και 34), τότε όλα τα sublayouts αυτόματα είναι παιδιά αυτού του layout. Έτσι, όταν το βασικό layout εισαχθεί στο dialog (γραμμή 35), γίνεται παιδί του dialog, και όλα τα widgets των layouts γίνονται παιδιά του dialog. Η ιεραρχία αυτή φαίνεται ξεκάθαρα στην Εικόνα 24. 36 setwindowtitle(tr("find")); 37 setfixedheight(sizehint().height()); 38 } 51

Εικόνα 24: Σχέσεις γονέα-παιδιού του Find dialog Οι τελευταίες γραμμές κώδικα θέτουν σαν τίτλο του παραθύρου το Find και ορίζουν ένα ουσιαστικά αυτόματο ύψος για το παράθυρο της εφαρμογής, διότι δεν υπάρχει ανάγκη για κάποιο περιορισμό. Η συνάρτηση QWidget::sizeHint() επιστρέφει ένα widget ιδανικού μεγέθους. Τα παραπάνω ολοκληρώνουν την παρουσίαση του constructor FindDialog. Με την χρήση του new στη δημιουργία των widgets και των layouts, θα περίμενε κανείς να καλεστούν κάποιοι destructor για να σβηστούν τα widgets και τα layouts που δημιουργήθηκαν. Αυτό όμως δεν είναι απαραίτητο, αφού το Qt αυτόματα διαγράφει τα αντικείμενα παιδιά όταν ο γονέας διαγράφεται όπου στην προκειμένη περίπτωση τα widgets και τα layouts είναι απόγονοι του FindDialog. Σε αυτό το σημείο θα αναλυθούν τα slots του dialog: 39 void FindDialog::findClicked() 40 { 41 QString text = lineedit->text(); 42 Qt::CaseSensitivity cs = 43 casecheckbox->ischecked()? Qt::CaseSensitive 44 : Qt::CaseInsensitive; 45 if (backwardcheckbox->ischecked()) { 46 emit findprevious(text, cs); 47 } else { 48 emit findnext(text, cs); 52

49 } 50 } 51 void FindDialog::enableFindButton(const QString &text) 52 { 53 findbutton->setenabled(!text.isempty()); 54 } Η συνάρτηση slot findclicked() καλείται όταν πατηθεί το κουμπί Find. Αυτό εκπέμπει είτε το σήμα findprevious() είτε το σήμα findnext(), ανάλογα με την ρύθμιση Search backward. Από την άλλη το slot enablefindbutton() καλείται όποτε ο χρήστης αλλάζει το περιεχόμενο κειμένου του line editor. Αυτά τα δύο slots ολοκληρώνουν το dialog. Εκτός από τα δύο αρχεία που αναλύθηκαν παραπάνω δημιουργείται και ένα τρίτο με όνομα main.cpp για να γίνει έλεγχος του widget FindDialog: 1 #include <QApplication> 2 #include "finddialog.h" 3 int main(int argc, char *argv[]) 4 { 5 QApplication app(argc, argv); 6 FindDialog *dialog = new FindDialog; 7 dialog->show(); 8 return app.exec(); 9 } Για να γίνει compile του προγράμματος, πρέπει να τρέξει η εντολή qmake όπως και στις προηγούμενες παραγράφους. Λόγω του ότι η κλάση FindDialog στον ορισμό της περιλαμβάνει την μακροεντολή Q_OBJECT, το αρχείο makefile που παράγεται από 53

το qmake θα περιλαμβάνει και ειδικούς κανόνες για να τρέχει το Qt meta-object compiler (moc). Για να λειτουργήσει σωστά το moc, θα πρέπει να τοποθετηθεί ο ορισμός της κλάσης σε ένα αρχείο header, ξεχωριστά από το αρχείο εκτέλεσης. Ο κώδικας που παράγεται από το moc περιέχει αυτό το αρχείο header και προσθέτει κάποιον δικό του κώδικα C++. Οι κλάσεις που χρησιμοποιούν την μακροεντολή Q_OBJECT πρέπει να έχουν το moc να τρέχει. Αυτό δεν είναι όμως πρόβλημα διότι το qmake αυτόματα εισάγει όλους τους απαραίτητους κανόνες στο makefile. 3.6 Μηχανισμός Signals and Slots Ο μηχανισμός signals and slots είναι θεμελιώδους σημασίας για τον προγραμματισμό σε Qt. Ο μηχανισμός επιτρέπει στον προγραμματιστή της εφαρμογής να συνδέει μεταξύ τους αντικείμενα χωρίς το ένα να γνωρίζει τίποτα για το άλλο. Έχουν παρουσιαστεί ήδη κάποια παραδείγματα παραπάνω για το πως πρέπει να χειρίζονται τα σήματα και τα slots. Σε αυτή την παράγραφο θα δοθεί μια προσεχτικότερη ματιά στο πώς λειτουργεί ο μηχανισμός. Τα Slots είναι σχεδόν ταυτόσημα με τις συνηθισμένες συναρτήσεις μέλη της C++. Τα slots μπορεί να είναι εικονικά (virtual), overloaded, δημόσια (public), προστατευόμενα (protected), ή ιδιωτικά (private). Επίσης, μπορούν να καλεστούν απευθείας σαν συναρτήσεις μέλη της C++ και οι παράμετροι τους μπορούν να είναι οποιουδήποτε τύπου. Η διαφορά είναι ότι τα slot μπορεί να συνδεθούν με σήματα (signals), όπου θα καλούνται αυτόματα κάθε φορά που εκπέμπεται ένα από αυτά. Η δήλωση του connect() φαίνεται παρακάτω: connect(sender, SIGNAL(signal), receiver, SLOT(slot)); Τα sender και receiver είναι δείκτες στο QObjects και τα signals και slots είναι υπογραφές συναρτήσεων χωρίς ονόματα παραμέτρων. Τα SIGNAL() και SLOT() είναι μακροεντολές που ουσιαστικά μετατρέπουν arguments σε string. 54

Στα παραδείγματα που αναφέρθηκαν μέχρι στιγμής διαφορετικά σήματα αντιστοιχούσαν σε διαφορετικά slots. Αυτό όμως δεν είναι κανόνας και παρακάτω θα αναφερθούν οι τρόποι σύνδεσης. Ένα σήμα (signal) συνδέεται με πολλά slots: connect(slider, SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(updateStatusBarIndicator(int))); Όταν το σήμα εκπέμπεται τα slots καλούνται το ένα μετά το άλλο με απροσδιόριστη σειρά Πολλά σήματα συνδέονται με το ίδιο slot: connect(lcd, SIGNAL(overflow()), this, SLOT(handleMathError())); connect(calculator, SIGNAL(divisionByZero()), this, SLOT(handleMathError())); Όποιο σήμα και να εκπεμφθεί θα ενεργοποιηθεί το slot. Ένα σήμα συνδέεται με ένα άλλο σήμα: connect(lineedit, SIGNAL(textChanged(const QString &)), this, SIGNAL(updateRecord(const QString &))); Όταν γίνει εκπομπή του πρώτου σήματος, ενεργοποιείται αμέσως και το δεύτερο. Εκτός από αυτό, οι συνδέσεις signal-signal είναι δυσδιάκριτες σε σχέση με τις συνδέσεις signal slot. Οι συνδέσεις μπορούν να διαγραφούν: disconnect(lcd, SIGNAL(overflow()), this, SLOT(handleMathError())); 55

Αυτό είναι πολύ σπάνια αναγκαίο διότι όλες οι συνδέσεις διαγράφονται μόλις γίνει διαγραφή κάποιου αντικειμένου που σχετίζεται με την σύνδεση. Για να γίνει επιτυχημένη σύνδεση μεταξύ ενός σήματος (signal) και ενός slot (ή άλλου signal), η σύνδεση θα πρέπει να έχει τον ίδιο τύπο παραμέτρων και να είναι με την ίδια σειρά: connect(ftp, SIGNAL(rawCommandReply(int, const QString &)), this, SLOT(processReply(int, const QString &))); Κατ 'εξαίρεση, εάν ένα σήμα έχει περισσότερες παραμέτρους από το slot με το οποίο είναι συνδεμένο, οι πρόσθετες παράμετροι απλώς αγνοούνται: connect(ftp, SIGNAL(rawCommandReply(int, const QString &)), this, SLOT(checkErrorCode(int))); Αν οι τύποι των παραμέτρων είναι ασυμβίβαστοι ή αν τα σήματα ή τα slot δεν υπάρχουν, τότε το Qt θα βγάλει κάποια προειδοποίηση (warning) κατά τον χρόνο εκτέλεσης εάν η εφαρμογή κάνει build σε debug mode. Με τον ίδιο τρόπο, στο Qt θα χτυπήσει ένδειξη warning, αν τα ονόματα των παραμέτρων συμπεριλαμβάνονται στις υπογραφές του σήματος ή του slot. Μέχρι στιγμής, έγινε χρήση των signals και slots για widgets. Ο μηχανισμός όμως υλοποιείται στο QObject και δεν περιορίζεται μόνο στον προγραμματισμό γραφικού περιβάλλοντος χρήστη. Ο μηχανισμός μπορεί να χρησιμοποιηθεί από οποιοδήποτε subclass του QObject: class Employee : public QObject { Q_OBJECT public: Employee() { mysalary = 0; } 56

int salary() const { return mysalary; } public slots: void setsalary(int newsalary); signals: void salarychanged(int newsalary); private: int mysalary; }; void Employee::setSalary(int newsalary) { if (newsalary!= mysalary) { mysalary = newsalary; emit salarychanged(mysalary); } } Στον παραπάνω κώδικα αξίζει να αναφερθεί η υλοποίηση του setsalary() slot. Το σήμα salarychanged() ενεργοποιείται μόνο όταν η συνθήκη μέσα στην if του setsalary() γίνει αληθής. Αυτό εξασφαλίζει πως οι κυκλικές συνδέσεις δεν θα οδηγήσουν σε ατέρμονο βρόγχο. 57

ΚΕΦΑΛΑΙΟ 4 Ο Μικροελεγκτής Ο μικροελεγκτής που χρησιμοποιήθηκε για την υλοποίηση του ελέγχου του συστήματος είναι της εταιρίας Infineon και συγκεκριμένα το μοντέλο TC1798 της οικογένειας AUDO MAX (Εικόνα 25). O λόγος που επιλέγεται η Infineon είναι η ευρεία κυκλοφορία των μικροελεγκτών της συγκεκριμένης εταιρίας πάνω στα drivers των επαγωγικών και μη κινητήρων. Έτσι μπορεί να προμηθεύεται εύκολα ο συγκεκριμένος μικροελεγκτής και εκτός αυτού είναι αρκετά οικονομικός. Ένα σημαντικό πλεονέκτημα της συγκεκριμένης εταιρίας είναι ότι οι μικροελεγκτές που παράγει είναι προσανατολισμένοι προς την οδήγηση κινητήρων. Εξαιτίας αυτού υλοποιούνται μέσα σε αυτόν κομμάτια υλικού που βοηθούν στην ανάπτυξη εφαρμογών προσανατολισμένων σε κινητήρες. Εικόνα 25: Ο TC1798 της οικογένειας AUDO MAX Στις επόμενες παραγράφους αυτού του κεφαλαίου θα γίνει ανάλυση των γενικών χαρακτηριστικών του μικροελεγκτή και θα γίνει ιδιαίτερη αναφορά στην ασύγχρονη σειριακή επικοινωνία που χρησιμοποιήθηκε ως μέσω επικοινωνίας μεταξύ μικροελεγκτή και υπολογιστή. 58

4.1 Γενικά για τον Μικροελεγκτή Ο συγκεκριμένος μικροελεγκτής είναι των 32 bit. Το TC1798 συνδυάζει τρεις ισχυρές τεχνολογίες πυριτίου μέσα σε μία μονάδα, επιτυγχάνοντας νέα επίπεδα ισχύος, ταχύτητας και οικονομίας για ενσωματωμένες εφαρμογές. Οι τεχνολογίες αυτές είναι οι εξής: Αρχιτεκτονική RISC ή αλλιώς αρχιτεκτονική υπολογιστή περιορισμένου συνόλου εντολών. Ψηφιακή επεξεργασία σήματος για πράξεις και λειτουργίες διευθυνσιοδότησης. On-Chip μνήμες και περιφερειακά. Η ψηφιακή επεξεργασία σήματος για πράξεις και οι λειτουργίες διευθυνσιοδότησης παρέχουν την υπολογιστική δύναμη που απαιτείται για να αναλυθούν αποτελεσματικά πολύπλοκα σήματα σε πραγματικό χρόνο. Η αρχιτεκτονική RISC παρέχει υψηλό υπολογιστικό εύρος με χαμηλό κόστος συστήματος. Ακόμα οι Onchip μνήμες και περιφερειακά έχουν σχεδιαστεί για να υποστηρίζουν εργασίες σε ενσωματωμένα συστήματα που είναι μεγάλου εύρους και πραγματικού χρόνου. Το μοντέλο TC1798 έχει και άλλα χαρακτηριστικά υψηλού επιπέδου. Κάποια από αυτά είναι τα εξής: Αποδοτική οργάνωση μνήμης. Διεπαφές σειριακής επικοινωνίας: ευέλικτες ρυθμίσεις για ασύγχρονη ή σύγχρονη σειριακή επικοινωνία. Επεξεργαστής για έλεγχο των περιφεριακών: αυτόνομες λειτουργίες δεδομένων και εξυπηρέτηση διακοπών. Επεξεργαστής για DMA και για SDMA. Ασφαλής επέκταση υλικού (Hardware). Ευέλικτη μηχανή CRC. Μετρητές χρόνου(timers) γενικού σκοπού. Υψηλής απόδοσης διαύλους. Ευέλικτες διεπαφές με άλλες μονάδες. Ευέλικτο σύστημα ελέγχου ισχύος. 59

Ο TC1798 είναι ένας υψηλής απόδοσης μικροελεγκτής με TriCore CPU, με πρόγραμμα και μνήμη δεδομένων, διαύλους, διαιτησία διαύλων, έναν ελεγκτή διακοπών, έναν επεξεργαστή για έλεγχο των περιφερειακών, έναν ελεγκτή DMA και άλλα on-chip περιφερειακά. Το TC1798 είναι σχεδιασμένο για να καλύπτει τις ανάγκες των πιο απαιτητικών εφαρμογών για ενσωματωμένα συστήματα ελέγχου όπου τα ανταγωνιστικά θέματα της τιμής σε σχέση με την απόδοση, της πραγματικού χρόνου απόκρισης, της υπολογιστικής δύναμης, του εύρους δεδομένων και της κατανάλωσης ισχύος είναι στοιχεία κλειδιά για τη σχεδίαση. Το TC1798 προσφέρει πολλές ευέλικτες on-chip περιφερειακές μονάδες όπως η σειριακοί ελεγκτές, μονάδες μετρητών χρόνου και μετατροπείς A/D. Εντός του TC1798, όλες οι περιφερειακές μονάδες συνδέονται με το σύστημα TriCore CPU μέσω του διαύλου Flexible Peripheral Interconnect (FPI) και του διαύλου Local Memory Bus (SRI). Αρκετές γραμμές εισόδου/εξόδου στις θύρες του TC1798 προορίζονται για αυτές τις περιφερειακές μονάδες ώστε να επικοινωνούν με τον εξωτερικό κόσμο. Παρακάτω φαίνεται το μπλοκ-διάγραμμα του μικροελεγκτή TC1798. Εικόνα 26: Μπλοκ διάγραμμα του TC1798 60

4.2 Ασύγχρονη Σειριακή Διεπαφή του TC1798 Αυτή η παράγραφος περιγράφει τις δύο ασύγχρονες σειριακές διεπαφές ASC, ASC0 και ASC1, του μικροελεγκτή της Infineon TC1798 και περιλαμβάνει τα ακόλουθα τμήματα: Λειτουργική περιγραφή του πυρήνα του ASC, ισχύει για ASC0 και ASC1. Περιγραφή των καταχωρητών του πυρήνα του ASC. 4.2.1 Περιγραφή του Πυρήνα ASC Εικόνα 27: Γενικό μπλοκ διάγραμμα της ASC διεπαφής Η ASC μονάδα επικοινωνεί με τον εξωτερικό κόσμο μέσω δύο γραμμών εισόδου/εξόδου. Η γραμμή RXD λαμβάνει σήματα εισόδου ενώ η γραμμή TXD εκπέμπει σήματα εξόδου. Ο έλεγχος του ρολογιού, η αποκωδικοποίηση των διευθύνσεων καθώς και η υπηρεσία αιτήσεων διακοπών διαχειρίζονται εξωτερικά από τη μονάδα ASC. Η μονάδα ASC παρέχει σειριακή επικοινωνία μεταξύ του TC1798 και άλλων μικροελεγκτών, μικροεπεξεργαστών ή άλλων εξωτερικών περιφερειακών. Επίσης, υποστηρίζει την πλήρως αμφίδρομη (full-duplex) ασύγχρονη επικοινωνία και την ημί- 61

αμφίδρομη σύγχρονη επικοινωνία. Όταν γίνεται ασύγχρονη ρύθμιση, τα δεδομένα που μεταφέρονται είναι των 8 ή των 9 bits και μπορεί να επιλεγεί parity bit καθώς και ένας αριθμός stop bits. Μια 13-bit γεννήτρια baud rate παρέχει στο ASC ένα ξεχωριστό σειριακό σήμα ρολογιού το οποίο μπορεί να ρυθμιστεί ακριβώς από έναν prescaler. Επιγραμματικά τα χαρακτηριστικά του ASC είναι τα εξής: Πλήρως αμφίδρομη ασύγχρονη σειριακή επικοινωνία: 8 ή 9 bits πακέτα δεδομένων. Γεννήτρια και έλεγχος Parity-bit. Ένα ή δυο stop bits. Baud rate από 6.875 Mbit/s μέχρι 1.64 bit/s. Λειτουργία πολυεπεξεργαστών για αυτόματη ανίχνευση byte δεδομένων ή διευθύνσεων. Δυνατότητα Loop-back. Ημι-αμφίδρομη σύγχρονη σειριακή επικοινωνία: Baud rate από 13.75 Mbit/s μέχρι 1119 bit/s. Double-buffered αποστολή/λήψη δεδομένων. Γεννήτρια διακοπών. Χαρακτηριστικά εφαρμογών όπως οι συνδέσεις των ελεγκτών DMA. 4.2.2 Ασύγχρονη Λειτουργία Η ρύθμιση για ασύγχρονη επικοινωνία υποστηρίζει πλήρως αμφίδρομη επικοινωνία η οποία στέλνει και λαμβάνει χρησιμοποιώντας την ίδια φόρμα πλαισίου δεδομένων και το ίδιο baud rate. Τα δεδομένα αποστέλλονται μέσω του pin TXD και λαμβάνονται μέσω του pin RXD. Η επόμενη εικόνα δείχνει το μπλοκ διάγραμμα σε ασύγχρονη ρύθμιση. 62

Εικόνα 28: Ασύγχρονη λειτουργία του ASC 4.2.3 Πλαίσια Δεδομένων στην Ασύγχρονη Λειτουργία Στην ασύγχρονη λειτουργία τα δεδομένα είναι σε πλαίσια των 8 ή των 9 bits. Επειδή όμως στην εφαρμογή που τελικά υλοποιήθηκε χρησιμοποιήθηκε πλαίσιο των 8 bits θα γίνει αναφορά μόνο σε αυτό. 63

Τα 8-bit πλαίσια δεδομένων περιλαμβάνουν είτε 8 bits δεδομένωνs D7 D0 (CON.M = 001B), είτε 7 bits δεδομένων D6 D0 (CON.M = 001B), μαζί με ένα αυτόματα παραγόμενο parity bit. Το parity bit μπορεί να είναι άρτιο ή περιττό πράγμα το οποίο εξαρτάται από το bit CON.ODD. Το άρτιο parity bit θα οριστεί ενεργό όταν το άθροισμα του συμπληρώματος ως προς δύο των εφτά bits είναι 1. Το περιττό parity bit θα γίνει σε αυτή την περίπτωση καθαρό. Ο έλεγχος parity ενεργοποιείται μέσω του bit CON.PEN (που είναι πάντα OFF στην λειτουργία των 8-bit). Η σημαία σφάλματος parity CON.PE θα ενεργοποιηθεί μαζί με την σημαία αίτησης διακοπής σφάλματος όταν ένα λάθος parity bit ληφθεί. Το ίδιο το λαμβανόμενο parity bit θα αποθηκευτεί στο RBUF. Εικόνα 29: Πλαίσιο των 8-bits 4.2.3 Γεννήτρια Baud Rate Το ASC έχει τη δικιά του 13-bit γεννήτρια baud rate με δεκατριών bit δυνατότητα επαναφόρτωσης, επιτρέποντας στην γεννήτρια baud rate να είναι ανεξάρτητη από τους άλλους μετρητές χρόνου (timers). Η γεννήτρια baud rate χρονίζεται με ένα ρολόι (fdiv) το οποίο προέρχεται μέσω ενός prescaler από την μονάδα ρολόι fasc. Το χρονόμετρο baud rate μπορεί να κάνει underflow ξεκινώντας ή σταματώντας μέσω του bit CON.R της γεννήτριας baud rate. Κάθε τέλος ενός underflow του timer παράγει ένα παλμό ρολογιού στο σειριακό 64

κανάλι. Ο timer παίρνει την τιμή που είναι τοποθετημένη στον 13-bit καταχωρητή του εκάστοτε underflow. Το προκύπτον του ρολογιού fbrt διαιρείται από ένα συντελεστή για το ρολόι baud rate ( 16 για ασύγχρονες ρυθμίσεις και 4 για σύγχρονες ρυθμίσεις). Ο prescaler επιλέγεται από τα bits CON.BRS και CON.FDE. Για ασύγχρονη λειτουργία η γεννήτρια baud rate παρέχει ένα ρολόι το fbrt με δεκάξι φορές μεγαλύτερο της τιμής του προκαθορισμένου baud rate. Κάθε λαμβανόμενο bit δειγματοληπτείται στον 7ο,8ο και 9ο κύκλο ρολογιού. Το κύκλωμα clock divider, το οποίο παράγει το ρολόι εισόδου fdiv για των 13-bit baud rate timer, επεκτείνεται από το κύκλωμα fractional divider που επιτρέπει να γίνει ακριβέστερη προσαρμογή των baud rates και επέκταση του εύρους του baud rate. Το baud rate της γεννήτριας baud rate εξαρτάται από τις ρυθμίσεις των τιμών των ακόλουθων καταχωρητών και bits: Ρολόι εισόδου fasc. Επιλογή του ρολογιού εισόδου fdiv από τα bits CON.FDE και CON.BRS. Αν το bit CON.FDE=1(fractional divider): η τιμή του καταχωρητή fdiv. Η τιμή του 13-bit καταχωρητή BG. Το ρολόι εξόδου του χρονιστή baud rate μαζί με τον καταχωρητή είναι το ρολόι δειγματοληψίας σε ασύγχρονη ρύθμιση του ASC. Για υπολογισμούς του baud rate, το ρολόι baud rate fbr καθορίζεται από το ρολόι δειγματοληψίας fbrt με μια διαίρεση με το δεκάξι. 65

Εικόνα 30: Κύκλωμα γεννήτριας ASC Baud Rate στην ασύγχρονη ρύθμιση Η χρήση των καθορισμένων clock divider εισόδου (CON.FDE = 0) για το baud rate του σειριακού καναλιού ASC και της κατάλληλης τιμής του BG καταχωρητή επαναφόρτωσης μπορούν να καθοριστούν από την επόμενη εικόνα: Εικόνα 31: Φόρμουλα χρήσης προκαθορισμένων Clock Dividers εισόδου Το BG παρουσιάζει το περιεχόμενο του πεδίου bit του καταχωρητή BG.BR_VALUE, σαν απρόσημο ακέραιο των 13-bit. Το μέγιστο baud rate που μπορεί να φτάσει στην ασύγχρονη ρύθμιση όταν γίνεται χρήση των δύο πρoκαθορισμένων clock dividers και της μονάδας ρολογιού από τα 110 MHz είναι 3.4375 Mbit/s. 66

Εικόνα 32: Τυπικές τιμές του ασύγχρονου baud rate χρησιμοποιώντας προκαθορισμένους clock dividers εισόδου Όταν γίνεται επιλογή του fractional divider, το ρολόι εισόδου fdiv για τον χρονιστή baud rate καθορίζεται από μια μονάδα ρολογιού fasc με ένα προγραμματιζόμενο fractional divider. Αν ισχύει πως το CON.FDE = 1, τότε το fractional divider ενεργοποιείται. Αυτό διαιρεί το fasc με ένα κλάσμα n/512 για οποιαδήποτε τιμή του n από το 0 μέχρι το 511. Αν το n = 0, ο λόγος διαίρεσης είναι 1, που σημαίνει ότι το fdiv = fasc. Γενικά, το fractional divider επιτρέπει το baud rate να προγραμματιστεί με την όσο το δυνατόν μεγαλύτερη ακρίβεια σε σχέση με τα δύο προκαθορισμένα στάδια του prescaler divider. Εικόνα 33: Φόρμουλα χρήσης ρολογιού εισόδου fractional divider Το BG παρουσιάζει το περιεχόμενο του πεδίου bit του καταχωρητή BG.BR_VALUE, σαν απρόσημο ακέραιο των 13-bit. Το FDV παρουσιάζει το περιεχόμενο του πεδίου bit του καταχωρητη FDV.FD_VALUE, σαν απρόσημο ακέραιο των 9-bit. 67

Εικόνα 34: Τυπικές τιμές του ασύγχρονου baud rate χρησιμοποιώντας fractional clock dividers εισόδου. 4.2.4 Διακοπές Στο σειριακό κανάλι ASC παρέχονται τέσσερις πηγές διακοπών. Η γραμμή TIR υποδεικνύει μια διακοπή μετάδοσης, η γραμμή TBIR υποδεικνύει διακοπή του buffer μετάδοσης, η γραμμή RIR υποδεικνύει την διακοπή λήψης και η γραμμή EIR υποδεικνύει τη διακοπή σφάλματος του σειριακού καναλιού. Οι γραμμές διακοπών εξόδου TBIR,TIR, RIR και EIR ενεργοποιούνται για δύο περιόδους του ρολογιού fasc. Η αιτία για την οποία προκαλείται μια διακοπή σφάλματος EIR μπορεί να οριστεί από τις σημαίες σφαλμάτων CON.FE, CON.PE και CON.OE. Για κανονική λειτουργία, ο ASC παρέχει τρία αιτήματα διακοπών για να ελέγχει την δοσοληψία δεδομένων μέσω του σειριακού καναλιού: Το TBIR ενεργοποιείται όταν τα δεδομένα μεταφέρονται από το TBUF στον καταχωρητή μετάδοσης(transmit shift register). Το TIR ενεργοποιείται πριν από την μετάδοση του τελευταίου bit ενός ασύγχρονου πλαισίου. Το RIR ενεργοποιείται όταν το πλαίσιο λήψης μεταφέρεται στο RBUF. Αν και το έργο του χειριστή διακοπής για λήψη δεδομένων είναι αρκετά σαφές, η μετάδοση δεδομένων εξυπηρετείται από δύο χειριστές. Αυτό παρέχει πλεονεκτήματα για την εξυπηρέτηση λογισμικού. 68

Για μετάδοση προς μια κατεύθυνση, αρκεί να γίνει χρήση της διακοπής μετάδοσης δεδομένων (TIR), που υποδεικνύει ότι τα δεδομένα που έχουν φορτωθεί την προηγούμενη χρονική στιγμή έχουν μεταδοθεί, με εξαίρεση το τελευταίο bit του ασύγχρονου πλαισίου. Για πολλαπλές back-to-back μεταδόσεις, είναι απαραίτητο να φορτωθεί τουλάχιστον το επόμενο κομμάτι δεδομένων πριν μεταδοθεί το τελευταίο bit του προηγούμενου πλαισίου δεδομένων. Στην ασύγχρονη λειτουργία, αυτό αφήνει στον χειριστή ένα bit για να ανταποκριθεί στην αίτηση διακοπής μετάδοσης. Η χρήση του TBIR για επαναφόρτωση των δεδομένων μετάδοσης παρέχει χρόνο απαραίτητο για να μεταδοθεί ολόκληρο το πλαίσιο για την ρουτίνα εξυπηρέτησης, ενώ το TBUF μπορεί να επαναφορτώνεται όσο τα προηγούμενα δεδομένα ακόμα μεταδίδονται. Εικόνα 35: Παραγωγή διακοπών ASC Όπως φαίνεται παραπάνω το σήμα TBIR σηματοδοτεί την έναρξη για την επαναφόρτιση των δεδομένων. Όταν έχει υλοποιηθεί η αποστολή των χαρακτήρων με τις παραμέτρους που έχουν οριστεί τότε ενεργοποιείται το σήμα TIR ώστε να σηματοδοτηθεί το τέλος του αντίστοιχου byte προς αποστολή. 69

4.2.5 Διεπαφές των Μονάδων ASC Οι σειριακές γραμμές εισόδου/εξόδου και των δύο μονάδων είναι συνδεδεμένες είτε στο Port 5 είτε στο Port 6. Κάθε μία από τις μονάδες ASC είναι εξοπλισμένη με έλεγχο διακοπών, αποκωδικοποίηση διευθύνσεων και με έλεγχο των ports. Μπορούν να παραχθούν δύο αιτήσεις DMA από κάθε μονάδα ASC. Και οι δύο μονάδες ASC χρησιμοποιούν την ίδια μονάδα χρόνου. Εικόνα 36: Υλοποίηση και διεπαφή μονάδας ASC0/ASC1 Κάποιες από τις εισόδους των ASC0 και ASC1 είναι συνδεδεμένες μέσω ενός πολυπλέκτη στην είσοδο LTC της μονάδας GPTA. 70

4.2.6 Εξωτερικοί Καταχωρητές Σχετιζόμενοι με μονάδα ASC0/ASC1 Για να μπορέσει να προγραμματιστεί η μονάδα ASC0/ASC1 είναι απαραίτητο να γίνει χρήση ορισμένων καταχωρητών που φαίνονται στην παρακάτω εικόνα. Εικόνα 37: Εξωτερικοί καταχωρητές σχετιζόμενοι με μονάδα ASC0/ASC1 Στη πρώτη στήλη με τους εξωτερικούς καταχωρητές διακρίνονται οι καταχωρητές ελέγχου. Ο καταχωρητής έλεγχου ρολογιού ASC0_CLC επιτρέπει στον προγραμματιστή να προσαρμόζει τη λειτουργικότητα και την κατανάλωση ενέργειας της μονάδας ASC ανάλογα με τις απαιτήσεις της εφαρμογής. Η παρακάτω περιγραφή δείχνει την λειτουργικότητα του καταχωρητή ελέγχου ρολογιού που υλοποιείται για τις μονάδες ASC. Καθώς τα ASC0 και ASC1 μοιράζονται το ίδιο κοινό ρολόι ελέγχου διεπαφής, το ASC0_CLC ελέγχει το σήμα ρολογιού της μονάδας fasc, τη λειτουργία ύπνου (sleep mode), τη λειτουργία αναμονής και τη γρήγορη λειτουργία shut-off και για τις δύο μονάδες. 71

Εικόνα 38: Καταχωρητής ελέγχου ρολογιού ASC0 Οι καταχωρητές ASC0_PISEL και ASC1_PISEL που περιλαμβάνονται στις μονάδες ASC0/ASC1 είναι περιφερειακοί καταχωρητές επιλογής εισόδου ώστε να λειτουργεί το συγκεκριμένο pin της port ως είσοδος για τις μονάδες ASC0/ASC1. Στην περίπτωση της ασύγχρονης-συγχρονης επικοινωνίας, χρησιμοποιούνται για ενεργοποίηση των γραμμών εισόδου RXD μονάδας ASC0/ASC1 μεταξύ διαφορετικών ζευγαριών pins των Port 5 και Port 6, όπως φαίνεται στην Εικόνα 39. Ο καταχωρητής ASC0_PISEL ελέγχει επιλογή εισόδου RXD για το ASC0 ενώ ο καταχωρητής ASC1_PISEL ελέγχει την επιλογή εισόδου RXD για το ASC1. 72

Εικόνα 39: Επιλογή Γραμμής Εισόδου RXD της μονάδες ASC Εικόνα 40: Καταχωρητής Επιλογής Περιφερειακής Εισόδου ASC0 73

Όπως φαίνεται στην Εικόνα 37 η δεύτερη στήλη περιλαμβάνει τους καταχωρητές για έλεγχο των ports. Οι γραμμές εισόδου/εξόδου των μονάδων ASC είναι συνδεδεμένες με τα pins του Class A2 του Port3. Επιπροσθέτως, για τον προγραμματισμό του καταχωρητή PISEL, η απαιτούμενη γραμμή port ASC πρέπει να προγραμματιστεί μέσω λογισμικού για την επιθυμητή λειτουργικότητα εισόδου/εξόδου ASC. Οι επιλογές που πρέπει να εκτελεστούν είναι δύο: Επιλογή συνάρτησης εισόδου/εξόδου.(ελέγχεται από τον καταχωρητή ελέγχου port εισόδου/εξόδου IOCR) Μπλοκ οδηγών επιλογής χαρακτηριστικών για τις εξόδους. (ελέγχεται από τον καταχωρητή PDR) Οι γραμμές εισόδου/εξόδου για τις μονάδες ASC ελέγχονται από τους καταχωρητές ελέγχου port εισόδου/εξόδου P5_IOCR0 και P6_IOCR8. Η Εικόνα 41 δείχνει πως τα bits και τα πεδία των bits πρέπει να προγραμματιστούν για την απαιτούμενη λειτουργικότητα των γραμμών εισόδου/εξόδου ASC. Αυτή η εικόνα δείχνει επίσης τις τιμές των καταχωρητών επιλογής περιφερειακών εισόδων. Εικόνα 41: Επιλογές Ελέγχου και Ρυθμίσεων των Εισόδων/Εξόδων ASC0/ASC1 74

Τέλος, στην τρίτη στήλη της Εικόνας 37 φαίνονται οι καταχωρητές ελέγχου διακοπών. Οι οκτώ διακοπές των μονάδων ASC0 και ASC1 από τις ακόλουθες υπηρεσίες αιτήσεων διακοπών είναι: ASC0_TSRC, ASC1_TSRC: ελέγχει τις διακοπές για αποστολή δεδομένων. ASC0_RSRC, ASC1_RSRC: ελέγχει τις διακοπές για λήψη δεδομένων. ASC0_ESRC, ASC1_ESRC: ελέγχει τις διακοπές για έλεγχο σφαλμάτων. ASC0_TBSRC, ASC1_TBSRC: ελέγχει τις διακοπές όταν ο buffer αποστολής δεδομένων είναι κενός. Εικόνα 42: Καταχωρητές Ελέγχου Διακοπών. 75

4.2.7 Χάρτης Διευθύνσεων Η απόλυτη διεύθυνση ενός καταχωρητή δίνεται από την offset διεύθυνση συν τη βασική διεύθυνση της μονάδας. Σε αυτή την υποπαράγραφο φαίνεται ο πίνακας διευθύνσεων των καταχωρητών. 76

Εικόνα 43: Πίνακας Διευθύνσεων Καταχωρητών 77

ΚΕΦΑΛΑΙΟ 5-Η Υλοποίηση Έχοντας αναφέρει σε προηγούμενη παράγραφο ορισμένα βασικά στοιχεία σχετικά με την ανάπτυξη εφαρμογών σε προγραμματιστικό περιβάλλον Qt καθώς και τα απαιτούμενα στοιχεία του μικροελεγκτή, μπορεί πλέον να αναλυθεί η υλοποίηση του αναπτυγμένου προγράμματος και της επικοινωνίας που ήταν και ο βασικός στόχος αυτής της διπλωματικής εργασίας. Παρακάτω θα γίνει ανάλυση του τρόπου σκέψης που ακολουθήθηκε για την συγκεκριμένη υλοποίηση, θα παρουσιαστούν λεπτομερώς κομμάτια κώδικα της υλοποίησης και θα γίνει ανάλυση της επικοινωνίας μεταξύ υπολογιστή και μικροελεγκτή. Η φυσική υλοποίηση του συστήματος φαίνεται στην Εικόνα 44. Εικόνα 44: Το φυσικό σύστημα 78

5.1 Γενικά Το πρόγραμμα που αναπτύχθηκε στην παρούσα διπλωματική εργασία έχει ως στόχο τον έλεγχο ενός αιολικού συστήματος με επαγωγική γεννήτρια. Η εφαρμογή παρέχει στον χρήστη διαγράμματα για την εποπτεία της συμπεριφοράς του συστήματος καθώς και πλαίσια εισαγωγής δεδομένων. Αυτά τα πλαίσια αλλάζουν βασικές ιδιότητες και μεγέθη του συστήματος σύμφωνα με τις απαιτήσεις του χρήστη. Το πρότυπο που ακολουθήθηκε και τελικά επιτυχώς αναπτύχθηκε φαίνεται στην Εικόνα 45. Εικόνα 45: Αιολικό Σύστημα με Επαγωγική Γεννήτρια Όπως εύκολα μπορεί να διακρίνει κάποιος από την παραπάνω εικόνα, ο χρήστης της εφαρμογής μπορεί να παρακολουθεί τις μεταβολές βασικών παραμέτρων του συστήματος, για παράδειγμα την ταχύτητα του ανέμου αλλά και την ταχύτητα της τουρμπίνας, μέσω ενδείξεων σε οθόνες LCD. Δίπλα σε αυτές τις ενδείξεις υπάρχουν τα αντίστοιχα κουμπιά που εμφανίζουν σε νέο παράθυρο το διάγραμμα της αντίστοιχης τιμής σε σχέση με το χρόνο, όπως φαίνεται στην Εικόνα 46. Εκτός από αυτά τα κουμπιά υπάρχουν και δύο πολύ σημαντικά κουμπιά τα Start και Stop. Το πρώτο κουμπί είναι απαραίτητο για την έναρξη του συστήματος ενώ το δεύτερο σταματάει τη λειτουργία του συστήματος οποιαδήποτε χρονική στιγμή. Επιπλέον, το κουμπί 79

sim_off έχει σαν σκοπό να σταματάει την διαδικασία προσομοίωσης στην οποία μπαίνει το πρόγραμμα με την έναρξη του. Τέλος, πέραν των επιπλέον δύο βασικών διαγραμμάτων Pout-Time και Speed-Time που περιλαμβάνονται στο βασικό παράθυρο της εφαρμογής υπάρχουν και τα τρία κουμπιά Rectifier C.S., Inverter C.S. και Basic Control System. Αυτά τα κουμπιά παράγουν τα πλαίσια εισαγωγής δεδομένων σε νέα παράθυρα και είναι υπεύθυνα για την αποστολή αυτών των δεδομένων στον μικροελεγκτή για έλεγχο του συστήματος. Εικόνα 46: Σύστημα μετά την πίεση του κουμπιού T-t Για την παραγωγή του προγράμματος ήταν απαραίτητη η δημιουργία νέου project στο περιβάλλον Qt. Έγινε επιλογή του Qt Gui application έχοντας ως βασική κλάση την QMainWindow. Πολλές από τις τεχνικές που παρουσιάστηκαν στο κεφάλαιο 3 και είχαν ως θέμα το QDialog είναι παρόμοιες με τις τεχνικές που θα παρουσιαστούν εδώ. Αυτό οφείλεται στο ότι και το QDialog αλλά και το QMainWindow προέρχονται από το QWidget. Το πρόγραμμα μπορεί να δουλέψει σε πλατφόρμα Windows καθώς και σε πλατφόρμα Unix. Ο χρήστης δεν χρειάζεται να έχει γνώσεις προγραμματισμού και το πρόγραμμα μπορεί να χαρακτηριστεί ως αρκετά εύκολο στη χρήση. Από την άλλη για την κατανόηση των παρακάτω παραγράφων καλό θα ήταν να υπάρχει κάποιο σχετικό 80

υπόβαθρο σε σχέση με τον προγραμματισμό σε γλώσσα C++. Παρόλα αυτά έχει γίνει μια προσπάθεια επεξήγησης ακόμα και σχετικά απλών εννοιών για να μπορέσει το σύγγραμμα να είναι προσιτό και σε αναγνώστες με περιορισμένες γνώσεις προγραμματισμού. 5.2 Επικοινωνία Υπολογιστή-Μικροελεγκτή 5 Στο σύστημα που αναπτύχθηκε ο μικροελεγκτής είναι ένα σημαντικό κομμάτι όσον αφορά τον έλεγχο. Για αυτό το λόγο, ο υπολογιστής στον οποίο θα τρέχει η εφαρμογή θα πρέπει να συνδεθεί με τον μικροελεγκτή έτσι ώστε να μπορεί να γίνεται ανταλλαγή δεδομένων. Τα δεδομένα που ανταλλάσσονται μεταξύ τους είναι δύο ειδών, αυτά που στέλνει ο μικροελεγκτής στον υπολογιστή και αυτά που στέλνει ο υπολογιστής στον μικροελεγκτή. Για να μπορέσει να γίνει αυτή η δοσοληψία δεδομένων χρησιμοποιήθηκε σειριακή επικοινωνία μεταξύ υπολογιστή και μικροελεγκτή. Στη σειριακή επικοινωνία τα δεδομένα στέλνονται ακολουθιακά μέσω ενός καναλιού επικοινωνίας, δηλαδή ανά κάποιο ορισμένο χρονικό διάστημα στέλνεται και ένα bit. Η σειριακή επικοινωνία χρησιμοποιείται για μεγάλων αποστάσεων επικοινωνίες, όπου η παράλληλη επικοινωνία είναι ανέφικτη λόγω είτε του υπερβολικού κόστους του καλωδίου είτε των δυσκολιών που παρουσιάζονται στο συγχρονισμό. Ο μικροελεγκτής στην προκειμένη περίπτωση έχει μια σχετικά μεγάλη απόσταση από τον υπολογιστή και για αυτό η σειριακή επικοινωνία είναι και η ενδεδειγμένη λύση. Επίσης ένας ακόμη σημαντικός λόγος της χρήσης της σειριακής επικοινωνίας είναι και το γεγονός ότι μόνο αυτή μπορεί να υποστηριχτεί από τον μικροελεγκτή μέσω του hardware που διαθέτει. 5.2.1 Σύνδεση υπολογιστή μικροελεγκτή Η σύνδεση μικροελεγκτή και υπολογιστή για σειριακή επικοινωνία μπορεί να πραγματοποιηθεί με δύο τρόπους. Ο πρώτος τρόπος είναι να γίνει μέσω καλωδίου RS- 5 Όλα τα αρχεία κώδικα που θα αναφερθούν δεν παρουσιάζονται ολοκληρωμένα αλλά αναφέρονται ορισμένα κομμάτια που κρίθηκαν ως πιο σημαντικά και κομβικά Όσον αφορά την υλοποίηση. 81

232. Τα pin του καλωδίου φαίνονται στην Εικόνα 27. Το RS-232 (Recommended Standard 232) είναι ένα πρότυπο για σειριακή μετάδοση δυαδικών σημάτων δεδομένων μεταξύ ενός DTE (Data terminal equipment) και ενός DCE (Data Circuit-terminating equipment). Χρησιμοποιείται συχνά στις σειριακές θύρες των προσωπικών υπολογιστών. Όταν χρησιμοποιείται αυτός ο τρόπος σύνδεσης θα πρέπει ο μικροελεγκτής να συνδέεται με ξεχωριστό καλώδιο στην παροχή ρεύματος. Εικόνα 47: Τα pin του RS-232 καλωδίου Ο δεύτερος τρόπος σύνδεσης του μικροελεγκτή με τον υπολογιστή είναι μέσω καλωδίου USB. Ο μικροελεγκτής της Infineon TC1798 της οικογένειας AUDO MAX που χρησιμοποιήθηκε έχει μία θύρα USB. Ο Ενιαίος Σειριακός Δίαυλος (USB) είναι τμηματικό πρότυπο δίαυλου για τη διασύνδεση συσκευών. Ο USB έχει ως σκοπό να επιτρέψει στις περιφερειακές μονάδες να συνδέονται με τον υπολογιστή χρησιμοποιώντας μια ενιαία τυποποιημένη υποδοχή διεπαφών και να βελτιώσει τις έτοιμες προς χρήση ικανότητες των συσκευών για σύνδεση ή αποσύνδεσή τους με το σύστημα χωρίς να χρειάζεται επανεκκίνηση. Άλλα χαρακτηριστικά γνωρίσματα περιλαμβάνουν την παροχή ηλεκτρικού ρεύματος στις συσκευές χαμηλής κατανάλωσης χωρίς την ανάγκη εξωτερικής παροχής ηλεκτρικού ρεύματος και την δυνατότητα πολλών συσκευών USB να χρησιμοποιηθούν χωρίς την απαίτηση ρυθμίσεων ή μεμονωμένων προγραμμάτων οδήγησης (drivers) από τους κατασκευαστές για να 82

εγκατασταθούν. Έτσι, μέσω της σύνδεσης με USB επιτυγχάνεται και αποστολή δεδομένων αλλά και πλήρης ενεργειακή κάλυψη των αναγκών του μικροελεγκτή. Για να επιτευχθεί σειριακή επικοινωνία μέσω USB η εταιρία της Infineon παρέχει στους πελάτες της ένα εργαλείο το DAS Tool Interface. Το εργαλείο αυτό χρησιμοποιήθηκε με σκοπό την εικονική μετατροπή της εκάστοτε θύρας USB του υπολογιστή που συνδέεται με το μικροελεγκτή σε μια σειριακή θύρα. Με αυτόν τον τρόπο στο Device Manager του υπολογιστή εμφανίζεται μία επιπλέον εικονική σειριακή θύρα. Παραπάνω ρυθμίσεις δεν χρειάζεται να γίνουν και η συμπεριφορά της επικοινωνίας είναι ίδια με αυτή της σύνδεσης του μικροελεγκτή και του υπολογιστή με καλώδιο RS-232 που περιγράφηκε προηγουμένως. 5.2.2 Πρωτόκολλο Επικοινωνίας Η δημιουργία ενός πρωτόκολλου επικοινωνίας ήταν απαραίτητη προϋπόθεση για τον άρτιο σχεδιασμό της επικοινωνίας μεταξύ υπολογιστή και μικροελεγκτή. Στόχος του πρωτοκόλλου είναι να μπορέσει να υπάρξει μία άριστη διαδικασία ανταλλαγής δεδομένων. Τα δεδομένα πρέπει να στέλνονται με τον ταχύτερο δυνατό τρόπο. Αυτό σημαίνει πως πρέπει να στέλνονται όσο το δυνατόν περισσότερα bits σε προκαθορισμένο χρονικό διάστημα. Επίσης, πολύ σημαντική θεωρείται και η αξιοπιστία της επικοινωνίας. Τα δεδομένα είναι αναγκαίο να στέλνονται και προς τις δύο κατευθύνσεις. Η αξιοπιστία εξασφαλίζεται με την ακέραια αποστολή των δεδομένων χωρίς παραποιήσεις ή ακόμα και ελλείψεις ορισμένων κομματιών τους. Το πρωτόκολλο ορίζει πως κάθε τιμή που στέλνεται από τον μικροελεγκτή προς τον υπολογιστή ή από τον υπολογιστή προς τον μικροελεγκτή θα πρέπει να έχει μέγεθος 5 bytes, δηλαδή 40 bits. Το πρώτο byte είναι byte αναγνώρισης του τύπου της τιμής που στέλνεται. Για παράδειγμα ορίστηκε πως για την αποστολή από τον υπολογιστή προς τον μικροελεγκτή της ταχύτητας αναφοράς, το πρώτο byte θα πρέπει να είναι το γράμμα e αν η τιμή είναι θετική ή το γράμμα E αν η τιμή είναι αρνητική. Με αυτόν τον τρόπο ο μικροελεγκτής αναγνωρίζει πως η τιμή που πήρε είναι αυτή της ταχύτητας αναφοράς αποφεύγοντας την σύγχυση λόγω μεγάλου αριθμού διαφορετικών τιμών. Τα άλλα τέσσερα byte έχουν να κάνουν με την αυτή καθεαυτή τιμή της μεταβλητής. Τα δεδομένα που στέλνονται και προς τις δύο κατευθύνσεις έχουν ως σκοπό την αποστολή 83

και την λήψη δεκαδικών (float) αριθμών. Οι δεκαδικοί αριθμοί ανάλογα με την ακρίβεια που έχουν, μεταλλάσσονται ως προς το μέγεθος. Για να μπορέσει να μικρύνει η ποσότητα της πληροφορίας χωρίς να επηρεάζεται η ακρίβεια της τιμής ακολουθήθηκε μια τυποποιημένη διαδικασία. Το ακέραιο καθώς και το δεκαδικό μέρος χωρίστηκαν σε δύο bytes το καθένα. Το ένα είναι το byte υψηλότερης σημασίας και το άλλο είναι το byte χαμηλότερης σημασίας. Η διαδικασία αυτή θα αναλυθεί περισσότερο σε επόμενα υποκεφάλαια. Οι μεταβλητές καθώς και τα αναγνωριστικά bytes που στέλνονται από τον υπολογιστή στον μικροελεγκτή και αντίστροφα φαίνονται στους παρακάτω πίνακες: Πίνακας 1: Bytes αναγνώρισης για μεταβλητές του Rectifier. Rectifier Variables Kp Ki MPPT Speed_ref Value p i m e Πίνακας 2: Bytes αναγνώρισης για μεταβλητές του Inverter. Inverter Variables Kp Ki Value k l Πίνακας 3: Bytes αναγνώρισης για βασικές μεταβλητές. Basic Variables P V F Value w v f 84

Πίνακας 4: Bytes αναγνώρισης για μεταβλητές εισόδου του υπολογιστή. Input variables Variables Speed Vdc Ia Ib Ic Torque Time Value 1(θετικό) 2(αρνητικό) d a b c n t Οι τρείς πρώτοι πίνακες σχετίζονται με την αποστολή δεδομένων από τον υπολογιστή στον μικροελεγκτή ενώ μόνο ο τελευταίος πίνακας σχετίζεται με την αποστολή των δεδομένων από τον μικροελεγκτή στον υπολογιστή. Στα values που είναι και τα bytes αναγνώρισης έχει εισαχθεί μόνο η τιμή για αποστολή θετικού variable. Το αρνητικό του κάθε variable είναι το αντίστοιχο κεφαλαίο γράμμα. Στον πίνακα Input variables η μεταβλητή Speed έχει σαν αναγνωριστικό byte το 1 για θετικές τιμές και 2 για αρνητικές τιμές. Η μεταβλητή Speed είναι η πρώτη μεταβλητή που στέλνεται και πρέπει να αναζητείται από τον αλγόριθμο ως αρχή. Επειδή δεν χρησιμοποιήθηκε κωδικοποίηση ASCII, οι τιμές των bytes αναγνώρισης που είναι σύμβολα γραμμάτων βρίσκονται μέσα στο πεδίο τιμών των μεταβλητών. Έτσι, για να μπορέσει να ξεκαθαριστεί πότε ξεκινάει ένα νέο πακέτο και για να μην υπάρξει σύγχυση των τιμών του πακέτου χρησιμοποιήθηκε το 1 και το 2 ως αναγνωριστικά bytes για την πρώτη μεταβλητή. Η χρήση αυτού του πρωτοκόλλου έχει ένα μεγάλο πλεονέκτημα σε σχέση με τον κλασικό τρόπο ανταλλαγής δεδομένων όπου κάθε ψηφίο ενός δεκαδικού αριθμού στέλνεται σαν ένας χαρακτήρας ASCII. Τα δεδομένα που ανταλλάσσονται μεταξύ υπολογιστή και μικροελεγκτή, όπως αναφέρθηκε και πιο πριν, είναι δεκαδικοί (float) αριθμοί. Στον κλασικό τρόπο ανταλλαγής δεδομένων ένας float αριθμός χρειάζεται 8 bytes για τα ψηφία του (4 χαρακτήρες ASCII για το ακέραιο μέρος και 4 χαρακτήρες ASCII για το δεκαδικό μέρος), 1 byte για την υποδιαστολή και 1 byte αναγνώρισης δηλαδή σύνολο 10 bytes. Από την άλλη, το πρωτόκολλο που δημιουργήθηκε 85

καταφέρνει στον ίδιο χρόνο να στέλνει έναν float αριθμό με μόλις 5 bytes. Σε λειτουργία 400Hz με τον κλασσικό τρόπο μπορούν να σταλούν το πολύ 3.2 μεταβλητές ενώ με το πρωτόκολλο μπορούν να σταλούν το μέγιστο μέχρι 7.2 μεταβλητές. Όπως μπορεί να γίνει εύκολα αντιληπτό, το πρωτόκολλο διπλασίασε την ταχύτητα αποστολής δεδομένων κρατώντας την αξιοπιστία της επικοινωνίας σε υψηλά επίπεδα. 5.2.3 Αρχικοποίηση της ασύγχρονης σειριακής επικοινωνίας στο Qt Η αρχικοποίηση της ασύγχρονης σειριακής επικοινωνίας πραγματοποιείται στα δύο κύρια αρχεία του προγράμματος, το mainwindow.h και το mainwindow.cpp. Όπως αναφέρθηκε στο δεύτερο κεφάλαιο του παρόντος συγγράμματος η ασύγχρονη σειριακή επικοινωνία επιτυγχάνεται στο Qt έπειτα από την προσθήκη της εξωτερικής βιβλιοθήκης QextSerialPort. Έπειτα από αυτή την προσθήκη, γίνεται εισαγωγή στο αρχείο header mainwindow.h των εξής: 1 #include "qextserialport.h" 2 class MainWindow : public QMainWindow 3 { 4 Q_OBJECT 5 private: 6 QextSerialPort *port; 7 }; Στην γραμμή 1 περιλαμβάνεται το qextserialport.h αρχείο ούτως ώστε να είναι εφικτή η δήλωση αντικειμένων για δημιουργία port επικοινωνίας. Στην γραμμή 6 δηλώνεται ως ιδιωτική μεταβλητή της κλάσης MainWindow το αντικείμενο με όνομα port. Το αντικείμενο port που ορίζεται στο αρχείο maninwindow.h με τον τρόπο που φαίνεται παραπάνω είναι καθολικό για όλο το πρόγραμμα. Οι αλλαγές και προσθήκες για την σωστή δημιουργία της ασύγχρονης σειριακής επικοινωνίας που γίνονται στο αρχείο mainwindow.cpp είναι καθοριστικές για το πως 86

θα λειτουργήσει το σύστημα. Παρακάτω φαίνονται οι γραμμές κώδικα που σχετίζονται με αυτές τις προσθήκες: 1 #include "mainwindow.h" 2 MainWindow::MainWindow(QWidget *parent) : 3 QMainWindow(parent), 4 ui(new Ui::MainWindow) 5 { 6 ui->setupui(this); 7 port = new QextSerialPort( ); 8 port->setportname("com1"); 9 port->setbaudrate(baud115200); 10 port->setparity(par_none); 11 port->setdatabits(data_8); 12 port->setstopbits(stop_1); 13 port->open( QIODevice::ReadWrite ); 14 connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead())); Στην έβδομη σειρά κώδικα ορίζεται ο constructor της κλάσης για το αντικείμενο port. Από την γραμμή κώδικα 8 έως την γραμμή κώδικα 13 καλούνται συναρτήσεις της κλάσης QextSerialPort για τη ρύθμιση της πόρτας επικοινωνίας. Όπως μπορεί εύκολα κάποιος να παρατηρήσει, η συνάρτηση setportname() ορίζει τη θύρα του υπολογιστή μέσω της οποίας θα πραγματοποιηθεί η επικοινωνία. Οι περισσότεροι υπολογιστές έχουν μία θύρα για σειριακή επικοινωνία η οποία συνήθως έχει το όνομα COM1. Στην γραμμή 9 ορίζεται το Baud rate της επικοινωνίας. Επειδή η σύνδεση του υπολογιστή με τον μικροελεγκτή γίνεται απευθείας μέσω καλωδίου, το Baud rate έχει ταυτόσημη ερμηνεία με το Bits per second. Αυτό έχει σαν αποτέλεσμα να μπορεί να πραγματοποιηθεί επικοινωνία με ανταλλαγή 115200 bits το δευτερόλεπτο. Στη γραμμή 10 ορίζεται πως δεν θα πρέπει να υπάρχει parity bit ενώ στις γραμμές 11 και 12 87

ορίζονται αντίστοιχα 8 bit δεδομένων για την επικοινωνία και ένα stop bit. Η συνάρτηση open() ανοίγει την θύρα επικοινωνίας μεταξύ των δυο συσκευών και παίρνει σαν όρισμα το QIODevice::ReadWrite. Αυτό το όρισμα επιτρέπει την αποστολή αλλά και την λήψη δεδομένων και προς τις δύο κατευθύνσεις. Τέλος, στην γραμμή 14 λειτουργεί ο μηχανισμός signal and slots που αναφέρθηκε εκτενώς στο κεφάλαιο 3. Εδώ κάθε φορά που υπάρχουν διαθέσιμα δεδομένα προς ανάγνωση από την πλευρά του υπολογιστή, θα καλείται η συνάρτηση onreadyread() που σχετίζεται με την τοποθέτηση των δεδομένων σε κατάλληλους πίνακες και θα αναλυθεί σε επόμενη υποπαράγραφο. Άξιο αναφοράς είναι πως στον κώδικα δεν συμπεριλαμβάνεται καθόλου το αρχείο qextserialport.h όπως έγινε στο αρχείο mainwindow.h. Αυτό έγινε διότι στην πρώτη γραμμή του κώδικα συμπεριλήφθηκε το αρχείο mainwindow.h που ήδη περιέχει το qextserialport.h, έτσι μια επιπλέον αναφορά του θα ήταν περιττή. 5.2.3 Υλοποίηση της Λήψεις Δεδομένων από τον Μικροελεγκτή Η υλοποίηση της λήψης δεδομένων από τον μικροελεγκτή πραγματοποιείται μέσω της συνάρτησης slot onreadyread(). Η συνάρτηση αυτή αναφέρθηκε στην προηγούμενη παράγραφο λόγω της σύνδεσης της με την διαθεσιμότητα των προς ανάγνωση δεδομένων στην θύρα του υπολογιστή. Η συνάρτηση τοποθετεί τα δεδομένα σε καθολικούς πίνακες που ορίστηκαν στο αρχείο mainwindow.h: 1 double time[500]; 2 double Speed[500]; 3 double turbine_torque_array[500]; Ενώ η συνάρτηση ορίζεται σαν ιδιωτικό slot ως εξής: private slots: void onreadyread(); Η υλοποίηση του αλγορίθμου της συνάρτησης slot onreadyread() γίνεται στο αρχείο mainwindow.cpp. Ο κώδικας της συνάρτησης slot αποτελείται από πολλές γραμμές κώδικα και είναι ασύμφορο να εισαχθούν στο παρόν κείμενο. 88

Τα bytes που έρχονται με αρκετά μεγάλο ρυθμό στην θύρα του υπολογιστή διαβάζονται με συνεχή τρόπο. Αρχικά, κάθε φορά που υπάρχουν διαθέσιμα δεδομένα στη θύρα, τοποθετούνται όλα σε έναν πίνακα χαρακτήρων. Έπειτα, σαρώνεται αυτός ο πίνακας χαρακτήρων κελί προς κελί και τοποθετούνται τα δεδομένα σε πίνακες τύπου double όπως αυτοί που ορίστηκαν προηγουμένως. Αυτή η σάρωση γίνεται μέσω μιας for που έχει σαν αρχή το μηδενικό κελί και σαν πέρας το τελευταίο κελί του πίνακα χαρακτήρων. Κάθε φορά που ο αλγόριθμος βρίσκει σε ένα κελί ένα αναγνωριστικό byte μπαίνει μέσα στην αντίστοιχη if που έχει δημιουργηθεί για αυτό το αναγνωριστικό. Εκεί συγκροτείται ο αριθμός από τα επόμενα 4 κελιά του πίνακα χαρακτήρων που περιλαμβάνει τα 4 byte του αριθμού. Για να μπορέσει να επιτευχθεί σωστά αυτή η συγκρότηση της τιμής καλείται μια ακόμα συνάρτηση η apotelesma_eiserxomenwn(char *array). Αυτή αναπτύσσεται ως εξής: 1 double MainWindow::apotelesma_eiserxomenwn(char *array){ 2 double apotelesma; 3 mi=array[0]; 4 mostint=mi; 5 li=array[1]; 6 leastint=li; 7 mf=array[2]; 8 mostfloat=mf; 9 lf=array[3]; 10 leastfloat=lf; 11 apotelesma=(mostint-3)*256+(leastint-3)+(mostfloat-3)*0.0039+(leastfloat- 3)*0.0000152587; 12 return apotelesma; 13 } 89

Το όρισμα (char *array) της συνάρτησης ουσιαστικά θα περιλαμβάνει έναν πίνακα τεσσάρων κελιών που ως περιεχόμενο θα έχει τα τέσσερα byte του αριθμού. Το μηδενικό κελί που είναι και το πρώτο περιέχει το μεγαλύτερης σημασίας byte του ακέραιου μέρους ενώ το κελί ένα περιέχει το λιγότερης σημασίας byte του ακέραιου μέρους. Αντίστοιχα, τα κελιά τρία και τέσσερα περιέχουν τα μεγαλύτερης και λιγότερης σημασίας byte του δεκαδικού μέρους. Έτσι, στην γραμμή 11 δημιουργείται ο double αριθμός apotelesma από την συγκρότηση όλων αυτών των bytes. Μπορεί εύκολα να παρατηρηθεί πως κάθε ένα από τα byte αφαιρείται με το 3 πριν πολλαπλασιαστή με τον κατάλληλο αριθμό για να προκύψει ο αριθμός. Αυτό γίνεται διότι πριν στείλει ο μικροελεγκτής κάθε byte το προσθέτει με το 3 για να μην γίνει σύγχυση μεταξύ πεδίου τιμών των byte αναγνώρισης και πεδίου τιμών των byte του ζητούμενου αριθμού. Με αυτό τον τρόπο επιστρέφεται η μεταβλητή apotelesma της συνάρτησης apotelesma_eiserxomenwn(char *array) στην μεταβλητή apotelesma της συνάρτησης onreadyread(). Εκεί υπάρχει ένα φίλτρο που ελέγχει αν η τιμή της μεταβλητής apotelesma που θέλει να τοποθετηθεί σε ένα πίνακα διαφέρει πολύ από την τελευταία τιμή που είχε ο πίνακας. Για παράδειγμα για τον πίνακα δεδομένων 500 θέσεων της ταχύτητας της ανεμογεννήτριας Speed υλοποιήθηκε το εξής φίλτρο: 1 if((apotelesma-speed[498]>50) (apotelesma-speed[498]<-50)){ 2 apotelesma=speed[498]; 3 } 4 Speed[499]=apotelesma; Η προσθήκη φίλτρων στους αλγόριθμους που σχετίζονται με την επικοινωνία είναι απαραίτητη. Στην ασύγχρονη σειριακή επικοινωνία μπορεί να προκληθεί αστοχία της μετάδοσης ορισμένων κομματιών δεδομένων λόγω εξωτερικών παραγόντων όπως ο ηλεκτρικός θόρυβος. Όταν συμβαίνει κάτι τέτοιο παρατηρούνται αιχμές σε διαγράμματα και απεικονίσεις των δεδομένων, κάνοντας δύσκολη την παρακολούθηση και τον έλεγχο του συστήματος. Στο παραπάνω φίλτρο ταχύτητας δεν επιτρέπεται η παρούσα τιμή να απέχει περισσότερο από 50 μονάδες από την προηγούμενη τιμή. Σε περίπτωση όμως που η διαφορά είναι μεγαλύτερη από 50 μονάδες η παρούσα τιμή απορρίπτεται και στην θέση της μπαίνει η προηγούμενη. Εκτός από το παραπάνω 90

φίλτρο για την ταχύτητα υπάρχουν σαφώς και άλλα φίλτρα για άλλες τιμές όπου ο έλεγχος δεν γίνεται στις 50 μονάδες αλλά σε αριθμό μονάδων που σχετίζεται με το αναμενόμενο εύρος τιμών της εκάστοτε μεταβλητής. Παρακάτω φαίνεται ο αλγόριθμος για ανίχνευση θετικής τιμής ταχύτητας: 1 if((c[i]== 1) (stop_s)){ 2 stop_s=false; 3 while((g<4)&&(stop_s==false)){ 4 if ((i+in_count+1)>megethos){ 5 stop_s=true; 6 in_count=-1; 7 } 8 else{ 9 temp[g]=c[i+in_count+1]; 10 g++; 11 in_count++; 12 } 13 } 14 if(stop_s==false){ 15 apotelesma=apotelesma_eiserxomenwn(temp); 16 for(r=0;r<499;r++){ 17 Speed[r]=Speed[r+1]; 18 } 19 if((apotelesma-speed[498]>50) (apotelesma-speed[498]<-50)){ 20 apotelesma=speed[498]; 21 } 22 Speed[499]=apotelesma; 23 g=0; 24 in_count=0; 25 } 26 } 91

Εκτός από τον έλεγχο για το αν ο πίνακας χαρακτήρων έχει στο κελί του το αναγνωριστικό byte, φαίνεται στην πρώτη γραμμή κώδικα πως υπάρχει και μια άλλη μεταβλητή. Αυτή η μεταβλητή είναι καθολική μεταβλητή τύπου bool και ορίζεται στο αρχείο mainwindow.h. Ο μικροελεγκτής μπορεί να διακόψει την αποστολή δεδομένων σε σημείο όπου o παραπάνω αλγόριθμος δεν έχει όλα τα byte για να συγκροτήσει τον αριθμό. Επειδή όμως στη σειριακή επικοινωνία στέλνονται συνεχόμενα τα bytes, στην επόμενη αποστολή δεδομένων αυτά τα bytes που δεν είχαν σταλεί θα είναι πρώτα στο πακέτο. Για να μην χαθούν τα δεδομένα υπάρχει αυτή η bool μεταβλητή όπου παραμένει true ώσπου να ολοκληρωθεί η συγκρότηση όλων των byte. Αν το πακέτο διακοπεί πριν την συγκρότηση όλων των byte, τότε με την έλευση του επόμενου πακέτου θα ενεργοποιηθεί το κομμάτι του κώδικα που έχει την bool μεταβλητή true και θα συνεχίσει από το σημείο που ήταν λόγω και του καθολικού μετρητή που υπάρχει και είναι κοινός για όλα τα if. Όταν τελειώσει η διαδικασία συγκρότησης του αριθμού η εκάστοτε bool μεταβλητή γίνεται false για να μην επηρεάσει περαιτέρω τον αλγόριθμο. Τέλος, στις γραμμές 16 έως 18 γίνεται μία αριστερή ολίσθηση του πίνακα κατά ένα κελί ενώ στην γραμμή 22 τοποθετείται η τελευταία τιμή στο τέλος του πίνακα. Αυτό έχει ως σκοπό να υπάρχουν διαθέσιμες πάντα οι τελευταίες τιμές που διαβάστηκαν από την θύρα ώστε να διατηρούνται τα διαγράμματα και οι εποπτικοί μηχανισμοί ενημερωμένοι. 5.2.4 Υλοποίηση της Αποστολής Δεδομένων προς τον Μικροελεγκτή Αφού έγινε ανάλυση της διαδικασίας λήψης δεδομένων στο υλοποιημένο πρόγραμμα Qt ήρθε η ώρα να ολοκληρωθεί το κομμάτι της επικοινωνίας, από την πλευρά του υπολογιστή, με την ανάλυση του τρόπου με τον οποίο υλοποιήθηκε η αποστολή δεδομένων από τον υπολογιστή προς τον μικροελεγκτή. Στην Εικόνα 43, μπορεί εύκολα κάποιος να διακρίνει πως τα τρία κουμπιά με τα οποία πραγματοποιείται η αποστολή των δεδομένων είναι τα Rectifier C.S., Inverter C.S. και Basic Control System. Το Rectifier C.S. παράγει ένα πλαίσιο εισαγωγής και αποστολής δεδομένων που επηρεάζει τις ιδιότητες του ανορθωτή του συστήματος. Αντίστοιχα, το Inverter C.S. παράγει ένα πλαίσιο εισαγωγής και αποστολής δεδομένων που επηρεάζει τις ιδιότητες του αντιστροφέα του συστήματος ενώ το Basic Control 92

System επηρεάζει περισσότερο κάποιες βασικές ιδιότητες του συστήματος. Το πώς απεικονίζεται ένα από αυτά τα πλαίσια φαίνεται στην Εικόνα 46. Για να υλοποιηθεί το πλήκτρο Rectifier C.S., ορίστηκε σαν καθολικό αντικείμενο της κλάσης QPushButton το rectifier_button. Στο αρχείο mainwindow.cpp ορίστηκε ο εξής κώδικας: 1 rectifier_button=new QPushButton(this); 2 rectifier_button->settext("rectifier C.S."); 3 connect(rectifier_button,signal(clicked()),this,slot(control_rectifier())); Ο παραπάνω κώδικας θέτει το πλήκτρο στο πλαίσιο του βασικού παραθύρου, ορίζει το όνομα του πλήκτρου και τέλος συνδέει την πίεση του πλήκτρου με μία συνάρτηση που είναι υπεύθυνη για την δημιουργία και τον σχηματισμό του επιπλέον παραθύρου. Εικόνα 48: Πλαίσιο αποστολής δεδομένων του Rectifier Η συνάρτηση slot control_rectifier() είναι βασικό παράδειγμα δημιουργίας φόρμας συμπλήρωσης και αποστολής δεδομένων. Το Inverter C.S καθώς και το Basic 93

Control System δημιουργούνται με παρόμοιο τρόπο με αυτόν που περιγράφεται σε αυτή τη παράγραφο. Ο κώδικας της συνάρτησης slot παρουσιάζεται παρακάτω: 1 void MainWindow::control_rectifier(){ 2 QVBoxLayout *layout1=new QVBoxLayout(); 3 layout1->addwidget(kp_rect); 4 layout1->addwidget(ki_rect); 5 layout1->addwidget(mppt_rect); 6 layout1->addwidget(speed_ref_rect); 7 QVBoxLayout *layout2=new QVBoxLayout(); 8 layout2->addwidget(kp_rectifier); 9 layout2->addwidget(ki_rectifier); 10 layout2->addwidget(mppt_rectifier); 11 layout2->addwidget(speed_ref_rectifier); 12 QVBoxLayout *layout3=new QVBoxLayout(); 13 layout3->addwidget(kp_rect_send); 14 layout3->addwidget(ki_rect_send); 15 layout3->addwidget(mppt_rect_send); 16 layout3->addwidget(speed_ref_send); 17 QHBoxLayout *layouth=new QHBoxLayout(); 18 layouth->addlayout(layout1); 19 layouth->addlayout(layout2); 20 layouth->addlayout(layout3); 21 QWidget *window=new QWidget(); 22 window->setwindowtitle("rectifier Control Center"); 23 window->setlayout(layouth); 24 window->show(); 25 connect(kp_rect_send,signal(clicked()),this,slot(senddata_kp_rectifier())); 26 connect(ki_rect_send,signal(clicked()),this,slot(senddata_ki_rectifier())); 27 connect(mppt_rect_send,signal(clicked()),this, SLOT(sendData_MPPT_rectifier())); 28 connect(speed_ref_send,signal(clicked()),this, SLOT(sendData_speed_ref_rectifier())); } 94

Το καινούργιο και σημαντικό κομμάτι βρίσκεται στις γραμμές 21 έως 24. Σε αυτές τις γραμμές ορίζεται ένα αντικείμενο της κλάσης QWidget που είναι widget γονιός όλων των αντικειμένων layout που ορίστηκαν στις προηγούμενες γραμμές. Αυτή η κληρονομικότητα υλοποιείται στην γραμμή 23 μέσω της συνάρτησης setlayout(). Ουσιαστικά, αυτό που υλοποιεί το αντικείμενο window είναι η δημιουργία ενός νέου παραθύρου με ξεχωριστό τίτλο( γραμμή 22) και ξεχωριστά widgets. Αυτό το νέο παράθυρο είναι ορατό στον χρήστη μετά από το κάλεσμα της εντολής show(). Στις προηγούμενες γραμμές κώδικα (από 2 έως 20 ) διακρίνεται η διαδικασία τοποθέτησης των widgets στις επιθυμητές θέσεις, για να υπάρξει το αποτέλεσμα που φαίνεται στην Εικόνα 28, μέσω της χρήσης των αντικειμένων layout. Αυτό που είναι αρκετά σημαντικό για την επικοινωνία είναι οι τελευταίες τέσσερις γραμμές κώδικα. Σε αυτές τις γραμμές γίνεται η σύνδεση των αντικειμένων των κουμπιών με αντίστοιχες συναρτήσεις που έχουν ως σκοπό να στείλουν τα δεδομένα που είναι γραμμένα μέσα στα αντικείμενα των QLineEdit στον μικροελεγκτή. Για παράδειγμα στην γραμμή 28 το κουμπί speed_ref_send είναι ουσιαστικά συνδεδεμένο με την αποστολή των δεδομένων που είναι γραμμένες μέσα στο αντικείμενο speed_ref_rectifier. Αυτή η αποστολή των δεδομένων υλοποιείται μέσω της συνάρτησης senddata_speed_ref_rectifier() της οποίας ο αλγόριθμος χωρίζεται σε δύο μέρη για καλύτερη εποπτεία. Το πρώτο μέρος φαίνεται παρακάτω: 1 QString text1; 2 QByteArray aprosimo,tprosimo,akeraiosmost,akeraiosleast; 3 QByteArray dekadikosmost,dekadikosleast,temp; 4 float arithmos,dekadikos; 5 int i,ak,dek,temp1,temp2; 6 char thetiko[1],arnitiko[1],akm[1],akl[1],dekm[1],dekl[1]; 8 unsigned char p1,p2,p3,p4; 9 text1=speed_ref_rectifier->text(); 10 temp=text1.toascii(); 11 arithmos=atof(temp); 12 thetiko[0]='e'; 13 arnitiko[0]='e'; 14 QString sdata1=qstring(thetiko[0]); 95

15 QString sdata2=qstring(arnitiko[0]); 16 tprosimo=sdata1.toascii(); 17 aprosimo=sdata2.toascii(); 18 if(arithmos<0){ 19 arithmos=arithmos*(-1); 20 port->write(aprosimo); 21 port->flush(); } 22 else if(arithmos>0){ 23 port->write(tprosimo); 24 port->flush(); } Στις αρχικές γραμμές του κώδικα ορίζονται κάποιες τοπικές μεταβλητές που εξυπηρετούν της πράξεις που χρειάζεται να πραγματοποιηθούν. Στη γραμμή 10 μετατρέπεται το περιεχόμενο του αντικειμένου speed_ref_rectifier σε ASCII, ενώ στη γραμμή 11 η συνάρτηση atof() είναι υπεύθυνη για την μετατροπή του string σε ένα float αριθμό. Αυτό γίνεται για να μπορέσει να ελεγχθεί αρχικά αν ο αριθμός που πληκτρολογήθηκε από τον χρήστη είναι θετικός ή αρνητικός και αντίστοιχα να σταλεί το κατάλληλο byte αναγνώρισης (γραμμές 18-24) καθώς επίσης να μπορέσει ο αριθμός να χωριστεί σε τέσσερα byte και να σταλεί σύμφωνα με το πρωτόκολλο επικοινωνίας. Το δεύτερο κομμάτι κώδικα της συνάρτησης που είναι υπεύθυνο για την διαχείριση και αποστολή των δεδομένων σύμφωνα με το πρωτόκολλο επικοινωνίας φαίνεται παρακάτω: 25 ak=(int)arithmos; 26 dekadikos=arithmos-ak; 27 dekadikos=dekadikos*65535; 28 dek=dekadikos; 29 p1=(char)ak; 30 temp1=ak>>8; 31 p2=(char)temp1; 32 akl[0]=p1; 96

33 akm[0]=p2; 34 p3=(char)dek; 35 temp2=dek>>8; 36 p4=(char)temp2; 37 dekl[0]=p3; 38 dekm[0]=p4; 39 QString sdata3=qstring(akl[0]); 40 QString sdata4=qstring(akm[0]); 41 QString sdata5=qstring(dekl[0]); 42 QString sdata6=qstring(dekm[0]); 43 akeraiosleast=sdata3.toascii(); 44 akeraiosmost=sdata4.toascii(); 45 dekadikosleast=sdata5.toascii(); 46 dekadikosmost=sdata6.toascii(); 47 for(i=0;i<4;i++){ 48 if(i==0){ 49 port->write(akeraiosmost); 50 port->flush(); } 51 if(i==1){ 52 port->write(akeraiosleast); 53 port->flush(); } 54 if(i==2){ 55 port->write(dekadikosmost); 56 port->flush(); } 57 if(i==3){ 58 port->write(dekadikosleast); 59 port->flush(); } } 97

Με μια προσεκτικότερη ματιά στον παραπάνω κώδικα μπορεί κάποιος να διακρίνει στις πρώτες 13 γραμμές πως μέσω αφαίρεσης και μιας αριστερής ολίσθησης (γραμμή 27) χωρίζεται το ακέραιο από το δεκαδικό μέρος και τοποθετείται σε δύο διαφορετικές μεταβλητές. Έπειτα στις γραμμές 29 έως 38 χωρίζεται αντίστοιχα το ακέραιο και το δεκαδικό μέρος σε άλλα δύο κομμάτια μέσω αναθέσεων και δεξιών ολισθήσεων. Επειδή η QextSerialPort μπορεί να στείλει τα δεδομένα μόνο εφόσον είναι πίνακες τύπου QByteArray, μετατρέπονται οι υπάρχοντες πίνακες χαρακτήρων με μέγεθος ενός κελιού σε πίνακες τύπου QByteArray. Αυτό πραγματοποιείται στις γραμμές 39 έως 46. Τέλος, στις γραμμές 47 έως 59 στέλνονται με τη σειρά στην θύρα από τον υπολογιστή προς τον μικροελεγκτή ένα προς ένα τα byte με την εξής σειρά: πρώτα το περισσότερο σημαντικό byte του ακέραιου μέρους, μετά το λιγότερο σημαντικό byte του ακέραιου μέρους, μετά το περισσότερο σημαντικό byte του δεκαδικού μέρους και τέλος το λιγότερο σημαντικό byte του δεκαδικού μέρους. 5.2.5 Υλοποίηση της Επικοινωνίας του Συστήματος στον Μικροελεγκτή Οι παραπάνω υποπαράγραφοι αυτού και του προηγουμένου κεφαλαίου ήταν ένα καλό υπόβαθρο για την κατανόηση της υλοποίησης της επικοινωνίας του συστήματος που πραγματοποιήθηκε. Για περισσότερες λεπτομέρειες σχετικά με τον μικροελεγκτή ο αναγνώστης θα πρέπει να ανατρέξει στο εγχειρίδιο χρήσης του TC1798. Σε αυτή την υποπαράγραφο θα αναλυθούν οι 5 συναρτήσεις που υλοποιήθηκαν για να μπορέσει να πραγματοποιηθεί με επιτυχία η επικοινωνία του μικροελεγκτή με τον υπολογιστή. Αυτές οι συναρτήσεις ρυθμίζουν τον μικροελεγκτή ως προς την λήψη και την αποστολή δεδομένων. 5.2.5.1 Αρχικοποίηση της Σειριακής Επικοινωνίας Για να μπορέσει να γίνει χρήση της σειριακής επικοινωνίας στον μικροελεγκτή θα πρέπει αρχικά να γίνουν κάποιες ρυθμίσεις σε συγκεκριμένους καταχωρητές. Αυτές οι ρυθμίσεις επιτυγχάνονται μέσω της συνάρτησης ASC0_vInit(void) που φαίνεται παρακάτω: 98

1 void ASC0_vInit(void) 2 { 3 volatile unsigned int uwtemp; 4 MAIN_vResetENDINIT(); 5 ASC0_CLC = 0x00000100; 6 uwtemp = ASC0_CLC; 7 MAIN_vSetENDINIT(); 8 ASC0_BG = 0x0000001A; 9 ASC0_CON = 0x00000001; 10 ASC0_PISEL = 0x0000; 11 P5_IOCR0 = (P5_IOCR0 & ~0x000000F0) 0x00000020; 12 P5_IOCR0 = (P5_IOCR0 & ~0x0000F000) 0x0000D000; 13 ASC0_TSRC = 0x00001005; 14 ASC0_RSRC = 0x00001003; 15 ASC0_TBSRC_SETR = 1; 16 ASC0_CON_R = 1; 17 } Στις γραμμές 4 έως 7 του παραπάνω κώδικα αρχικοποίησης γίνεται η ρύθμιση της μονάδας ρολογιού. Πιο συγκεκριμένα, στη γραμμή 4 ενεργοποιείται η μονάδα ASC0 ενώ στη γραμμή 7 η μονάδα ASC0 σταματάει όταν ο μικροελεγκτής βρεθεί σε sleep mode. Φορτώνεται ο καταχωρητής ρολογιού στην γραμμή 5 με clock divider για κανονική λειτουργία. Στην γραμμή 8 ορίζεται το baud rate σε τιμή 115200. Με την τιμή που φορτώνεται ο καταχωρητής ASCO_CON ορίζεται επικοινωνία 8-bit μαζί με ένα stop bit. Στις επόμενες γραμμές γίνεται η επιλογή των pins και η ρύθμιση των διακοπών 99

για αποστολή και λήψη δεδομένων. Στην περίπτωση της λήψης αλλά και της αποστολής δεδομένων επιλέχθηκε ρύθμιση διακοπών CPU με την μόνη διαφορά πως η προτεραιότητα της λήψης δεδομένων είναι 3 (γραμμή 14) ενώ της αποστολής είναι 5 (γραμμή 13). Όσο μικρότερος είναι ο αριθμός προτεραιότητας στις διακοπές τόσο μεγαλύτερη προτεραιότητα έχει και η διακοπή. Έτσι, μεγαλύτερη προτεραιότητα παρατηρείται στην λήψη δεδομένων. Τέλος, στη γραμμή 16 ενεργοποιείται η γεννήτρια baud rate. 5.2.5.2 Συνάρτηση Αποστολής Δεδομένων Ο μικροελεγκτής στέλνει δεδομένα, που αντιλαμβάνεται από το σύστημα, στον υπολογιστή. Η αποστολή του πρώτου byte δεδομένων γίνεται μέσω της κύριας συνάρτησης, ενώ τα υπόλοιπα bytes στέλνονται μέσω της συνάρτησης ASC0_viTx(void). Αυτός ο τρόπος αποστολής των υπολοίπων bytes δεδομένων από την συνάρτηση ASC0_viTx(void) και όχι από την κύρια συνάρτηση έγινε για να μην απασχολείται η CPU όταν στέλνονται δεδομένα. 1 void INTERRUPT (ASC0_TINT) ASC0_viTx(void) 2 { 3 if (interrupt_counter<=print_counter){ 4 ASC0_TBSRC_CLRR = 1; 5 ASC0_TBUF=print[interrupt_counter]; 6 interrupt_counter++; 7 } 8 } 100

5.2.5.3 Συνάρτηση Λήψης Δεδομένων Η διαδικασία λήψης των δεδομένων στον μικροελεγκτή είναι παρόμοια με αυτήν της λήψης δεδομένων από τον υπολογιστή. Κάθε φορά που ένα byte δεδομένων έρχεται στο buffer της σειριακής πόρτας του μικροελεγκτή καλείται η συνάρτηση ASC0_viRx(void). Η βασική λογική της συνάρτησης είναι να βλέπει το χαρακτήρα του πρώτου byte που είναι και το αναγνωριστικό byte και ανάλογα να μεταβάλλει την αντίστοιχη μεταβλητή. Το πρωτόκολλο επικοινωνίας που ακολουθήθηκε για την λήψη καθώς και την αποστολή δεδομένων παρουσιάζεται λεπτομερώς σε παρακάτω παράγραφο. Η συνάρτηση φαίνεται εδώ: 1 void INTERRUPT (ASC0_RINT) ASC0_viRx(void) 2 { 3 ENABLE(); 4 receive_p[count_receive]=asc0_usgetdata(); 5 count_receive++; 6 if (count_receive==5){ 7 count_receive=0; 8 total_receive=receive_p[1]*256+(0.4*(receive_p[2]*2.5))+ receive_p[3]*0.003906+receive_p[4]*0.000015259; 9 switch (receive_p[0]){ 10 case 'p' : 11 kp=total_receive; 12 break; 13 case 'P': 14 total_receive=-total_receive; 15 kp=total_receive; 16 break; 17 case 'i': 101

18 ki=total_receive; 19 break; 20 case 'I': 21 total_receive=-total_receive; 22 ki=total_receive; 23 break; 24 case 'e': 25 speed_ref=total_receive; 26 break; 27 case 'E': 28 total_receive=total_receive; 29 speed_ref=total_receive; 30 break; 31 } 32 receive_p[0]=0; 33 receive_p[1]=0; 34 receive_p[2]=0; 35 receive_p[3]=0; 36 } 37 } 5.2.5.4 Δημιουργία Πινάκων των Bytes για Αποστολή Τα δεδομένα πρέπει να τοποθετηθούν σε πίνακες για να μπορέσει να γίνει η αποστολή τους. Αυτό γίνεται μέσω της συνάρτησης convert_out(float *reg, char *p). Σε αυτή τη συνάρτηση χωρίζονται τα 4 byte του float χαρακτήρα σε 4 byte ενός πίνακα χαρακτήρων. Η βασική συνάρτηση τρέχει τόσες φορές όσες και τα δεδομένα προς 102

αποστολή. Η μεταβλητή thetiko μεταβάλλει τον αναγνωριστικό χαρακτήρα που στέλνεται σαν πρώτο byte. Κεφαλαίο χαρακτήρα για αρνητικό αριθμό και πεζό για θετικό. Η συνάρτηση σαν είσοδο παίρνει τον pointer του πινάκα των δεδομένων προς αποστολή reg και τον πίνακα χαρακτήρων που δημιουργεί p. 1 # include "MAIN.h" 2 void convert_out(float *reg, char *p){ 3 unsigned int akaireo,count=0,decadiko=0,i; 4 unsigned inttemp_akaireos,temp_decadikos,thetiko; 5 unsigned char temp1,temp2; 6 float temp3,temp4; 7 count=0; 8 for (i=0; i<3 i++){ 9 if (reg[i]<0){ 10 temp4=-reg[i]; 11 thetiko=32; 12 } 13 else{ 14 temp4=reg[i]; 15 thetiko=0; 16 } 17 akaireo=temp4; 18 temp3=(temp4-akaireo)*65536; 19 if (i==0){ 20 print[count]='s'-thetiko; 21 count++; 22 } 103

23 if (i==1){ 24 print[count]='d'-thetiko; 25 count++; 26 } 27 if (i==2){ 28 print[count]='t'-thetiko; 29 count++; 30 } 31 temp1=akaireo; 32 temp_akaireos=(akaireo-temp1); 33 temp2=temp_akaireos>>8; 34 print[count]=temp2; 35 count++; 36 print[count]=temp1; 37 count++; 38 decadiko=temp3; 39 temp1=decadiko; 40 temp_decadikos=(decadiko-temp1); 41 temp2=temp_decadikos>>8; 42 print[count]=temp2; 43 count++; 44 print[count]=temp1; 45 } 46 print_counter=count; 47 } 104

5.2.5.5 Timer για την Διαδικασία Αποστολής Δεδομένων Για να μπορούν τα δεδομένα να στέλνονται με σταθερό ρυθμό και σε σταθερούς χρόνους πρέπει να οριστεί ένας timer. H παρακάτω συνάρτηση είναι ένας timer των 400Hz. Κάθε φορά που ενεργοποιείται ο χρονιστής ως βασική του λειτουργία έχει να ενεργοποιεί τις αντίστοιχες συναρτήσεις αποστολής των δεδομένων. Αρχικά δίνονται οι τιμές των μεταβλητών προς αποστολή στον πίνακα print_float και έπειτα καλείται η συνάρτηση μετατροπής αυτού του πίνακα σε έναν πίνακα χαρακτήρων αποστολής όπως έχει οριστεί. Έπειτα αποστέλλεται το πρώτο byte του πίνακα ώστε να καλεστεί η συνάρτηση αποστολής των δεδομένων αφού έχει τερματιστεί η αποστολή του πρώτου χαρακτήρα. Ο πηγαίος κώδικας φαίνεται παρακάτω: 1 void INTERRUPT (GPT120_T5INT) GPT120_viTmr5(void) 2 { 3 float ig_rms; 4 int temp2; 5 counter_timer=counter_timer+0.025; 6 if (counter_timer>10000) 7 counter_timer=0; 8 ENABLE(); 9 print_float[0]=speed; 10 print_float[1]=torque_ref; 11 print_float[2]=counter_timer; 12 print_float[4]=ia; 13 convert_out(print_float,print); 14 if (ASC0_TBSRC_SRR){ 15 ASC0_TBSRC_CLRR = 1; 16 interrupt_counter=0; 105

17 ASC0_TBUF=print[interrupt_counter]; 18 interrupt_counter=1; 19 } 20 } 5.3 Διαδικασία Ανάπτυξης των Διαγραμμάτων Η διαδικασία ανάπτυξης διαγραμμάτων ήταν ένα από τα σημαντικά κομμάτια της εφαρμογής που υλοποιήθηκε. Όπως αναφέρθηκε και στο δεύτερο κεφάλαιο πέρα των δυσκολιών που έχει η εγκατάσταση της Qwt βιβλιοθήκης, που περιέχει κλάσεις που σχετίζονται με την ανάπτυξη διαγραμμάτων, αξίζει να γίνει μία εκτενής ανάλυση για το πώς υλοποιούνται τα διαγράμματα καθώς και οι καμπύλες πάνω σε αυτά. Σε ένα περιβάλλον Qt που έχει εγκατεστημένη την βιβλιοθήκη Qwt θα πρέπει να κληθούν τα κατάλληλα αρχεία header για να γίνει σωστή χρήση των εργαλείων της βιβλιοθήκης. Στην εφαρμογή επιλέχθηκε η εισαγωγή μίας νέας κλάσης C++ με το όνομα Plot. Αυτή η εισαγωγή παράγει δύο συνδεδεμένα μεταξύ τους αρχεία plot.h και plot.cpp που θα είναι πλέον τοποθετημένα στους φακέλους του project με ονόματα header και source αντίστοιχα. Ο κώδικας που αναπτύχθηκε στο αρχείο plot.h έχει ως εξής: 1 #ifndef PLOT_H 2 #define PLOT_H 3 #include <qwt_plot.h> 4 class Plot: public QwtPlot 5 { 6 Q_OBJECT 7 public: 8 Plot(QWidget *parent=0); 9 }; 106

10 #endif // PLOT_H Η κλάση Plot αναπτύχθηκε ώστε να έχουν όλα τα αντικείμενα των διαγραμμάτων τα ίδια χαρακτηριστικά και να μην χρειάζεται να επαναλαμβάνονται οι δηλώσεις για κάθε διάγραμμα ξεχωριστά. Με αυτό τον τρόπο δημιουργείται κώδικας ο οποίος μπορεί να τρέξει με μεγαλύτερη ταχύτητα και να αναγνωστεί ευκολότερα. Στον παραπάνω κώδικα μέσω της γραμμής 4 συμπεριλαμβάνονται στη κλάση Plot όλες οι δημόσιες συναρτήσεις και μεταβλητές της κλάσης QwtPlot. Η κλάση QwtPlot είναι υπεύθυνη για την δημιουργία ενός δυσδιάστατου διαγράμματος. Πέραν της δημιουργίας αυτής, η κλάση QwtPlot περιέχει ορισμένες συναρτήσεις που μπορούν και αλλάζουν χαρακτηριστικά των διαγραμμάτων όπως για παράδειγμα τα ονόματα των αξόνων. Το αρχείο plot.cpp αποτελείται από τον εξής κώδικα: 1 #include "plot.h" 2 #include <qwt_scale_engine.h> 3 #include <qwt_plot_grid.h> 4 #include <qwt_symbol.h> 5 #include <QPen> 6 Plot::Plot(QWidget *parent ): 7 QwtPlot( parent ) 8 { 9 setaxisautoscale(qwtplot::yleft,true); 10 setaxisautoscale(qwtplot::xbottom,true); 11 setcanvasbackground(qcolor(qt::darkblue)); 12 QwtPlotGrid *grid = new QwtPlotGrid; 13 grid->enablexmin( true ); 14 grid->setmajpen( QPen( Qt::white, 0, Qt::DotLine ) ); 15 grid->setminpen( QPen( Qt::gray, 0, Qt::DotLine ) ); 16 grid->attach( this ); 17 } 107

Ο παραπάνω κώδικας στη πρώτη γραμμή περιλαμβάνει το αρχείο plot.h οπότε μέσω αυτού περιλαμβάνεται και το αρχείο qwt_plot.h. Στις γραμμές δύο έως τέσσερα συμπεριλαμβάνονται αρχεία header που είναι υπεύθυνα για τη ρύθμιση της κλίμακας των αξόνων, το σχεδιασμό κάποιων συμβόλων και το σχεδιασμό γραμμών. Στις γραμμές 9 και 10 ορίζεται πως όποιο αντικείμενο της κλάσης Plot δημιουργηθεί θα έχει αυτόματη ενημέρωση στο εύρος των τιμών που θα έχουν οι άξονες χ και ψ. Με αυτό τον τρόπο ο χρήστης της εφαρμογής μπορεί να βλέπει όλες τις μεταβολές της καμπύλης που είναι πάνω στο διάγραμμα χωρίς να χάνει κάποιο κομμάτι της. Για καλύτερο έλεγχο των μεταβολών τις καμπύλης έχει προστεθεί πάνω στο εκάστοτε διάγραμμα πλέγμα. Αυτό το πλέγμα που υλοποιείται στις γραμμές 12 έως 16 έχει λευκό και γκρι χρώμα και διευκολύνει την εύρεση τιμών πάνω στην καμπύλη. Η συνάρτηση setcanvasbackground() ορίζει το χρώμα που θα έχει το περιβάλλον του εκάστοτε διαγράμματος. Για να μπορέσει να χρησιμοποιηθεί η παραπάνω κλάση μέσα στο MainWindow θα πρέπει να γίνει μία δήλωση αυτής της κλάσης στο αρχείο mainwindow.h. Αυτό πραγματοποιείται εισάγοντας την παρακάτω γραμμή κώδικα κάτω από τις δηλώσεις των αρχείων header: class Plot; Η δημιουργία και η απεικόνιση των διαγραμμάτων και των καμπυλών θα γίνει μέσω ενός παραδείγματος. Παρακάτω εξηγείται το πώς δημιουργήθηκε το διάγραμμα Speed-Time που φαίνεται στην Εικόνα 45. 1 plot_1=new Plot(this); 2 plot_1->setaxistitle(qwtplot::xbottom, "<font size='2' color='darkblue' face='arial'>time(s)</font>"); 3 plot_1->setaxistitle(qwtplot::yleft, "<font size='2' color='darkblue' face='arial'>speed</font>"); 4 curve_1=new QwtPlotCurve(); 5 curve_1->attach(plot_1); 6 curve_1->setpen(qpen(qt::yellow)); 108

Τα αντικείμενα plot_1 και curve_1 είναι καθολικά και δηλώνονται αρχικά στο αρχείο mainwindow.h. Το plot_1 είναι αντικείμενο της κλάσης Plot ενώ το αντικείμενο curve_1 είναι αντικείμενο της κλάσης QwtPlotCurve και σχετίζεται με τη δημιουργία και την επεξεργασία της καμπύλης. Στη γραμμή 1 υπάρχει το όρισμα this μέσα στον constructor. Το όρισμα αυτό καθορίζει πως το διάγραμμα θα απεικονιστεί στο βασικό παράθυρο. Στις γραμμές 2 και 3 ορίζονται τα ονόματα των αξόνων σύμφωνα με αυτό που χρειάζεται να απεικονιστεί. Η συνάρτηση attach() της γραμμής 5 τοποθετεί την καμπύλη curve_1 πάνω στο διάγραμμα plot_1 και με αυτόν τον τρόπο συνδέονται τα δύο αντικείμενα. Η καμπύλη στην εφαρμογή που δημιουργήθηκε δεν πρέπει να είναι στατική πρέπει να ανανεώνεται σύμφωνα με τα δεδομένα που αντλεί ο υπολογιστής από την σειριακή θύρα. Για να επιτευχθεί αυτό δημιουργήθηκε ένας χρονοδιακόπτης των 500ms όπως φαίνεται παρακάτω: 1 timer=new QTimer(this); 2 connect(timer,signal(timeout()),this,slot(renewal())); 3 timer->start(500); Αυτός ο χρονοδιακόπτης συνδέεται με την συνάρτηση slot renewal() μέσω του μηχανισμού signal and slot. Με την πάροδο 500ms καλείται η συνάρτηση renewal() ώστε να εκτελεστεί ο κώδικας της. Έπειτα μηδενίζεται ξανά ο χρονοδιακόπτης και μετράει ξανά μέχρι τα 500ms για να πραγματοποιήσει την ίδια εργασία. Αυτό πραγματοποιείται για όσο χρονικό διάστημα η εφαρμογή είναι ανοιχτή. Μέσα στην συνάρτηση slot renewal() το κομμάτι του κώδικα που έχει να κάνει με την ανανέωση της καμπύλης του διαγράμματος Speed-Time παρουσιάζεται παρακάτω: 1 void MainWindow::renewal(){ 2 curve_1->setsamples(time,speed,500); 3 plot_1->replot(); 4 } 109

Η συνάρτηση setsamples() ορίζει ποιοι πίνακες θα είναι αυτοί που θα απεικονιστούν πάνω στους άξονες χ και ψ των διαγραμμάτων. Έτσι, στη γραμμή κώδικα 2 ορίστηκε στον άξονα των χ το time, στον άξονα των ψ το Speed και το τελευταίο όρισμα ορίζει πως θα απεικονιστούν τα 500 πρώτα κελιά των πινάκων time και Speed. Από την άλλη, η συνάρτηση replot() είναι αυτή που είναι υπεύθυνη για την ανανέωση του διαγράμματος κάνοντας το να τρέχει σε χρόνο πολύ κοντά στον πραγματικό. Εκτός από την δημιουργία και την ρύθμιση των διαγραμμάτων και των καμπυλών υλοποιήθηκε και ένας επιπλέον μηχανισμός, ο μηχανισμός zoom. Με αυτό το μηχανισμό ο χρήστης μπορεί να στοχεύει σε ένα συγκεκριμένο κομμάτι της καμπύλης ενός διαγράμματος ή σε ένα συγκεκριμένο εύρος τιμών μόνο με την χρήση του ποντικιού του. Προς αυτό το σκοπό υλοποιήθηκε η κλάση Zoomer καθώς και η συνάρτηση zoom(). 1 class Zoomer: public QwtPlotZoomer 2 { 3 public: 4 Zoomer(int xaxis, int yaxis, QwtPlotCanvas *canvas): 5 QwtPlotZoomer(xAxis,yAxis, canvas) 6 { 7 settrackermode(qwtpicker::alwaysoff); 8 setrubberband(qwtpicker::norubberband); 9 setmousepattern(qwteventpattern::mouseselect2, 10 Qt::RightButton, Qt::ControlModifier); 11 setmousepattern(qwteventpattern::mouseselect3, 12 Qt::RightButton); 13 } 14 }; Η κλάση Zoomer περιέχει τις δημόσιες μεταβλητές και συναρτήσεις της κλάσης QwtPlotZoomer. Η κλάση QwtPlotZoomer παρέχει στον χρήστη την δυνατότητα ζουμ σε αντικείμενα της κλάσης QwtPlot. Έτσι, στον constructor της κλάσης Zoomer 110

προστέθηκαν ορίσματα τα οποία ρυθμίζουν την διαδικασία του ζουμ, ορίζουν δηλαδή σε ποιο αντικείμενο τύπου Plot θα γίνει το ζουμ και σε ποιους άξονες του. Σύμφωνα με την κλάση Zoomer, για να μεγεθύνει ή αλλιώς να εστιάσει ο χρήστης σε ένα κομμάτι της καμπύλης θα πρέπει να πραγματοποιήσει αριστερό κλικ. Κρατώντας το αριστερό κλικ πατημένο ο χρήστης πραγματοποιεί ένα παραλληλόγραμμο που εντός του θα πρέπει να περιέχεται το κομμάτι της καμπύλης που επιθυμεί να μεγεθύνει. Από την άλλη, για να γίνει σμίκρυνση πραγματοποιείται απλά ένα δεξί κλικ. Παρακάτω φαίνεται το κομμάτι του κώδικα της συνάρτησης zoom() που αφορά το ζουμ του διαγράμματος Speed-Time: 1 void MainWindow::zoom(){ 2 zoomer_plot_1[0] = new Zoomer( 0,QwtPlot::yLeft,plot_1->canvas()); 3 zoomer_plot_1[0]->setrubberband(qwtpicker::rectrubberband); 4 zoomer_plot_1[0]->setrubberbandpen(qcolor(qt::green)); 5 zoomer_plot_1[0]->settrackermode(qwtpicker::activeonly); 6 zoomer_plot_1[0]->settrackerpen(qcolor(qt::white)); 7 } Η συνάρτηση zoom() καλείται στο MainWindow. Στην γραμμή 2 που υλοποιείται ο constructor δεν γίνεται ζουμ στον άξονα των χ παρά μόνο στον άξονα των ψ. Στην συνάρτηση το παραλληλόγραμμο που ορίστηκε προηγουμένως για την εστίαση της περιοχής λειτουργίας παίρνει πράσινο χρώμα ύστερα από την συνάρτηση της γραμμής 4. Εκτός από το ζουμ η συνάρτηση προσφέρει στον χρήστη την δυνατότητα να βλέπει με το που πηγαίνει τον κέρσορα πάνω στην καμπύλη τις τιμές των χ και ψ σε εκείνο το σημείο. Αυτές οι τιμές παρουσιάζονται με λευκό χρώμα ύστερα από την εισαγωγή της γραμμής 6. Ενδεικτικά στην παρακάτω εικόνα φαίνεται η υλοποίηση του διαγράμματος Speed-Time. 111

Εικόνα 49: Διάγραμμα Speed-Time 5.4 Ανανέωση Γεωμετρίας του Βασικού Παραθύρου Στην προηγούμενη παράγραφο αναφέρθηκε πως υπάρχει μία συνάρτηση, η renewal(), που είναι υπεύθυνη για την ανανέωση των καμπυλών των διαγραμμάτων. Εκτός όμως από αυτή τη λειτουργία η συνάρτηση πραγματοποιεί και άλλες εργασίες. Όλα τα widget που είναι τοποθετημένα στο βασικό παράθυρο της εφαρμογής δεν είναι στατικά. Έχει αναπτυχθεί κώδικας που κάνει τα widget να προσαρμόζονται στις θέσεις που έχουν προκαθοριστεί ανάλογα με το μέγεθος του κεντρικού παραθύρου. Αυτός ο κώδικας είναι τοποθετημένος εσωτερικά της συνάρτησης renewal() και έχει ως εξής: 1 QRect rect = this->geometry(); 2 int platos,ipsos; 3 platos=rect.width(); 4 ipsos=rect.height(); Η κλάση QRect ορίζει ένα ορθογώνιο παραλληλόγραμμο με ακρίβεια ακεραίου. Έτσι με την γραμμή 1 ορίζεται ένα αντικείμενο αυτής της κλάσης που έχει σαν χαρακτηριστικά την εκάστοτε γεωμετρία του βασικού παραθύρου. Αυτό το 112

παραλληλόγραμμο δεν είναι ορατό στον χρήστη. Στη γραμμή 3 και στη γραμμή 4 του παραπάνω κώδικα τοποθετείται το μέτρο του πλάτους και του μήκους σε δύο τοπικές μεταβλητές. Αυτές οι μεταβλητές χρησιμοποιούνται σαν ορίσματα σε νέα αντικείμενα της κλάσης QRect και χρησιμοποιούνται στην γεωμετρική τοποθέτηση των widget όπως φαίνεται στον παρακάτω κώδικα. 5 QRect rect_1(2*platos/3,ipsos/25,9*platos/30,9*ipsos/30); 6 QRect rect_2(2*platos/3,2*ipsos/3,9*platos/30,9*ipsos/30); 7 QRect rect_3(0.05*platos,0.3*ipsos,platos/11,ipsos/11); 8 plot_1->setgeometry(rect_1); 9 plot_2->setgeometry(rect_2); 10 wind_speed->setgeometry(rect_3); Ο constructor QRect::QRect ( int x, int y, int width, int height ) έχει τέσσερα ορίσματα. Τα πρώτα δύο σημεία θέτουν το σημείο που ταυτίζεται με το πάνω αριστερά άκρο του ορθογωνίου παραλληλογράμμου ενώ τα άλλα δύο ορίσματα ορίζουν το πλάτος και το ύψος που θα εκταθεί το παραλληλόγραμμο. Έτσι, στον παραπάνω κώδικα παρατηρείται στις γραμμές 5 έως 7 της κλάσης QRect πως οι constructor των αντικειμένων περιέχουν σαν ορίσματα υποπολλαπλάσια των μεταβλητών platos και ipsos. Στις γραμμές 8 έως 10 ορίζονται σαν γεωμετρίες των widget τα ορθογώνια παραλληλόγραμμα των αντικειμένων QRect. Λόγω του ότι η συνάρτηση renewal() καλείται κάθε 500ms, οι μεταβλητές platos και ipsos ανανεώνονται συνεχώς με τις νέες τιμές των μεγεθών του παραλληλογράμμου που έχει σαν γεωμετρία την γεωμετρία του βασικού παραθύρου. Τοποθετώντας τις μεταβλητές αυτές μέσα στις γεωμετρίες των widget κάνει τα widget να μεγαλώνουν και να μικραίνουν ανάλογα με τις μεταβολές του βασικού παραθύρου. 113

5.5 Απεικόνιση Δεδομένων σε Οθόνες LCD Ο σχεδιασμός της εφαρμογής απαιτούσε να υπάρχουν ορισμένα πλαίσια μέσα στα οποία θα απεικονίζονται οι τιμές που θα έπαιρνε ο υπολογιστής από τον μικροελεγκτή. Αυτά τα πλαίσια απεικόνισης δεν θα έπρεπε να είναι στατικά αλλά θα έπρεπε να μεταβάλλονται συνεχώς δυναμικά σε σχέση με τα εισερχόμενα δεδομένα. Στόχος ήταν να μπορεί ο χρήστης του συστήματος να έχει μία συνεχή ενημέρωση για το πως συμπεριφέρεται το σύστημα κάθε χρονική στιγμή είτε αν συνέβαινε κάποια αλλαγή στα χαρακτηριστικά του είτε όχι. Οι τιμές απεικόνισης (π.χ. ταχύτητα ανέμου) είναι δεκαδικοί αριθμοί όποτε θα έπρεπε να βρεθεί το κατάλληλο widget που θα μπορεί να υποστηρίξει την απεικόνιση τέτοιων αριθμών. Η κλάση που χρησιμοποιήθηκε είναι η QLCDNumber. Δημιουργήθηκαν έντεκα αντικείμενα της κλάσης ούτως ώστε να απεικονιστούν τα έντεκα αντίστοιχα widget LCD, όπως φαίνονται στην Εικόνα 45. Η σύνδεση των τιμών με τα αντικείμενα της κλάσης QLCDNumber γίνεται στην συνάρτηση slot renewal(). Οι τιμές δεν συνδέονται απευθείας με τα αντικείμενα της κλάσης ως έχουν, διότι η ταχύτητα με την οποία έρχονται τα δεδομένα είναι τόσο μεγάλη που η απευθείας σύνδεση δεν επιτρέπει στο ανθρώπινο μάτι να προλάβει τις αλλαγές που προκαλούνται. Έτσι, από τη στιγμή που οι τιμές συνδέθηκαν με τα αντικείμενα στην συνάρτηση slot renewal() κάθε 500ms θα ανανεώνονται οι τιμές των LCD. Για την ακόμα ομαλότερη αλλαγή των τιμών του LCD, η τιμή που απεικονίζεται υπολογίζεται από τον μέσο όρο των τελευταίων 500 τιμών που έφτασαν στη σειριακή θύρα του υπολογιστή. Ενδεικτικό κομμάτι του πηγαίου κώδικα μέσα στην συνάρτηση slot renewal() για την σύνδεση των τιμών με τα πλαίσια LCD φαίνεται παρακάτω: 1 double Igenerator_temp=0,wind_speed_temp=0,turbine_torque_temp=0 2 int i; 3 for(i=0;i<500;i++){ 4 Igenerator_temp+=Igenerator_array[i]; 5 wind_speed_temp+=wind_speed_array[i]; 6 } 7 Igenerator_temp=Igenerator_temp/500; 114

8 Igenerator_average=Igenerator_temp; 9 generator_current->display(igenerator_average); 10 wind_speed_temp=wind_speed_temp/500; 11 wind_speed_average=wind_speed_temp; 12 wind_speed->display(wind_speed_average); Στις γραμμές από 3 έως 6 τοποθετούνται σε μεταβλητές τα αθροίσματα των πινάκων για το ρεύμα της γεννήτριας και για την ταχύτητα του ανέμου, ώστε να χρησιμοποιηθούν μετά για τον υπολογισμό του μέσου όρου που αναφέρθηκε προηγουμένως. Ο υπολογισμός του κάθε μέσου όρου ξεχωριστά γίνεται στις γραμμές 7 και 10. Τέλος, η συνάρτηση display() είναι υπεύθυνη για την απεικόνιση των τιμών στα πλαίσια LCD και εκτελείται στις γραμμές 9 και 12. 5.6 Λειτουργία Πλήκτρων Απεικόνισης Διαγραμμάτων Σε αυτή τη παράγραφο θα εξηγηθεί ο τρόπος με τον οποίο υλοποιήθηκαν τα πλήκτρα απεικόνισης διαγραμμάτων. Δίπλα από κάθε πλαίσιο LCD υπάρχει και ένα πλήκτρο που όταν πατηθεί εμφανίζεται ένα επιπλέον παράθυρο με το διάγραμμα της τιμής που απεικονίζει το LCD συναρτήσει του χρόνου. Το διάγραμμα απεικονίζει την πραγματική τιμή και όχι το μέσο όρο συναρτήσει του χρόνου. Αρχικά, γίνεται η δήλωση των πλήκτρων και δημιουργούνται τα νέα αντικείμενα ενώ επίσης πραγματοποιείται η σύνδεση αυτών των πλήκτρων με τις αντίστοιχες συναρτήσεις για απεικόνιση των διαγραμμάτων σε νέα παράθυρα. Ενδεικτικά, παρουσιάζεται ο πηγαίος κώδικας της συνάρτησης slot απεικόνισης του διαγράμματος Wind Speed Time: 1 void MainWindow::wind_speed_function(){ 2 QVBoxLayout *layout=new QVBoxLayout(); 3 layout->addwidget(wind_speed_plot); 4 QWidget *window=new QWidget(); 5 window->setwindowtitle("s-t"); 6 window->setlayout(layout); 115

7 window->show(); 8 } Για να μπορεί να απεικονιστεί το widget σε ένα νέο παράθυρο, δημιουργήθηκε ένα νέο layout που περιλαμβάνει το μοναδικό widget wind_speed_plot. Αυτό το layout ορίζεται σαν βασικό layout του widget με όνομα window. Με τη χρήση της συνάρτησης show() γίνεται το widget με όνομα window ορατό στον χρήστη σε ένα νέο παράθυρο όπως φαίνεται στην παρακάτω Εικόνα 50. Η υλοποίηση των διαγραμμάτων είναι παρόμοια με αυτή που περιγράφηκε σε παραπάνω παράγραφο και θα ήταν περιττό να αναφερθεί ξανά. Εικόνα 50:Διάγραμμα Turbine Torque-Time 116

5.7 Διαδικασία Καθορισμού των Κερδών Στην τελευταία παράγραφο αυτού του κεφαλαίου θα γίνει αναφορά για το πώς δημιουργήθηκε η διαδικασία καθορισμού των κερδών. Σκοπός της προσομοίωσης είναι να επιτρέπει στον χρήστη να ρυθμίζει τα κέρδη του συστήματος σε τιμές που επιθυμεί. Κάθε φορά που εκκινεί η εφαρμογή που δημιουργήθηκε, ξεκινάει και η διαδικασία της προσομοίωσης. Στην διαδικασία αυτή αλλάζει ανά δύο δευτερόλεπτα τιμή η μεταβλητή speed_ref του Rectifier και παίρνει εναλλάξ τις τιμές 300 και 700. Το κατάλληλο αντικείμενο της κλάσης QTimer δημιουργήθηκε για να λειτουργεί σαν ένας χρονοδιακόπτης των 500ms και συνδέθηκε αντίστοιχα με μία συνάρτηση slot την simulation_function(). Η συνάρτηση simulation_function() περιέχει έναν ακέραιο μετρητή ο οποίος αρχικά έχει μηδενική τιμή και αυξάνεται κατά μία μονάδα κάθε φορά που ο χρονοδιακόπτης καλεί την συνάρτηση. Μέσα στην συνάρτηση έχε οριστεί πως κάθε φορά που ο μετρητής παίρνει την τιμή 3 τότε στέλνεται στον μικροελεγκτή μέσω της σειριακής επικοινωνίας η τιμή 300 στην θέση του speed_ref σύμφωνα με το πρωτόκολλο επικοινωνίας. Από την άλλη, κάθε φορά που ο μετρητής παίρνει την τιμή 7 τότε στέλνεται στον μικροελεγκτή μέσω της σειριακής επικοινωνίας η τιμή 700 στην θέση του speed_ref και πάλι σύμφωνα με το πρωτόκολλο επικοινωνίας. Με το που φτάνει ο μετρητής στην τιμή 7 μηδενίζεται και η διαδικασία ξεκινά πάλι από την αρχή. Για να μπορέσει να γίνει παύση της διαδικασίας προσομοίωσης και να συνεχιστεί η λειτουργία του προγράμματος σε πλαίσια κανονικής λειτουργίας έχει πραγματοποιηθεί ένα πλήκτρο με όνομα sim_off. Αυτό το πλήκτρο συνδέθηκε με την συνάρτηση slot simulation_off_function() η οποία υλοποιεί την οριστική αποσύνδεση του χρονοδιακόπτη από το σύστημα. 1 void MainWindow::simulation_off_function(){ 2 timer_1->disconnect(); 3 } 117

Μετά την αποσύνδεση του χρονοδιακόπτη που σχετίζεται με την προσομοίωση, για να επανεκκινήσει η διαδικασία προσομοίωσης θα πρέπει να επανεκκινήσει και το πρόγραμμα. Η εναλλαγή από τα 300 στα 700 στο υλοποιημένο πρόγραμμα φαίνεται γραφικά στην εικόνα 51. Εικόνα 51: Εναλλαγή του sped_ref από 300 σε 700. 118