//microdev.gr //Παναγιώτης Παπάζογλου //Ιανουάριος 2023 //Ενσωμάτωση βιβλιοθήκης για τη σειριακή επικοινωνία import processing.serial.*; Serial myPort; //Δήλωση αντικειμένου img για το χειρισμό/φόρτωση της εικόνας PImage img; //Αρχικοποίηση κατάστασης διακόπτη int button=0; //Αρχικές τιμές χρωμάτων μίξης (χρώματα στους κύκλους) int red=255, green=255, blue=255; //Αρχικές τιμές για τη μίξη των χρωμάτων στο φόντο int bred=0, bgreen=0, bblue=0; //Αρχικοποίηση τιμής για τον αισθητήρα απόστασης //Ώστε να εμφανίζεται αρχικά το microdev.gr int dist=100; //Αρχικές συντεταγμένες για την τοποθέτηση των στοιχείων στην οθόνη //Όλη η σχεδίαση γίνεται βάσει αυτών των τιμών //Η αλλαγή τους, προσαρμόζει αυτόματα τη σχεδίαση //xinit=θέση Χ, y=θέση Υ, d=ύψος κύκλων int xinit=200; int y=200; int d=150; //Μεταβλητές που θα φιλοξενούν αυτά που διαβάζονται από τη σειριακή θύρα //a=Ποτενσιόμετρο RED, χρώμα στο προσκήνιο (πρώτος κύκλος) //b=Ποτενσιόμετρο GREEN, χρώμα στο προσκήνιο (δεύτερος κύκλος) //c=Ποτενσιόμετρο BLUE, χρώμα στο προσκήνιο (τρίτος κύκλος) //s1=Ποτενσιόμετρο RED, χρώμα στο φόντο //s2=Ποτενσιόμετρο GREEN, χρώμα στο φόντο //s3=Ποτενσιόμετρο BLUE, χρώμα στο φόντο int a=0,b=0,c=0,s1=0,s2=0,s3=0; //Συνάρτηση αρχικοποίησης void setup() { //Μέγεθος παραθύρου εφαρμογής size(1000, 1000); //Φόρτωση εικόνας (από τον κατάλογο που είναι αποθηκευμένη η εφαρμογή) img=loadImage("ti.jpg"); //Εμφάνιση τίτλου παραθύρου surface.setTitle("Color Mixer - microdev.gr"); //Δήλωση αντικειμένου myPort για διάβασμα από τη σειριακή θύρα //Προσοχη: το COM8 είναι η θύρα που χρησιμοποιήθηκε στο παράδειγμα //Στο δικό σας σύστημα, μπορεί να είναι άλλη (όπου έχουν βρει το Arduino τα Windows) //Το 9600 θα πρέπει να συμφωνεί με την αντίστοιχη ταχύτητα που έχετε δηλώσει //στον κώδικα του Arduino myPort = new Serial(this, "COM8", 9600); } //Συνάρτηση που εκτελείται συνεχώς void draw() { //Διάβασμα από τη σειριακή θύρα (ένα αλφαριθμητικό που τερματίζεται με αλλαγή γραμμής) //Στο Arduino το τελευταίο print είναι println String inString=myPort.readStringUntil('\n'); //Αν έχουν ληφθεί δεδομένα (τιμή null αν δεν έχει ληφθεί τίποτα) if (inString!=null) { //Δημιουργία πίνακα αλφαριθμητικών βάσει του χαρακτήρα διαχωρισμού "." //Τα δεδομένα στέλνονται στη μορφή 123.211.0, κλπ //Με το διαχωρισμό θα ισχύει ότι num[0]="123", num[1]="211", κ.ο.κ. String[] num=splitTokens(inString,"."); //Κατά την πρώτη λήψη, πολλές φορές το πρώτο αλφαριθμητικό περιέχει και σπουπίδια, //Δηλαδή ανεπιθύμητους χαρακτήρες. Πρακτικά, ο πρώτος χαρακτήρας είναι μη αποδεκτός, //δηλαδή, δεν είναι στο διάστημα ['0','9']. //Διαβάζουμε μόνο τον πρώτο χαρακτήρα και αν είναι εκτός διαστήματος, τότε //εκχωρούμε στο a την τιμή 0, διαφορετικά την μετατρέπουμε κανονικά σε ακέραιο //Έτσι, δεν προκύπτει ποτέ σφάλμα στην εκκίνηση της σειριακής επικοινωνίας char ic=' ', ic2=' '; ic=num[0].charAt(0); if (num[0].length()>1) ic2=num[0].charAt(1); if ((ic<'0') || (ic>'9') || (ic2<'0') || (ic2>'9')) a=0; else //RED F a=Integer.parseInt(num[0]); //Μετατροπή και των υπόλοιπων χαρακτήρων που λαμβάνονται σε ακέραιες τιμές //GREEN F b=Integer.parseInt(num[1]); //BLUE F c=Integer.parseInt(num[2]); //RED B s1=Integer.parseInt(num[3]); //GREEN B s2=Integer.parseInt(num[4]); //BLUE B s3=Integer.parseInt(num[5]); //Κατάσταση κουμπιού-διακόπτη button=Integer.parseInt(num[6]); //Μέτρηση αισθητήρα απόστασης dist=Integer.parseInt(num[7].trim()); //Αν ο διακόπτης είναι ενεργοποιημένος, τότε οι τιμές όλων των //χρωμάτων, προκύπτουν από το ποτενσιόμετρα if (button==1) { //Μίξη χρωμάτων στο προσκήνιο (κύκλοι) από τα ποτενσιόμετρα red=a; green=b; blue=c; //Μίξη χρωμάτων στο φόντο από τα ποτενσιόμετρα bred=s1; bgreen=s2; bblue=s3; } else { //Χωρίς ποτενσιόμετρα, το φόντο παραμένει μαύρο bred=0; bgreen=0; bblue=0; } //Εμφάνιση βοηθητικών μηνυμάτων στην κονσόλα για να ξέρουμε //τι λαμβάνουμε από το Arduino. Μπορείτε να τα βγάλετε αν θέλετε print("p1=",a,", "); print("p2=",b,", "); print("p3=",c,", "); println("button=",button); print("s1=",s1,", "); print("s2=",s2,", "); print("s3=",s3,", "); println("dist=",dist); println("----------------------------"); } //Καθορισμός χρώματος φόντου //Θυμηθείτε ότι, κάθε φορά που εκτελείται η εντολή background //διαγράφεται όλο το περιεχόμενο του παραθύρου της εφαρμογής //Αυτό, επιτρέπει την ανανέωση του περιεχομένου με την εκτέλεση //των εντολών που ακολουθούν background(bred,bgreen,bblue); //Κάθε στοιχείο σχεδιάζεται στη θέση x, η οποία είναι πολλαπλάσιο της //αρχικής τιμής xinit int x=xinit; //Βοηθητικές μεταβλητές για καθορισμό ορισμένων αποστάσεων κατά τη σχεδίαση //χρησιμοποιούνται πάντα μεταβλητές, ώστε η σχεδίαση να προσαρμόζεται εύκολα //αν αλλάξει για παράδειγμα το μέγεθος του παραθύρου της εφαρμογής int dx=45, dy=30; //Μέγεθος γραμματοσειράς για τα μηνύματα που ακολουθούν int ts=70; //Η εμφάνιση των ακόλουθων μηνυμάτων στο παράθυρο της εφαρμογής, //γίνεται βάσει της απόστασης που μετρά ο αισθητήρας. //Τοποθετώντας για παράδειγμα το χέρι μας σε διάφορες αποστάσεις, //αλλάζει το μήνυμα που εμφανίζεται. Επιπλέον, το χρώμα των χαρακτήρων //είναι αυτό που προκύπτει κάθε φορά από τη μίξη των χρωμάτων στο προσκήνιο //Το dist αντιπροσωπεύει απόσταση και είναι σε cm //Εμφάνιση του W e l c o m e if ((dist>=3) && (dist<6)) { //Χρώμα όπως και η μίξη fill(red,green,blue); //Καθορισμός μεγέθους γραμματοσειράς textSize(ts); //Εμφάνιση κειμένου text("Welcome",xinit,dy+y+2*d); //Εμφάνιση του κειμένου και στην κονσόλα (για λόγους ελέγχου λειτουργίας) println("Welcome"); } //Εμφάνιση του D i g i t a l A r t s if ((dist>=6) && (dist<9)) { fill(red,green,blue);textSize(ts); text("Digital Arts",xinit,dy+y+2*d); println("Digital Arts"); } //Εμφάνιση του C i n e m a if ((dist>=9) && (dist<12)) { fill(red,green,blue);textSize(ts); text("Cinema",xinit,dy+y+2*d); println("Cinema"); } //Εμφάνιση του M i c r o d e v . g r if (dist>=12) { fill(red,green,blue);textSize(ts); text("Microdev.gr",xinit,dy+y+2*d); println("Microdev.gr"); } //Εμφάνιση της εικόνας image(img, (width/2)-300, y-50+3*d); //Βοηθητική μεταβλητή για συνένωση αλφαριθμητικών String msg=""; //Αν το κουμπί-διακόπτης είναι ενεργός, θα πρέπει να εμφανιστεί σχετικό μήνυμα //ότι ο έλεγχος γίνεται από τα ποτενσιόμετρα //Επίσης, θα εμφανίζονται και δύο πλαίσια πάνω στην εικόνα για να καταλάβει //ο χρήστης τον έλεγχο από τα ποτενσιόμετρα if (button==1) { //Εμφάνιση μηνύματος ότι, ο έλεγχος γίνεται από τα ποτενσιόμετρα textSize(20); fill(red,green,blue); text("Control=POT",(width/2)+150,height-10); //Εμφάνιση πλαισίων πάνω στην εικόνα noFill(); stroke(255,255,0);strokeWeight(16); rect((width/2)-300,y+3*d,250,80); rect((width/2)-200,108+y+3*d,150,80); noStroke();strokeWeight(1); } //Διαφορετικά (ο διακόπτης δεν έχει ενεργοποιηθεί), απλά εμφανίζεται //το μήνυμα ότι ο έλεγχος γίνεται από το ποντίκι //Σημείωση: ο έλεγχος του φόντου γίνεται μόνο από τα ποττενσιόμετρα, //εφόσον επιλεγούν μέσω του διακόπτη else { textSize(20); fill(red,green,blue); text("Control=MOUSE",(width/2)+150,height-10); } //Εμφάνιση του τίτλου της εφαρμογής με χρώμα από τη μίξη στο προσκήνιο //πάνω δεξιά του παραθύρου fill(red,green,blue);textSize(30); text("COLOR MIXER V1.0",width-240,50); //*********************************************************************************** //Σχεδίαση του πρώτου κύκλου, αποκλειστικά με την ένταση του κόκκινου χρώματος (RED) //*********************************************************************************** fill(red,0,0); noStroke(); circle(x,y,d); //Σχεδίαση κουμπιών χειρισμού έντασης με το ποντίκι (0-255) draw_buttons(x,y,d); //Εμφάνιση τιμής έντασης κόκκινου (RED) για το προσκήνιο αλλά και το φόντο msg="red="+str(red); text(msg,x-dx,y-d+35); msg="Bred="+str(bred); dy=dy+30; text(msg,x-dx,y+d+dy); //*************************************************************************************** //Σχεδίαση του δεύτερου κύκλου, αποκλειστικά με την ένταση του πράσινου χρώματος (GREEN) //*************************************************************************************** x=2*xinit; fill(0,green,0); noStroke(); circle(x,y,d); //Σχεδίαση κουμπιών χειρισμού έντασης με το ποντίκι (0-255) draw_buttons(x,y,d); //Εμφάνιση τιμής έντασης πράσινου (GREEN) για το προσκήνιο αλλά και το φόντο msg="green="+str(green); text(msg,x-dx,y-d+35); msg="Bgreen="+str(bgreen); text(msg,x-dx,y+d+dy); //******************************************************************************** //Σχεδίαση του τρίτου κύκλου, αποκλειστικά με την ένταση του μπλε χρώματος (BLUE) //******************************************************************************** x=3*xinit; fill(0,0,blue); noStroke(); circle(x,y,d); //Σχεδίαση κουμπιών χειρισμού έντασης με το ποντίκι (0-255) draw_buttons(x,y,d); //Εμφάνιση τιμής έντασης μπλε (BLUE) για το προσκήνιο αλλά και το φόντο msg="blue="+str(blue); text(msg,x-dx,y-d+35); msg="Bblue="+str(bblue); text(msg,x-dx,y+d+dy); //************************************************************* //Σχεδίαση του τέταρτου κύκλου, την μίξη των παραπάνω χρωμάτων //************************************************************* x=4*xinit; fill(red, green, blue); noStroke(); circle(x,200,d); } //************************************************************* //Κλήση συνάρτησης σχεδίασης κουμπιών κάτω από κάθε κύκλο //Μέσω των παραμέτρων x,y,d καθορίζεται η πάνω αριστερή γωνία //από την οποία θα ξεκινήσει η σχεδίαση //Λειτουργία κουμπιού: //+ (αύξηση έντασης χρώματος) //- (μείωση έντασης χρώματος) //R (ελάχιστη ένταση=0) //S (μέγιστη ένταση=255) //************************************************************* void draw_buttons(int x, int y, int d) { draw_p(x+10,(y+d/2)+10,40,30,'+'); draw_p(x-50,(y+d/2)+10,40,30,'-'); draw_p(x+10,(y+d/2)+50,40,30,'S'); draw_p(x-50,(y+d/2)+50,40,30,'R'); } //************************************************************* //Σχεδίαση κουμπιών //xstart, ystart: συντεταγμένες x,y της πάνω αριστερής γωνίας //wd: πλάτος, ht: ύψος, s: κείμενο (χαρακτήρας) κουμπιού //************************************************************* void draw_p(int xstart, int ystart, int wd, int ht, char s) { fill(0); stroke(255); rect(xstart, ystart, wd, ht); fill(255); textSize(30); text(s, xstart+10, ystart+30); } //************************************************************* //Χειρισμός κλικ ποντικιού //Οι μεταβλητές mouseX και mouseY, περιέχουν πάντα τις //συντεταγμένες του δείκτη του ποντικού //Η συνάρτηση καλείται αυτόματα σε κάθε κλικ του ποντικιού //Ένα κουμπί πατήθηκε αν τα mouseX και mouseY ανήκουν //στην περιοχή που έχει σχεδιαστεί //************************************************************* void mouseClicked() { //+ RED if ((mouseX>=xinit+10) && (mouseX<=xinit+40)) if ((mouseY>=(y+d/2)+10) && ((mouseY<=(y+d/2)+30))) { red=red+5; if (red>255) red=255; } //- RED if ((mouseX>=xinit-50) && (mouseX<=xinit-50+40)) if ((mouseY>=(y+d/2)+10) && ((mouseY<=(y+d/2)+30))) { red=red-5; if (red<0) red=0; } //+ RED if ((mouseX>=xinit+10) && (mouseX<=xinit+40)) if ((mouseY>=(y+d/2)+50) && ((mouseY<=(y+d/2)+70))) red=255; //- RED if ((mouseX>=xinit-50) && (mouseX<=xinit-50+40)) if ((mouseY>=(y+d/2)+50) && ((mouseY<=(y+d/2)+70))) red=0; //+ GREEN if ((mouseX>=(xinit*2)+10) && (mouseX<=(xinit*2)+40)) if ((mouseY>=(y+d/2)+10) && ((mouseY<=(y+d/2)+30))) { green=green+5; if (green>255) green=255; } //- GREEN if ((mouseX>=(xinit*2)-50) && (mouseX<=(xinit*2)-50+40)) if ((mouseY>=(y+d/2)+10) && ((mouseY<=(y+d/2)+30))) { green=green-5; if (green<0) green=0; } //+ GREEN if ((mouseX>=(xinit*2)+10) && (mouseX<=(xinit*2)+40)) if ((mouseY>=(y+d/2)+50) && ((mouseY<=(y+d/2)+70))) green=255; //- GREEN if ((mouseX>=(xinit*2)-50) && (mouseX<=(xinit*2)-50+40)) if ((mouseY>=(y+d/2)+50) && ((mouseY<=(y+d/2)+70))) green=0; //+ BLUE if ((mouseX>=(xinit*3)+10) && (mouseX<=(xinit*3)+40)) if ((mouseY>=(y+d/2)+10) && ((mouseY<=(y+d/2)+30))) { blue=blue+5; if (blue>255) blue=255; } //- BLUE if ((mouseX>=(xinit*3)-50) && (mouseX<=(xinit*3)-50+40)) if ((mouseY>=(y+d/2)+10) && ((mouseY<=(y+d/2)+30))) { blue=blue-5; if (blue<0) blue=0; } //+ BLUE if ((mouseX>=(xinit*3)+10) && (mouseX<=(xinit*3)+40)) if ((mouseY>=(y+d/2)+50) && ((mouseY<=(y+d/2)+70))) blue=255; //- BLUE if ((mouseX>=(xinit*3)-50) && (mouseX<=(xinit*3)-50+40)) if ((mouseY>=(y+d/2)+50) && ((mouseY<=(y+d/2)+70))) blue=0; } void keyPressed() { if (key==27) exit(); }