Raspberry My

Programmare il più famoso microcomputer, dalle cose più semplici alle più complesse

Il Raspberry Pi ha anche la possibilità di comandare dell'hardware esterno in maniera molto semplice, andando ad “invadere” il campo di Arduino.
Da buon computer può essere programmato in vari modi e con vari linguaggi.
Proviamo a vederne alcuni, sia per fare cose semplici senza hardware aggiuntivo,
sia per comandare l'hardware esterno collegato alle porte disponibili. (Stefano Salvi)

NOTA: Questa presentazione è una versione statica della demo, che deve girare su di una raspberry. Le videate di tutti gli esempi sono quindi degli screenshot. A evidenziare questo nello sfondo compare la parola FACSIMILE.
NOTA 1: Questo lavoro è orientato a persone che abbiano un minimo di familiarità con sistemi Linux (come Raspbberry Pi) ed una conoscenza, almeno di base, di qualche linguaggio di programmazione.
Il suo scopo non è di insegnare a programmare, ma di mostrare varie possibilità (ovviamente non tutte) di programmare la Raspberry Pi.
NOTA 2: tutti i file del progetto sono indicati con il relativo percorso. Se non sono messi nella directory indicata, tutti i collegamenti contenuti non funzionano.
In particolare, i percorsi relativi sono relativi alla document_root del webserver, di default /var/www/html ma l'intero sottoalbero può anche essere messo in un'altra directory all'interno dello spazio Web del Webserver.
I percorsi assoluti sono invece relativi agli eseguibili cgi e sono riferiti alla configurazione standard di Apache su Raspberry.
Gli archivi alla fine del lavoro contengono i file che vanno nello spazio Web e quelli che vanno nella cartella cgi_bin, già organizzati secondo la struttura di directory necessatia, pronti per essere caricati sulla SD del Raspberry Pi.
NOTA 3: Tutti i file di questo lavoro, e quelli che creerete, vanno caricati sul Raspebrry Pi. Per farlo esistono moltissimi modi. e sicuramente ci sono un sacco di altri modi che non mi sono venuti in mente (io ho utilizato l'ultimo in elenco)

Il Raspberry Pi, giunto ormai alla sua 3 versione, è un microcomputer con Linux che può spesso essere usato al posto di un computer normale.
Esistono delle immagini preconfezionate per usarlo in vari modi, ad esempio come Media Center.
Ha però anche la possibilità di comandare dell'hardware esterno in maniera molto semplice, andando ad invadere, per certi versi, il campo di Arduino.
Da buon computer può essere programmato in vari modi e con vari linguaggi.
Proviamo a vederne alcuni, sia per fare cose semplici senza hardware aggiuntivo, sia per comandare l'hardware esterno collegato alle porte disponibili.

Per usarlo come semplice computer tre possibilità:

  1. Usarlo come sostituto di un desktop
  2. Usarlo come terminale per visualizzare dati o comandare un sistema
  3. Usarlo come server

Nel primo caso basterà collegare un monitor, una tastiera ed un mouse e caricare una distribzione desktop sulla SD. Otterremo un PC molto economico, sebbene di prestazioni non esaltanti.
Non è richiesta alcuna programmazione.

Nel secondo caso dovremo avere un sistema da monitorare o controllare e dovremo scrivere un adeguato software con interfaccia grafica.
Salvo non si usi un browser per il lavoro, probabilmente scriveremo un programma in Python o in C.
Non avendo un sistema da controllare, non è la soluzione giusta per questa dimostrazione.

Per finire, possiamo usarlo come server. In questo caso ci servirà una distribuzione senza interfaccia grafica e probabilmente dovremo programmare il nostro server.
Questo è l'ambiente più semplice per dimostrare l'uso di vari linguaggi.

La scelta è quindi di realizzare un server. Il più semplice da mettere in piedi è un server WEB, che consente una grande gamma di possibilità di programmazione.

Prepariamo quindi la nostra Raspberry per questo scopo.

Per prima cosa dovremo caricare su di una SD card o MicorSD card, a seconda del modello diRaspberry che stimo utilizzando, una versione denza interfaccia grafica di un sistema operativo.
La scelta ufficiale è Raspbian, in particolare utilizzerò Raspian Jessie Light, che può essere scaricato dalla pagina ufficiale https://www.raspberrypi.org/downloads/raspbian/
Il link diretto al file da scaricare $egrave; https://downloads.raspberrypi.org/raspbian_lite_latest
È anche disponibile una pagina di istruzioni, sempre collegata alla pagina del download: https://www.raspberrypi.org/documentation/installation/installing-images/README.md

Una volta scaricato il file sul nostro PC, potremo scompattarlo e copiarlo su di una scheda SD.
Perché il sistema funzioni, il file deve essere copiato sull'intera scheda, non sulla partizione dati. In questo modo sula scheda SD creeremo due partizioni, su di una delle quali si trova il filesystem di Linux.
Su un sistema Linux divremo entrare come superurente (root) e dare i segiuenti comandi:

unzip 2016-09-23-raspbian-jessie-lite.zip
dd if=2016-09-23-raspbian-jessie-lite.img of=/dev/sdb bs=1M

dove 2016-09-23-raspbian-jessie-lite.zip è il file che avete scaricato. Potrebbe avere un nome diverso, se è uscita una nuova versione di Raspbian;
2016-09-23-raspbian-jessie-lite.img è il file decompresso. Anche questo potrebbe aver eun nome diverso;
/dev/sdb è il dispositivo della SD (l'intera SD, non la partizione); a seconda del vostro sistema potrebbe avere un nome diverso. Attenti a non sovrascrivere uno dei vostri dichi fissi!

Ora toglieremo la SD dal computer e lo inseiremo nella Rapberriy (spenta, ovvimente). Collegheremo monitor e tastiera e daremo corrente.
Al primo avvio la scheda si configura automaticamente ed espande il file system ad occupare l'intera card. Potremo eventualmente configurare ulteriormente la scheda con il comando:

sudo raspi-config

Dobbiamo ora installare il Web Server. Raspbian offre due opzioni: Lighttpd e Apache2.
Il primo è un server molto legero e semplice, utile in molti casi. Dato che però vogliamo utilizzare programmi esterni e PHP, è meglio installare Apache2. Per farlo daremo i comandi:

sudo aptitude update
sudo aptitude install apache2

Potremo ora collegarci al nostro Raspberry, digitando il suo indirizzo IP (lo possiamo ottenere con il comando ifconfig) sul nostro browser.
Vedremo la pagina di cortesia, caricata nella directory dei file Web (la documentroot di Apache2) che è /var/www/html

Possiamo ora scrivere il nostro primo programma, utilizzando semplicemente HTML, CSS e Javascript.

Questo è un esempio minimo di programmazione. Il programma (il javascript) viene eseguito nel browser. La Raspberry è sfruttata solo per servire la pagina ed i file correlati (il CSS, il Javascript e le immgini).

Cerchiamo ora di fare eseguire un programma sul Raspberry.
Apache consente di eseguire dei programmi esterni attraverso l'interfaccia cgi (Common Gateway Interface).
Questo standard prevede che:

  1. Il programma sia in una perticolare directory (nel nostro caso /usr/lib/cgi-bin) o nelle sue sottodirectory
  2. Il programma sia eseguibile da shell (quindi anche uno script in qualunque linguaggio supportato, non solo un eseguibile)
  3. Il programma stampi su standard output il contenuto da inviare al browser
  4. Prima del contenuto da inviare al browser il programma deve stampare una linea contente la scritta content type: text/html dove text/html è il tipo mime dle contenuto trasmesso
  5. Dopo questa riga il programma deve stampare una riga vuota
  6. Il contenuto del form della pagina chiamante verrà rstituito nella variabile di ambiente QUERY_STRING esattamete come compare nell'URL, dopo il ?
  7. Il programma sarà quindi lanciato accedendovi tramite un'URL che inizi /cgi-bin/ all'interno del sito

L'installazione standard di Apache non abilita i programmi esterni. Per abilitarli dovremo lanciare i sefuenti comandi:

sudo a2enmod cgi
sudo service apache2 restart

Potremo ora scrivere il nostrp programma sulla Raspberry. Come primo esempio scriveremo uno script di shell:

Il prossimo passo è di programmare il nostro Raspberry in PHP. Questo è un cosiddetto linguaggio embedded (come d'altronde il javascript), in quanto le istruzioni PHP sono inserite all'interno di una pagina HTML utilizzando un tag particolare.
A differenza del Javascript l'utente non può vedere il codice PHP perchè l'elaborazione avviene sul server ed all'utente arriva solo il suo risultato.
I programmi PHP possono essere eseguiti direttamente da Apache, tramite un apposito modulo.
Ancora, nell'installazione standard PHP non c'è, quindi dovremo installarlo con il comando:

sudo aptitude install php5

Siamo ora pronti a scrivere il nostro programma PHP.
Di norma io consiglio di non mischiare codice PHP all'interno di HTML, perché questo rende il codice prodotto difficilmente manutenibile. Suggerisco in genere di produrre l'HTML direttamente all'interno del codice, tramite istruzioni print o echo
In questo esempio derogo da questa mia regola, per non appesantire troppo l'esempio.
Vediamolo:

Ed arriviamo alla cosa più complessa: la programmazione C.
Naturalmente questo esempio è come sparare ad una mosca con un cannone. Ha senso solo se il programma C deve fare operazioni complesse che con programmi in altri linguaggi risulterebbero impossibili oppure se il C è il nostro linguaggio preferito.

A differenza dei linguaggi usati finora, che erano interpretati, il C è un linguaggio compilato. Per poterlo utilizzare dovremo quindi compilarne il testo. Occorre quindi installare il compilatore e gli strumenti accessori:

sudo aptitude install build-essential

Potremo quindi scrivere il nostro programma e compilarlo. Per semplificare l'operazione ho anche creato un semplicissimo Makefile.
Potremo quindi compilare il programma entrando come root, andando nella directory dei sorgenti e digitando make.
La sessione risulta come questa:

root@raspberrymy:/usr/lib/cgi-bin/c# make clean
rm index.cgi
root@raspberrymy:/usr/lib/cgi-bin/c# ls -l
totale 12
-rw-r--r-- 1 root root 4599 ott 21 19:31 index.c
-rw-r--r-- 1 root root   95 ott 21 13:16 Makefile
root@raspberrymy:/usr/lib/cgi-bin/c# make
gcc -o index.cgi index.c
root@raspberrymy:/usr/lib/cgi-bin/c# ls -l
totale 24
-rw-r--r-- 1 root root  4599 ott 21 19:31 index.c
-rwxr-xr-x 1 root root 10112 ott 30 20:12 index.cgi
-rw-r--r-- 1 root root    95 ott 21 13:16 Makefile
root@raspberrymy:/usr/lib/cgi-bin/c#

Otterremo quindi l'esempio che segue:

Il prossimo passo prevede di connettere dell'hardware al nostro raspberry.
Ogni Raspberry possiede un conettore che porta all'esterno alcuni piedini del processore, detti General Purpose Inputs/Outputs o GPIO che possono essere comnadati dal software per svolgere diverse funzioni.
In particolare, nella versione 2 e 3 della scheda questo connettore possiede 40 piedini.

È possibile collegare hardware esterno direttamente, utilizzando dei fili adeguati.
Per comodità io ho invece collegato il vecchio cavo di un hard disk IDE ad un piccolo adattatore che mi ha consentito di collegare una breadbord. Questo rende la prova dell'hardware molto più semplice.

Utilizzando la breadbord ho collegato un LED, tramite una resistenza da 330 Ohm tra il piedino idicato come #16 e la massa, un pulsante tra il piedino #6 e la massa ed un servomotore al piedino #18 (in realtà nella foto è sconnesso, in quanto è collegato alla fila di fianco al servomotore).

La breadbord con il mLED, il pulsante ed il servocomando

Per poter comandare l'hardware è necessario installare il pacchetto wiringpy, che contiene sia il comando gpio per gestire l'hardware da riga di comando, sia i bindings Python che la libreria wiring per il linguaggio C.
daremo il comando:

sudo aptitude install wiringpi

per installare il pacchetto.

Se a questo punto, direttamente da terminale, dall'utente pi, possiamo dare il comando gpio printall e vedere lo stato dei piedini:

pi@raspberrymy:~ $ gpio readall
 +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 |   IN | 1 |  3 || 4  |   |      | 5V      |     |     |
 |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 0 | IN   | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | IN   | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | OUT  | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI |   IN | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO |   IN | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK |   IN | 0 | 23 || 24 | 1 | IN   | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | IN   | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | OUT  | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
pi@raspberrymy:~ $

Questa schermata ci mostra un sacco di informazioni sul nostro hardware.
Nella colona centrale (Physical) sono indicati i numeri di piedino del connettore a 40 piendini.
Subito di fianco (V) il valore letto sul piedino (se non è un'alimentazione o una massa.
Poi il modo (Mode) che ci indica se il piedino è configurato come un'ingrsso o un'uscita.
Quindi troviamo il nome, come compare sulla documentazione.
Nella colonna successiva (wPi) troviamo la numerazione secondo lo standard della libreria WiringPi.
Infine nella colonna più esterna (BCM) troviamo la numerazione nello standard Broadcom. Quella indicata sull'adattatore è proprio quest'ultima.

Dobbiamo notare quindi che il LED (piedino #16) è connesso al piedino 27 secondo WiringPi, il pulsante (piedino #6) al piedino 22 ed il servomotore (piedino #18) all'1.

Sempre da terminale possiamo impostare la modalità dei piedini, accendere e spegnere il LED e verificare se il tasto è premuto (uscita 0) o rilasciato (uscita 1).
Ricordando che usiamo la numerazione WiringPi, avbbiamo:

pi@raspberrymy:~ $ gpio mode 27 out
pi@raspberrymy:~ $ gpio write 27 1
pi@raspberrymy:~ $ gpio write 27 0
pi@raspberrymy:~ $ gpio mode 22 up
pi@raspberrymy:~ $ gpio read 22
1
pi@raspberrymy:~ $ gpio read 22
0
pi@raspberrymy:~ $

Abbiamo tutti gli ingredienti per poter fare un programmino che dal Web comandi il nostro LED e verifichi lo stato del pulsante.

In particolare, per il pulsante occorre verificarne periodicamente lo stato.
Per farlo senza ricaricare continuamente la pagina, ho utilizzato AJAX (acronimo per Asinchronous Javascript XML) che consente, tramite una chiamata Javascritt, di richedere in background una pagina al server e processarne il contenuto.

Ecco l'esempio:

Mettiamo ora in campo un nuovo linguaggio di programmazione: Python.

Questo linguaggio è installato di default in tutti i sistemi Linux e la libreria per l'interazione con l'hardware è stata installata tramite il pacchetto wiringpi.

Se noi vogliamo utilizzare Python per scrivere programmi CGI, che vengono lanciati dall'utente www-data, e che gestiscano l'hardware, dobbiamo aggiungere l'utente www-data al gruppo gpio, con il comando:

sudo addgroup www-data gpio

Vediamo ora l'esempio:

E veniamo all'ultimo esempio: l'ahdware tramite il linguaggio C.

Per usare l'hardware in C occorre linkare la libreria libwiringPi. La libreria è già stata caricata tramite il pacchetto wiringpy.

A differenza di Python e GPIO, un programma in C che acceda all'hardware deve necessariamente essere lanciato dal superutente.
Per questo motivo non ho potuto inserire direttamente il programma C in cgi-bin, come precedentemente. Ho dovuto nvece scrivere un programma in php che invoca del piccoli programmi in C tramite il comando sudo che consente di eseguire questi programmi con i diritti di root.

Per consentire all'utente www-data di accedere ai nostri programmini come root, dobbiamo creare un apposito file di configurazione nella directory /etc/sudoers.d.
Naturalmente il PHP non può fornire la password a sudo, quindi occorre aggiungere l'utente www-data al gruppo sudo con il comando:

sudo addgroup www-data sudo

Per semplificare la compilazione, che questa volta deve anche richiamare ujna libreria, ho creato un Makefile. Se lo eseguiamo otteniamo:

root@raspberrymy:/var/www/html/cHW# make clean
rm on off pwm testbutton
root@raspberrymy:/var/www/html/cHW# ls -l
totale 28
-rw-r--r-- 1 root root 2767 ott 22 02:02 index.php
-rw-r--r-- 1 root root  250 ott 22 01:02 Makefile
-rw-r--r-- 1 root root  205 ott 22 00:52 off.c
-rw-r--r-- 1 root root  205 ott 22 00:52 on.c
-rw-r--r-- 1 root root  447 ott 22 01:53 pwm.c
-rw-r--r-- 1 root root  248 ott 22 00:55 testbutton.c
-rw-r--r-- 1 root root   57 ott 22 02:00 testbutton.php
root@raspberrymy:/var/www/html/cHW# make
gcc -lwiringPi -o on on.c
gcc -lwiringPi -o off off.c
gcc -lwiringPi -o pwm pwm.c
gcc -lwiringPi -o testbutton testbutton.c
root@raspberrymy:/var/www/html/cHW# ls -l
totale 60
-rw-r--r-- 1 root root 2767 ott 22 02:02 index.php
-rw-r--r-- 1 root root  250 ott 22 01:02 Makefile
-rwxr-xr-x 1 root root 6292 ott 30 20:15 off
-rw-r--r-- 1 root root  205 ott 22 00:52 off.c
-rwxr-xr-x 1 root root 6292 ott 30 20:15 on
-rw-r--r-- 1 root root  205 ott 22 00:52 on.c
-rwxr-xr-x 1 root root 6828 ott 30 20:15 pwm
-rw-r--r-- 1 root root  447 ott 22 01:53 pwm.c
-rwxr-xr-x 1 root root 6452 ott 30 20:15 testbutton
-rw-r--r-- 1 root root  248 ott 22 00:55 testbutton.c
-rw-r--r-- 1 root root   57 ott 22 02:00 testbutton.php
root@raspberrymy:/var/www/html/cHW#

Vediamo quindi l'esempio completo:

Puoi scaricare le configurazioni ed i programmi di questa demo: