Prolunga relè v2.0 – Python & Atmega328p
Ecco presentata la versione 2.0 del modulo per il controllo remoto di elettrodomestici.
Nella versione precedente abbiamo visto i componenti essenziali:
– Una prolunga elettrica, con un’uscita femmina.
– Un microcontrollore con uscita seriale (che collegheremo ad un pc* )
– Un relè che supporti alte tensioni (Io ho scelto un SSR – Solid State Relay … )
A cui aggiungiamo adesso:
– Alimentatore DC 12V 1A.
– Moduli radio ricevente/trasmittente con frequenza a 433Mhz (una frequenza libera nel nostro paese).
Il codice Python e l’interfaccia web, rimangono INVARIATI, quindi potete utilizzare gli stessi della versione 1.0, che riportiamo qua per comodità:
Codice Python:
import serial import sys import time import os import win32com.client #incluso nel pacchetto pywin32 import urllib.request SERIALPORT = input("Inserire la porta seriale a cui e' connesso il dispositivo: ") # Set up serial port try: ser = serial.Serial(SERIALPORT, 9600) except serial.SerialException: print('No device connected - exiting...') time.sleep(4) sys.exit() ''' try: #cancelliamo il file dei comandi se non e' in uso. os.remove('C:\\xampp\\htdocs\\luce\\comando.txt') except: pass ''' print("### Light Module - Jupiter Home-System 1.4 ###\n") print("In attesa di comandi dall'interfaccia web...") #COMANDI def esegui_cmd(comando): global ser global on if comando == "on": ser.write("m".encode('latin1')) print("Luce accesa! :)") elif comando == "off": ser.write("n".encode('latin1')) print("Luce spenta...!") else: print("Comando non riconosciuto...") #LISTENING id_code = 0000 while True: try: response = urllib.request.urlopen('http://www.roccomusolino.com/luce/comando.txt') x = response.read() x = x.decode("utf-8") if id_code != x[-4:]: cmd = x[0:x.index(" ")] #estrae dalla riga solo il comando esegui_cmd(cmd) id_code = x[-4:] #aggiorniamo con le 4 cifre dell'id finale (e' di tipo str) except: pass #END |
Codice interfaccia:
<!DOCTYPE html> <html> <head><title>Play with light!</title> <script src="jquery-1.9.1.min.js"></script> <script> var k = "off"; //variabile che definisce lo stato della luce sulla pagina web. La inizializziamo ad "off". function toggle(p_val){ //p_val = "on" oppure "off" if (!(k == p_val)){ // un comando è stato inviato, si invia il comando all'attuatore. $.get("switch.php", { action: p_val }) .done(function(data) { //segue codice per switch dell'img. if (p_val == "on") { $('#icona_luce').attr("src", "light-on.png"); } else { $('#icona_luce').attr("src", "light-off.png"); } k = p_val; }); } } function img_click(){ if (k == "off"){ toggle("on"); } else toggle("off"); } function check_status(){ $.get("switch.php?status", function(data) { toggle(data); // a prescindere dal valore, con questa funzione richamata ciclicamente si verifica la sincronizzazione tra pagina web e attuatore. }); } setInterval("check_status()", 3000); </script> </head> <body> <center> <br/><br/> <a href="#" onclick="img_click();"><img src="light-off.png" id="icona_luce" /></a> </center> </body> </html> |
Codice switch.php per processare il comando ricevuto dall’interfaccia:
<?php if (isset($_GET['action'])) { $comando = $_GET['action']; $comando = preg_replace('/[^a-zA-Z0-9]/', '', $comando); //vengono filtrati tutti i caratteri speciali, disponibili lettere minuscole, maiuscole e numeri. $ip = $_SERVER['REMOTE_ADDR']; //scriviamo il file di log.txt che ci indica il comando lanciato, a che ora, e da qualche indirizzo IP: // . . . //scriviamo il file di comando.txt $filename= "comando.txt"; $file = fopen($filename, "r+") or exit("errore apertura file"); $random = rand(1000,9999); $str = fwrite($file, "$comando $random"); } //se è presente il parametro "status", verrà restituito l'ultimo valore nel file di log. Questo parametro viene usato dalla richiesta in AJAX per ottenere il valore. if (isset($_GET['status'])){ $filename = "comando.txt"; $file=fopen($filename,"r") or exit("Impossibile aprire il file!"); $str = fread($file, filesize($filename)); echo substr($str, 0, strpos($str, " ")); } ?> |
Ciò che viene introdotto è una modifica nei codici dei microcontrollori, ora sono 2 e non più 1, ed entrambi montano rispettivamente un modulo per la trasmissione e la ricezione radio a 433Mhz.
La trasmittete TX è collegata in seriale al PC. Come nella foto seguente:
La ricevente RX fa parte del circuito che pilota il relè allo stato solido.
Per ottenere un lavoro pulito, l’arduino è stato inscatolato e viene alimentato attraverso un alimentatore 12V collegato a “T” con la stessa prolunga che alimenterà l’elettrodomestico (usando pin VIN).
Il trasmettitore è collegato al micro-controllore, e grazie alla libreria VirtualWire riceve facilmente comandi dalla trasmittente TX.
Giu qualche foto esplicativa:
Questo è il codice che andrà caricato nell’arduino trasmettitore:
//Transmitter - Arduino connesso in seriale, riceve "m" o "n" da tastiera e spedisce via radio 433mhz le stringhe "on" oppure "off" #include <VirtualWire.h> int val; void setup() { Serial.begin(9600); // Debugging only // Initialise the IO and ISR vw_set_ptt_inverted(true); // Required for DR3100 vw_setup(2000); // Bits per sec } void loop() { if (Serial.available()) { val = Serial.read(); Serial.println(val); if (val == 110) // n = 110 in dec { const char *msg = "off"; vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); // Wait until the whole message is gone } else if (val == 109) //109 = m in dec { const char *msg = "on"; vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); // Wait until the whole message is gone } } delay(200); } |
Questo invece il codice per l’arduino ricevente, che si collega al relè attraverso il pin digitale 8:
// Reicever - Al pin 8 è connesso il relè. #include <VirtualWire.h> void setup() { //Serial.begin(9600); // Debugging only pinMode(8, OUTPUT); // Initialise the IO and ISR vw_set_ptt_inverted(true); // Required for DR3100 vw_setup(2000); // Bits per sec vw_rx_start(); // Start the receiver PLL running } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if (vw_get_message(buf, &buflen)) // Non-blocking { int i; String x = ""; //conterrà la stringa ricevuta for (i = 0; i < buflen; i++) { //Serial.print(buf[i], HEX); //Serial.print(" "); //Serial.print((char) buf[i]); //casting a carattere del codice ascii x += (char)buf[i]; } //Serial.println(""); if (x == "on"){ // Se il mex ricevuto è "on" //Serial.println(x); digitalWrite(8, HIGH); }else if(x == "off"){ digitalWrite(8, LOW); } } } |
Nei moduli visti in foto, non sono state ancora saldate le due antenne. Come antenna si possono utilizzare fili di rame.. (smaltati o meno, poco cambia, quelli smaltati avranno soltanto una maggiore resistenza all’ossidazione, che comunque non compromette il segnale, dei fili di rame si possono riciclare da cavi telefonici o di rete).
La domanda ora è, quanto devono essere lunghe le antenne? Esiste un modo per calcolare la lunghezza ottimale di un’antenna:
Quando si realizza un’antenna per un dispositivo RF il massimo lo si ottiene con un’antenna che è lunga quanto la lunghezza d’onda (lambda) da trasmettere/ricevere. La formula per calcolare tale lunghezza d’onda è la seguente:
Lambda = v/f
Dove v è la velocità di propagazione nel mezzo di trasmissione, che nell’etere è pari alla velocità della luce, 300.000 Km/s, espressa in metri, ed f è la lunghezza d’onda, in Hertz.
Qiundi per 433 MHz si ha
300.000.000/433.000.000=0,6928 m
Quindi 69,28 cm.
Ora, siccome spesso non è praticabile fare l’antenna di pari lunghezza di lambda, si ricorre alle frazioni.
Quindi si usa lambda mezzi, lambda quarti ecc.. cioè lambda/2, lambda/4 ecc…
Un quarto di lambda nel nostro caso è appunto 69.28/4 = 17.32 cm.
Dunque per una frequenza di 433Mhz necessitiamo di un’antenna di 17.32 cm che è un quarto d’onda della lunghezza ottimale.
Per comodità potete scaricare l’intero software, in versione 2.0, con tanto di interfaccia web, nell’archivio compresso, a questo link: DOWNLOAD SORGENTI.
Commenti