
In questo tutorial, vedremo come programmare un semplice theremin che cambia l'intonazione in base alla distanza della mano da un sensore di prossimità ad infrarossi. In aggiunta si può facilmente variare la lunghezza del "beat" e far lampeggiare due o più LED contemporaneamente... è la magia del multi-threading, è la magia di VIPER!
INTRODUZIONE
Il theremin è uno strumento musicale inventato dal fisico russo Lev Sergeevic Termen negli anni '20. A differenza dei comuni strumenti musicali ha due caratteristiche che lo rendono molto interessante per gli amanti della tecnologia: è uno dei primi strumenti musicali ad essere completamente elettronico e può essere suonato senza contatto fisico!
Il funzionamento è abbastanza semplice: due antenne rilevano la posizione nello spazio delle mani dell'esecutore e la parte elettronica dello strumento elabora questa informazione per controllare la frequenza e l'ampiezza del suono emesso. Un suono talmente particolare, che varia dal violoncello-violino fino a raggiungere caratteristiche vocali, da essere stato utilizzato in numerose colonne sonore di vecchi film, tra cui La moglie di Frankenstein, Ultimatum alla Terra e Qualcuno volò sul nido del cuculo.
In questo tutorial, vedremo come costruire un semplice theremin che cambia l'intonazione in base alla distanza della mano da un sensore di prossimità ad infrarossi (come quello usato in questo vecchio articolo). In aggiunta si può facilmente variare la lunghezza del "beat" e far lampeggiare due o più LED contemporaneamente... è la magia del multi-threading, è la magia di VIPER!
A dispetto dell'apparente complessità, questo progetto richiede una elettronica molto semplice, in quanto il lavoro sporco lo fa VIPER, il nuovo software usato per programmare il theremin.
VIPER (acronimo di VIPER Is Python Embedded in Realtime) è una suite di sviluppo per il design di oggetti interattivi, pronti per il cloud e l'Internet delle Cose (Internet of Things, IoT). Con VIPER creativi, designers e professionisti possono sviluppare in Python per Arduino DUE, ST Nucleo, Particle Core/Photon e tutte le altre più famose piattaforme di prototipazione, usando i paradigmi e le features tipiche della programmazione ad alto livello.
DISCLAIMER
Sebbene VIPER sia una piattaforma di sviluppo professionale e performante, questo tutorial mostra come costruire un theremin non-professionale. Comunque, siamo abbastanza fiduciosi che otterrete risultati migliori di Sheldon 😀
Quindi, proseguiamo!
Step 1: Materiale necessario
Avrete bisogno di:
- 1 x sensore di prossimità ad infrarossi Sharp (GP2Y0A21YK)
- 2 x resistenze da 1 kΩ
- 2 x LED (possibilmente uno rosso e uno verde)
- 1 x piezo buzzer
- 1 x potenziometro rotativo
- 1 x breadboard
- un po' di cavetti jumper
- VIPER! Non importa che sistema operativo usiate, VIPER è cross-platform!
- Arduino DUE o una ST Nucleo o una Particle (conosciuta precedentemente come Spark) Core o Photon. Non importa quale scheda usiate, VIPER è multi-board! Potete trovare tutte le board attualmente supportate in questa sezione della documentazione di VIPER.
Step 2: Assembla il circuito
- Un sensore Sharp IR ha 3 pin. Uno serve per l'alimentazione, che nel nostro caso è la 3.3 V. Un altro è per la massa, che connetteremo al pin GND. Infine, c'è un output analogico che varia da 3.1 V a 0.4 V (che corrispondono a distanze di 10 e 80 cm). Questo pin deve essere collegato ad un pin di input analogico della board. Nel nostro caso, useremo il pin A5.
- Il piezo buzzer usa uno speciale cristallo che si espande e si contrae in base al segnale elettrico che lo attraversa. Questo genera un suono che possiamo udire. Un pin del buzzer va a massa (GND) mentre l'altro va collegato ad un pin digitale. Nel nostro caso useremo il D7 (o un altro pin con PWM se si usa lo Spark Core, come ad esempio A4).
- Un potenziometro rotativo ha 3 pin. Connetti un pin esterno a 3.3V e l'altro pin esterno a GND. Il pin centrale avrà quindi un potenziale che varierà da 0 V a 3.3 V in relazione alla rotazione applicata. Questo pin deve essere collegato ad un pin di input analogico della board. Nel nostro caso, useremo il pin A2.
- Per costruire il circuito per i LED, connetti una estremità della resistenza al pin D8 (o D7 su Spark Core). Connetti il terminale più lungo del LED (il polo positivo, chiamato anodo) all'altra estremità della resistenza. Connetti il terminale più corto del LED (il polo negativo, chiamato catodo) a massa (GND).
Step 3: Programma la board con VIPER
Usare VIPER è molto semplice! Vediamo come fare:
- Scarica l'installer per Windows, Linux o iOS dalla pagina di download di VIPER (potrebbero apparire dei messaggi di alert, per favore accetta il "rischio" e vai avanti, è un falso allarme e verrà risolto il prima possibile).
- Installalo (ecco un breve tutorial su come installare VIPER) e lancia l'applicazione tramite l'icona apparsa sul desktop.
- Crea un utente VIPER attraverso il pulsante dedicato in alto a destra. Controlla la tua mail e verifica il tuo nuovo account cliccando sull'apposito link. Perchè registrarsi? Con un account VIPER puoi: partecipare alla VIPER community; salvare i tuoi progetti on-line nel VIPER Cloud; ricevere automaticamente gli aggiornamenti!
- Connetti la tua board e rinominala come preferisci in modo da poterla riconoscere facilmente in futuro!
- Per rendere la board usabile, bisogna Viperizzarla, cioè installare su di essa la VIPER VM (Virtual Machine), attraverso l'apposito pulsante nella topbar del VIPER IDE.
- Crea un nuovo progetto, copia il codice che trovi su github, compila lo script e caricalo nella board!
Step 4: Spiegazione del codice
Perchè usare VIPER
Uno dei concetti più difficili da comprendere per chi si avvicina alla programmazione embedded è come gestire diversi task contemporaneamente, cioè come creare una sorta di multitasking. Gli sviluppatori sono spesso frustrati dalle difficoltà incontrate nell'implementazione di questa funzionalità nei microcontrollori.
Per risolvere questi problemi, VIPER supporta gran parte delle features di alto livello di Python, in particolare il multithreading, ma anche moduli, classi, callbacks, timers ed eccezioni, più alcune particolari features relative all'hardware come interrupts, PWM, digital I/O, ecc.
Ogni thread in VIPER è una sorta di processo parallelo che funziona autonomamente sulla board. Per eseguire un thread è necessario definire una funzione di input, che può essere istanziata da vari threads dando la possibilità di scrivere codice molto conciso e riutilizzabile. Più info qui.
Inside the code
Lo script è implementato usando 4 threads che funzionano in parallelo. Un thread istanzia la funzione sampling() che converte e normalizza i segnali analogici acquisiti attraverso un potenziometro e un sensore di prossimità a IR. Due threads sono usati per instanziare una generica funzione di blink() che fa lampeggiare due LED a differenti frequenze. Un altro thread istanzia una generica funzione buzz() che fa suonare un buzzer a differenti frequenze e durata dello sleep (per creare un effetto "beat"), calcolati sulla base dei segnali analogici acquisiti.
Il codice è molto intuitivo e ha un bel po' di commenti che vi aiuteranno a capirne tutti i dettagli. Mi dilungo solo un altro po' per descrivere due aspetti fondamentali e innovativi di VIPER.
1. delay() vs sleep()
In Arduino/Wiring usare la funzione delay() ha un effetto collaterale: interrompe il ciclo di esecuzione di uno "sketch" per il numero di millisecondi assegnato come argomento. Cioè Arduino letteralmente si blocca e non rileva alcun input così come non invia alcun output!
In VIPER la funzione sleep() sospende il thread corrente MA tutti gli altri threads continuano ad essere eseguiti!
2. VIPER built-in functions
La VIPER Virtual Machine estende Python con delle funzioni particolari (built-in functions) in grado di gestire i pin di Input e Output dei microcontrollori. Queste funzioni ricordano quelle tipiche del linguaggio Arduino, ma sono più flessibili. Vediamone alcune:
analogRead() vs adc.read()
La funzione analogRead() è fornita come built-in per facilitare il passaggio da Arduino/Wiring a VIPER.
Comunque, la sintassi preferibile per leggere i valori dai pin analogici in VIPER è:
# import the adc driver
import adc
x = adc.read(pin, samples=1)
Se "samples" è uguale a 1 (o non espresso), la funzione ritorna il valore intero letto sul pin. Se "samples" è maggiore di 1, ritorna una tupla () di interi con dimensione uguale a quella impostata.
analogWrite() vs. pwm.write()
La funzione analogWrite() di Arduino fornisce una semplice interfaccia per la gestione della PWM, impropriamente chiamata "analog output". In particolare, permette di variare il duty cycle dell'onda quadra ma non fornisce nessun controllo sul periodo dell'onda quadra. VIPER, invece, attraverso una sintassi molto semplice, permette di controllare sia il periodo che il duty cycle dell'onda.
Anche qui la funzione analogWrite() è fornita come built-in per facilitare il passaggio da Arduino/Wiring a VIPER. Tuttavia il modo migliore di usare il PWM in VIPER è:
# import the pwm driver
import pwm
pwm.write(pin, period, pulse, time_unit=MILLIS)
Lo stato del pin è periodicamente alternato tra LOW e HIGH in base ai parametri impostati. In particolare:
- "period" imposta la durata dell'onda quadra
- "pulse" imposta la durata del duty cycle
- "time_unit" imposta l'unità di misura di "period" e "pulse"
Step 5: Divertiti!
- aggiungere un controllo del volume
- usare la smartSensors library invece di mappare l'input analogico "a mano"
Sentitevi liberi di suggerire le vostre idee, e divertitevi ad infastidire la gente con il vostro nuovo theremin!
PARTECIPA AL VIPER-PRIZE!
Infine vi ricordo che sono aperte le iscrizioni per partecipare al workshop gratuito: Interaction design ed IoT: sviluppare oggetti interattivi con VIPER! Avrà luogo Sabato 25 luglio 2015 dalle 14:00 alle 18:30 presso il FabLab Firenze, in via Renato Fantoni 8.
Iscrivendoti potrai partecipare al #VIPERprIZE!
Regolamento:
- crea un progetto usando VIPER
- caricalo su Hackster.io (https://www.hackster.io/viper)
- presentalo durante il workshop
Riceverai gratuitamente TOIshield, uno shield multi-sensor compatibile con le più famose board di prototipazione!
Ti aspettiamo!
Luigi F. Cerfeda (@L_F_Cerfeda) - VIPER team
Articolo originale su Instructables (in inglese)

Complimenti per l’articolo, ben strutturato e argomento interessante. Ho realizzato diversi progetti con Phyton ma non ero a conoscenza di VIPER; mi hai incuriosito, lo voglio provare 😉
Ciao Ernesto, ti ringrazio! Oggi è il giorno giusto per provare VIPER: è stato appena rilasciato un update importante… più info qui http://www.viperize.it/blog/update-0-2-0-0007-is-out/
errata corrige: Python 🙂
GRAZIE per avermi fatto scoprire VIPER!
VIVA VIPER! 🙂
Ciao.
Grazie per avermi fatto conoscere Viper
Molto interessante usare un tools che si può usare su diverse piattaforme..
Ho visto che Viper per Windows vuole il sistema a 64 bit.. nulla a 32?
Come sono le prestazioni rispetto a Wiring classico?
Grazie
Ciao Francesco, scusa per ti rispondo solo ora.
La versione a 32 bit è in programma, c’è da aspettare ancora un po’.
In linea generale VIPER è altamente ottimizzato perchè fa fare all’hardware quasi tutto il lavoro. Fare un confronto di prestazioni con il Wiring è abbastanza complicato, .ma stiamo lavorando su una serie di articoli tecnici di benchmarking che usciranno a breve.
Stay tuned 😀
Ok!!
L’argomento mi interessa non poco!! Per le novità ti aspetto su questo sito.
Buone vacanze.. ed a presto
Ciao!
Per chi fosse interessato, è da poco uscito un update di VIPER con tante nuove features, tra cui la VIPER APP! http://bit.ly/ViperApp
Una volta installata, la VIPER APP agisce come interfaccia per tutti i dispositivi “viperizzati” che si trovano in rete (Wifi o Bluetooth), che possono quindi inviare o ricevere dati da essa.
Nota tecnica: per programmare una interfaccia tramite la Viper App non è necessario conoscere la programmazione Android!
Le interfacce, infatti, sono basate su semplici template HTML 5 e Javascript che possono essere scritti direttamente nel VIPER IDE e poi sono automaticamente trasferiti nel microcontrollore insieme al bytecode python. Questo poi viene trasferito alla VIPER APP che farà magicamente apparire l’interfaccia utente desiderata.
Più info qui: http://www.viperize.it/blog/viper-0-2-0-0008-is-out-get-the-viper-app/
Per chi verrà al Maker Faire Rome, VIPER sarà allo stand G22 (http://on.fb.me/1GdenZT)
Vi aspettiamo!
Nel frattempo date uno sguardo alle nuove demo: https://www.hackster.io/viper
Arduino M0 visto che è una versione più recente, ve bene lo stesso immagino. Giusto?
Ciao Orazio,
Arduino M0 potrebbe essere compatibile con VIPER, ma al momento non è ancora tra le board supportate. Più info qui: https://community.viperize.it/discussion/48/arduino-m0-pro
Ciao