Cose che ho letto

martedì 11 dicembre 2012

Arduino e OpenWRT - Accensione led da remoto con server e client Python

Se il vostro router OpenWRT è provvisto di una porta USB, una cosa che di sicuro sarà venuto in mente a tutti di fare, è collegarvi un Arduino per implementare un controllo da remoto e gestire i vostri progetti di domotica per esempio. Nel nostro semplice caso l'accensione di un LED


Andiamo a vedere come realizzare una semplice interazione sfruttando la comunicazine via seriale e trasmissione di dati via socket, quindi via internet, con una soluzione Client e Server in Python.


Per prima cosa dobbiamo far riconoscere arduino al router, per far questo installiamo i pacchetti essenziali per le periferiche usb, gia visti in altre guide, e disponibile sulla wiki usb ufficiale di OpenWRT, e quelli specifici per i nostri scopi
  • opkg update
  • opkg install kmod-usb-acm kmod-usb-serial kmod-usb-serial-ftdi
  • reboot
Questi pacchetti consentono la comunicazione con la maggior parte dei chip di interfacciamento montati da arduino e altri microcontrollori, per casi particolari googolate o chiedete.

Dopo il riavvio colleghiamo l'arduino e dopo una decina di secondi controlliamo l'avvenuto riconoscimento con il comando dmesg, leggeremo qualosa tipo

uhci_hcd: USB Universal Host Controller Interface driver
i2c /dev entries driver
cdc_acm 1-1.4:1.0: ttyACM0: USB ACM device
usbcore: registered new interface driver cdc_acm
cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters
usbcore: registered new interface driver usbserial
USB Serial support registered for generic
usbcore: registered new interface driver usbserial_generic

ttyACM0 è il nome assegnato al nostro dispositivo, l'ultimo passo prima di testare la comunicazione è ovviamente caricare su arduino il giusto scatch, ovviamente gia pronto per voi: Download

const int ledPin = 13;
int incomingByte;

void setup() {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
}

void loop() {

    if (Serial.available() > 0) {
        incomingByte = Serial.read();
        if (incomingByte == 'H') {
            digitalWrite(ledPin, HIGH);
        }
        if (incomingByte == 'L') {
            digitalWrite(ledPin, LOW);
        }
    }
}

Sostanzialmente l'arduino legge dei caratteri che inviamo sulla seriale, se riceve H accende il led connesso al pin 13, se legge L lo spegne.

Una volta caricato il programma e connesso l'arduino, possiamo testare la connessione aprendo 2 shell openwrt
  • nella prima digitiamo il comando "cat /dev/ttyACM0" (nel mio caso)
  • questa schell va lasciata aperta fintanto che usufruiamo della connessione
  • nella seconda inviamo i caratteri con "echo H > /dev/ttyACM0" o "echo L > /dev/ttyACM0"
Se tutto è andato liscio accenderete e spegnerete tranquillamente il vostro led.

Comunicazione seriale da remoto con client e server Python

Quello che ci prefiggiamo di fare è instaurare una connessione tramite socket tra un programma che avviamo sul nostro computer e un programma che è costantemente in esecuzione sul nostro router, trasmettere i caratteri che digitiamo, e scriverli sulla seriale remota.
Dando per scontato che abbiate installato sul vostro pc Python, vi mostrerò come installarlo su openwrt assieme alle librerie necessarie. Per continuare dovete avere gia una partizione montata, come una penna usb, su cui installare Python, dato che la versione per openwrt occupa 20MB, che solitamente è di più della memoria disponibile che abbiamo su dispositivi embedded.
  • abilitiamo l'installazione su partizioni esterne modificnado il file  /etc/opkg.conf
  • src/gz packages http://downloads.openwrt.org/backfire/10.03.1/brcm63xx/packages
    dest root /
    dest ram /tmp
    dest penna /mnt/penna - questo è il percorso alla mia partizione montata
    lists_dir ext /var/opkg-lists
    option overlay_root /overlay
  • opkg install -d penna python pySerial
  • modifichiamo il file /etc/profile
  • inserendo di seguito nella variabile PATH il percorso di installazione sulla nostra partizione
    • export PATH=/bin:/sbin:/usr/bin:/usr/sbin
    • export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/mnt/penna/usr/bin
  • reboot
  • mettete in una cartella a piacere sul vostro router il mio file mySerialServer
  • sul nostro pc scarichiamo invece mySerialClient
  • entrambi i file sono molto semplici da capire e mofidicare, inserite le vostre specifiche informazioni
  • avviamo il server digitando il comando "python mySerialServer.py" nella cartella in cui abbiamo sistemato il file
  • vedremo stampate a schermo alcune informazioni di debug che ci confermano la corretta esecuzione del programma
  • vi ricordo che affichè il server ascolti correttamente, la porta scelta deve essere forwardata sul nostro dispositivo openwrt, e aperta nel firewall proprietario, vedi guida al controllo remoto
  • avviamo il programma client sul nostro computer e attendimo la connessione
  • adesso digitando i caratteri H ed L potremo controllare a distanza l'accensione del nostro led, o della nostra caldaia, semplicemente sostituendo il led con un relè
Il mio server in particolare è progettato per rimanere sempre in running una volta avviato, se usciamo chiudendo la finestra client o inviando il carattere vuoto o q. Se invece inviamo exit chiuderemo definitivamente client e server, liberando così memoria e porte.
NB: prima di poter riaprire il sevrer bisognerà aspettare un paio di minuto. E' un difetto dato probabilmente dalla versione python per openwrt o dalla potenza limitata del processore.
  • Se vogliamo che il server parta da solo all'accesione del router, basterà tramite interfaccia grafica, System->Startup, aggiungere il comando personalizzato 
  • python /miacartella/mySerialServer.py
Per il momento è tutto gente ;) Alla prossima!

I commenti sono sempre graditi!

Ah, dimenticavo i ringraziamenti e i link utili

8 commenti:

  1. Gran bel lavoro, complimenti!
    Mi piacerebbe testarlo, ma i file non si scaricano più dal Dropbox.

    RispondiElimina
    Risposte
    1. ciao e garzie, ho appena ritestato i link, e funzionano, riprova ;) in caso di problemi ricommenta e li metto su un altro sito

      Elimina
  2. Ciao volevo sapere se fosse possibile eseguire i comandi su arduino direttamente da pagina web o da smartphone.

    RispondiElimina
    Risposte
    1. se ti interessa farlo da smartphone, per android c'è QPython che ti consente di usare lo stesso script. altrimenti per browser, devi creare una pagina web che metterai sul router, con un semplice pulsante che invia una stringa di testo a arduino o allo script python in locale. ti consiglio in php

      Elimina
    2. Grazie mille!Comunque i comandi devo essere eseguiti per forza in python, ad esempio non sarebbe possibile più semplicemente in php?

      Elimina
    3. non credo si possa aprire una comunicazione seriale direttamente in php. ma puoi sempre chiamare uno script esterno sh oppure un altro linguaggio, python secondo me rimane la soluzione migliore

      Elimina
  3. È possibile visualizzare l'output di Arduino su una pagina web tramite Arduino?

    RispondiElimina
    Risposte
    1. tramite arduino, vuoldire usare una ethernet shield

      Elimina