Ελέγχουμε διάφορες ηλεκτρονικές συσκευές από το Android και το Arduino
- Τρίτη, 09 Φεβρουαρίου 2016 20:16
Πριν από χρόνια σας είχα δείξει ενδεικτικά ένα μέρος του σπιτιού μου, το οποίο (χάρη στο Arduino) ελέγχω από το Android κινητό μου -ή φυσικά και από οποιονδήποτε υπολογιστή-.
Το συγκεκριμένο άρθρο αφορά την πιο συχνή ερώτηση που δέχομαι -τον έλεγχο από το Android "πιο πολύπλοκων" συσκευών, όπως τηλεοράσεις, κλιματιστικά, ηχοσυστήματα κτλ.- Και εξηγούμαι.
Ο έλεγχος των κεντρικών φώτων στα δωμάτια, ο έλεγχος φωτιστικών δαπέδου/γραφείου, του θερμοσίφωνα, της καφετιέρας μου, της ηλεκτρικής σόμπας κτλ, απαιτεί απλά ένα relay στο κύκλωμα τροφοδοσίας τους για ενεργοποίηση/απενεργοποίηση από το Arduino (και στην συνέχεια από το Android), το οποίο έδειξα για πολλές περιπτώσεις πώς μπορείτε να το αντιμετωπίσετε. Με τις υπόλοιπες συσκευές;
Hint για το πώς μπορείτε να τις ελέγξετε και αυτές είχα δώσει στο άρθρο "ασύρματου" ελέγχου της DSLR μου, μέσω IR LED. Ναι, δεν το είχα δείξει στο Project του Smart Home -αλλά η λογική παραμένει η ίδια-. Απλά αντί το Arduino να στείλει την υπέρυθρη κυματομορφή όταν λάβει στην COM port του κάποιο σήμα, θα την στέλνει όταν λάβει κάποιο συγκεκριμένο GET request στον Server που τρέχει σε αυτό, χάρη στην Ethernet Shield. Επειδή σας κούρασα, πάμε στο βίντεο και συνεχίζουμε:
Στην ουσία μπορούμε να διαβάσουμε την κυματομορφή που παράγει το χειριστήριο υπερύθρων της εκάστοτε συσκευής, και μετά να την αναπαράξουμε από ένα υπέρυρθο LED. Γιάννη δεν έχουμε παλμογράφο σας ακούω να λέτε και έχετε δίκιο. Γι' αυτόν τον λόγο μπορείτε να χρησιμοποιήσετε μία δίοδο υπερύρθων όπως η TSOP34838, ή αντίστοιχες (TSOP38238), με ελάχιστο κόστος.
Αφού συνδέσουμε την IR δίοδο, μπορούμε να χρησιμοποιήσουμε κάποια από τις έτοιμες IR βιβλιοθήκες του Arduino για να διαβάσουμε την κυμματομορφή. Η χρήση κάποιας έτοιμης βιβλιοθήκης γλιτώνει στον μέσο χρήστη πολύ κόπο από την κατανόηση (αλλά και υλοποίηση) διαφόρων πρωτοκόλλων που θα συναντήσει (NEC, Sony, RC5, RC6). Στην συνέχεια συνδέουμε τουλάχιστον ένα υπέρυθρο LED σε κάποιο/κάποια PWM Digital Pin του Arduino. (Προσωπικά για δική μου ευκολία, χρησιμοποίησα διαφορετικό Arduino, ένα για να διαβάσω την κυματομορφή, και ένα άλλο για να την αναπαράξω -με διευκόλυνε να μην χρειάζεται να αλλάζω συνέχεια sketches.) Για να διαβάσετε από το TSOP χρησιμοποιήστε το example IRrecvDumpV2 που περιέχεται στην βιβλιοθήκη, ενώ για να αναπαράξετε την κυματομορφή μπορείτε να δείτε το IRsendDemo (ή για άγνωστες κυματομορφές που δεν ακολουθούν κάποιο γνωστό πρωτόκολλο, το IRsendRawDemo)
Παρακάτω δίνω τον κώδικα του Arduino (με την Ethernet Shield) που περιέχει (προφανώς) τα σήματα των δικών μου συσκευών. Ενδεικτικά ο Server μας τρέχει στο 192.168.10.40 (προφανώς αλλάζετε την IP σε αντίστοιχη για το δικό σας δίκτυο), όπως επίσης προφανώς με port forwarding (και dynDNS) μπορείτε να "ανοίξετε" τον Server προς το Internet (με ό,τι αυτό συνεπάγεται).
Τόσο στην Android εφαρμογή, όσο και στην εφαρμογή στο laptop που δείχνω, κάνω GET Requests στα URLs που περιέχει ο κώδικας του Arduino παρακάτω:
#include <SPI.h> #include <Ethernet.h> #include <IRremote.h> IRsend My_Sender; byte mac[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; IPAddress ip(192, 168, 10, 40); //IPAddress gateway(192, 168, 10, 254); //IPAddress subnet(255, 255, 255, 0); int khz = 38; // 38kHz sixnotita ferontos unsigned int IrSigOn[] = {8750, 4200, 400, 1700, 350, 650, 400, 600, 450, 600, 400, 1650, 400, 600, 450, 600, 400, 650, 400, 600, 450, 600, 400, 600, 450, 600, 400, 600, 450, 1650, 400, 600, 400, 650, 400, 1650, 400, 1650, 400, 1650, 400, 1650, 400, 650, 400, 600, 400, 1700, 400, 600, 450, 600, 400, 1700, 400, 600, 450, 1650, 400}; unsigned int IrSigOff[] = {8750,4200,450,1650,400,600,400,650,400,600,400,1650,450,600,400,600,450, 650,400,1650,400,1650,400,650,400,600,450,600,400,600,450,600,450,600,400,650,400,600,400,650, 400,600,400,650,400,1650,400,600,450,1600,450,600,450,550,450,650,400,1650,400}; EthernetServer server(80); String readString; void setup() { pinMode(A0, OUTPUT); //Serial.begin(9600); Ethernet.begin(mac, ip); //Ethernet.begin(mac, ip, gateway, subnet); server.begin(); //Serial.print("O Server trexei stin IP: "); //Serial.println(Ethernet.localIP()); //Serial.println("Bootup!"); } void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("new client"); while (client.connected()) { if (client.available()) { char c = client.read(); //read char by char HTTP request if (readString.length() < 100) { readString += c; //Serial.print(c); Serial.write(c); if (c == '\n') { //Serial.println(readString); //gia debugging client.println("HTTP/1.1 200 OK"); //send new page client.println("Content-Type: text/html"); client.println(); client.println("<a href=\"/?tvon\">TV On</a>"); client.println("<a href=\"/?tvoff\">TV Off</a>"); client.println("<a href=\"/?chplus\">C+</a>"); client.println("<a href=\"/?chminus\">C-</a>"); client.println("<a href=\"/?volplus\">V+</a>"); client.println("<a href=\"/?volminus\">V-</a>"); client.println("<a href=\"/?airon\">Air On</a>"); client.println("<a href=\"/?airoff\">Air Off</a>"); client.println("<a href=\"/?fwson\">Fws On</a>"); client.println("<a href=\"/?fwsoff\">Fws Off</a>"); //telika kratisa to html sta apolitws vasika, alliws ta global vars crasharan to arduino delay(1); client.stop(); if (readString.indexOf("?tvon") > 0) //on { My_Sender.sendRC5(0x84c, 12); //Serial.println("TVon"); } else if (readString.indexOf("?tvoff") > 0) //off { My_Sender.sendRC5(0x84c, 12); //Serial.println("TVoff"); } else if (readString.indexOf("?chplus") > 0) //plus { My_Sender.sendRC5(0x060, 12); //Serial.println("Ch+"); } else if (readString.indexOf("?chminus") > 0) //minus { My_Sender.sendRC5(0x061, 12); //Serial.println("Ch-"); } else if (readString.indexOf("?volplus") > 0) //plus { My_Sender.sendRC5(0x050, 12); //Serial.println("Vol+"); } else if (readString.indexOf("?volminus") > 0) //minus { My_Sender.sendRC5(0x051, 12); //Serial.println("Vol-"); } else if (readString.indexOf("?airon") > 0) //on { My_Sender.sendRaw(IrSigOn, sizeof(IrSigOn) / sizeof(IrSigOn[0]), khz); //Serial.println("AirOn"); } else if (readString.indexOf("?airoff") > 0) //off { My_Sender.sendRaw(IrSigOff, sizeof(IrSigOff) / sizeof(IrSigOff[0]), khz); //Serial.println("AirOff"); } else if (readString.indexOf("?fwson") > 0) //on { digitalWrite(A0,HIGH); //Serial.println("Energopoihsh Relay"); } else if (readString.indexOf("?fwsoff") > 0) //off { digitalWrite(A0,LOW); //Serial.println("Apenergopoihsh Relay"); } //clearing string for next read readString = ""; //ena mikro delay gia ton browser delay(1); client.stop(); //Serial.println("client disonnected"); } } } } } }