BIO-Sound machine

Il mondo vegetale è un mondo inanimato oppure ha un’anima?
Non solo le piante hanno vita, costituendo la maggioranza delle forme viventi sul pianeta, ma presentano, tra le altre caratteristiche, gli stessi segnali elettrici che controllano il corpo umano.

BIO-Sound machine è uno strumento che trasforma le variazioni di queste caratteristiche elettriche dei Bio-organismi, come la conduttività elettrica,  in generazione di suoni.
Il programma informatico acquisisce i dati dei sensori attraverso un circuito elettronico progettato, e restituisce i comandi delle note musicali ad un sintetizzatore controllato secondo il protocollo MIDI (Musical Instruments Digital Interface), avvalendosi della tecnologia Arduino.

Il progetto nasce all’interno del nostro Istituto per la Didattica e l’Educazione Ambientale, oltre che per la sensibilizzazione delle persone verso la vita del mondo vegetale.

BIO Organismi: le Piante

Recenti studi scientifici hanno confermato il fatto che le piante, pur non potendosi muovere (sono Sessili), hanno una personalità e percepiscono l’ambiente attraverso una quindicina di sensi, oltre ai 5 che abbiamo anche noi, e sono in grado di sentire la Gravità, i Campi Elettromagnetici, l’Umidità e svariati altri Gradienti Chimici.
Esse non hanno organi unici come accade agli animali, ma diffusi in tutto il loro corpo e sono collegati tra loro da una struttura a rete non diversa da Internet.
Possono comunicare tra loro e con altri esseri viventi, come gli insetti, e sono in grado di produrre ultrasuoni quando sono stressate.
Inoltre è studiato che i segnali elettrici che controllano il corpo umano sono presenti anche nelle piante, sebbene queste non abbiano neuroni.

Come gli altri esseri viventi si scambiano informazioni e interagiscono, adottano strategie per la sopravvivenza, hanno una vita sociale, sfruttano al meglio le risorse energetiche.
Hanno cioè una propria intelligenza e sono capaci di scegliere, imparare e ricordare.

Hanno anche una Intelligenza di Sciame, che permette loro di comportarsi e reagire non come singole unità ma come comunità intera, un po’ come certe specie di uccelli e insetti.
[Greg Gage – Stefano Mancuso].

Le Piante ed il mondo vegetale costituisce il 97% delle forme di vita sul pianeta Terra, contro il 3% costituito dal Regno Animale (2/3 del quale sono insetti).
L’Uomo ne costituisce solo lo 0,01%.
E’ stato però capace di portare all’estinzione dell’83% dei mammiferi esistenti e del 50% delle specie Vegetali.

Da un punto di vista della Biomassa presente sulla Terra le Piante costituiscono l’83% del peso delle forme viventi, i Batteri il 13% ed il Regno Animale solo il 5%.
Tutti gli uomini del pianeta hanno un peso minore dei Virus o dei Vermi!

Tutto questo ci dovrebbe indurre a rivalutare la considerazione che abbiamo di noi genere umano..

La vita segreta delle piante è probabilmente molto più ricca e complicata di quanto pensiamo e oggi siamo solo all’inizio dell’esplorazione scientifica di questo affascinante campo di studio.

BIO Sound Machine

Con la curiosità di chi vuole esplorare l’argomento, abbiamo cercato attraverso il progetto BIO Sound Machine, di capire come fosse possibile dar loro voce utilizzando sensori che traducono alcuni dei loro propri processi biologici in musica.
Processi biologici come quello della fotosintesi o del movimento dei liquidi all’interno della pianta durante il processo di cavitazione, in cui le bolle d’aria vengono aspirate attraverso il corpo della pianta, specialmente quando l’acqua è scarsa.
Come tutti gli organismi viventi, le piante subiscono variazioni di resistenza elettrica dovute a questi fattori, tra cui importantissimi stati fisiologici ed emozionali.
Le piante sono delle grandi antenne, dei ricettori sensibilissimi, esse captano dall’ambiente moltissime variazioni energetiche fisiche (ad esempio campi elettromagnetici statici e variabili..).

Il suono che sentiamo come musica attraverso BIO Sound non è il suono naturale delle piante, ma viene generato attraverso un circuito elettronico, il programma informatico che controlla ed elabora i dati captati dai sensori ed un sintetizzatore di suoni.

BIO Sound per l’Educazione Ambientale e la Didattica

Il progetto BIO Sound nasce dall’esigenza di sensibilizzare alla conoscenza ed al rispetto del mondo vegetale, e della vita in generale, da parte delle persone, in modo speciale i bambini.
La sua capacità di emozionare è in grado di condurci in una realtà che molto spesso ignoriamo, perchè celata ai nostri occhi.
Scoprire la vitalità delle piante, che grazie a BIO Sound può arrivare ai nostri sensi, è una forma di educazione ambientale che rafforza il rispetto.

La possibilità di interazione a livello emozionale, e non solo in quello della sfera cognitiva, lo rende un mezzo per aprire canali di comunicazione con persone che presentano difficoltà cognitive e comportamentali.

Le sue implicazioni didattiche sono nell’ambito della Musica e delle Scienze, ed accompagna il bambino alla scoperta di sé e dell’altro.
Altro che in questo caso contempla anche il mondo delle piante.

Proposta laboratorio: Il_Suono_delle_PianteDownload

Il Circuito Elettronico

Il circuito elettronico realizzato per il progetto è passato attraverso varie fasi di sviluppo con la creazione di successivi prototipi ai quali si sono aggiunte via via varie funzionalità.

BIO Sound v1
BIO Sound v2
BIO Sound v3
BIO Sound v4

La sezione di ingresso, realizzata con integrato Timer555, ha la funzione di convertire la conduttività elettrica tra foglia e foglia o tra terreno e foglia, rilevata attraverso sensori elettrici adesivi di uso medicale, in un segnale elettronico digitale di frequenza proporzionale ad essa.
Tale frequenza determina la lunghezza dell’impulso (semiperiodo alto) che viene letta in ingresso da Arduino utilizzando la funzione pulseIn(), che restituisce questo valore in mS.

Sulla base della variazione di questi valori rilevati attraverso i sensori collegati all’ingresso del circuito è stato impostato tutto il programma per la generazione del suono MIDI.

Nello schema circuitale sono stati inseriti in ingresso ad Arduino anche tre potenziometri ed un selettore a 12 posizioni, per poter manipolare da programma le modalità di generazione del suono.

Schema elettronico versione2
Schema elettronico versione2

La versione 4 di BIO Sound prevede, oltre al circuito elettronico ed Arduino, che costituiscono il modulo di generazione delle note, anche l’utilizzo di un microcomputer Raspberry sul quale è installato il sintetizzatore FluidSinth, rendendo quindi lo strumento indipendente dall’utilizzo di un computer e dalla presenza della rete wifi.

Il Programma Arduino

L’algoritmo legge il valore della durata dell’impulso generato dalla sezione di ingresso con Timer555, valore che è espresso in mS.
Questo valore che subisce continuamente piccole variazioni legate ai processi biologici viene memorizzato nei suoi valori minimi e massimi. Attraverso questi valori si effettua quindi una normalizzazione rispetto al valore minimo e massimo delle note che si vogliono riprodurre.
Questo significa che, sapendo che nel protocollo MIDI ogni nota delle ottave corrispondenti al campo audio è identificata da un numero che varia da 0 a 127, il range di variazione dell’impulso letto viene amplificato adattandolo a questi valori delle note. Quindi ogni variazione che genera un passaggio da una nota a quelle successive o precedenti può produrre la generazione di un valore MIDI.
Questo valore, insieme al valore della sua Velocity (intensità), viene quindi inviato sull’uscita MIDI con messaggi seriali secondo il protocollo.

Attraverso i potenziometri inseriti è possibile controllare i valori del Volume di uscita, della Soglia della variazione di generazione delle note e della Estensione delle ottave di generazione.
Il primo (colore Blu) imposta il valore della Velocity tra 0 e 127 determinando il volume di uscita.
Il controllo della Soglia (colore Bianco) imposta invece il valore oltre il quale la variazione del segnale prodotto in ingresso generi la nota.
Il valore prodotto dal potenziometro della Estensione delle ottave (colore Arancione) modifica i valori MIDI minimo e massimo nella normalizzazione per la generazione in base alle variazioni dovute al segnale di ingresso, modificando di fatto il numero di ottave entro il quale questa generazione avviene, da un massimo di 9 ad un minimo di una (quella centrale).

Con il pulsante BTN1 viene selezionata la produzione della nota singola o della sua triade maggiore, mentre con BTN2 si possono selezionare i modi Cromatico, Maggiore, Minore o Minore Diatonico entro i quali generare le note.

Il programma gestisce inoltre la visualizzazione di queste impostazioni attraverso una serie di led.
I quattro led da 5mm indicano il modo scelto, mentre quelli da 3mm la tonalità (da sinistra da DO a SI, il led verde l’eventuale #).

Volendo utilizzare direttamente la porta USB di Arduino, che nella versione2 è un MEGA 2560, come uscita MIDI da collegare direttamente al Sintetizzatore per la riproduzione dei suoni, occorre, una volta caricato lo scheck, sostituire il Firmware nel processore della seriale della scheda con quello MIDI.
Per farlo si deve installare una applicazione DFU (Device Firmware Update) come ATMEL Flip e fare l’upload del firmware Arduino_MIDI. Per utilizzare l’applicazione DFU occorre prima di tutto cortocircuitare l’ingresso Reset2 di Arduino a GND (Pulsante DFU della scheda BIO Sound) e quindi collegare ATMEL Flip alla scheda selezionando USB (Ctrl+U), caricare il file del firmware e lanciare RUN.
Nel caso dobbiate apportare modifiche al programma Arduino dovete ripristinare il firmware originale a seconda della scheda utilizzata (Arduino UNO Rev3, Arduino MEGA 2560).

Listato programma:

/* BIOSound - Generazione MIDI con le piante (e non solo :)
 *  
 * Versione v3 .- 24 Maggio 2023
 * scheda: Arduino Mega 2560 
 * autore: Fabrizio Silvetti fabriziosilvetti.com
 * 
 * Collegamenti Arduino:
 *  -----------------------------------------------------
 *  pin 3,3v                        pin 13 -> SEL1 C
 *  pin 5v                          pin 12 -> SEL2 C#
 *  pin GND                         pin 11 -> SEL3 D
 *  pin GND                         pin 10 -> SEL4 D#
 *  pin Vin                         pin 9 -> SEL5 E
 *  pin A0 -> BTN1                  pin 8 -> SEL6 F
 *  pin A1 -> BTN2                  pin 7 -> SEL7 F#
 *  pin A2 -> SEL12 B               pin 6 -> SEL8 G
 *  pin A3 -> EST_OTT               pin 5 -> SEL9 G#
 *  pin A4 -> VOLUME                pin 4 -> SEL10 A
 *  pin A5 -> SOGLIA                pin 3 -> SEL11 A#
 *  pin A6                          pin 2 -> IN_555
 *  pin A7                          pin 1 -> MIDI_OUT
 *  pin A8 -> LED_BLUE              pin 0
 *  pin A9 -> LED_RED               pin 14 -> LED_TON_#
 *  pin A10 -> LED_YELLOW           pin 15 -> LED_TON_C
 *  pin A11 -> LED_GREEN            pin 16 -> LED_TON_D
 *  pin A12                         pin 17 -> LED_TON_E
 *  pin A13                         pin 18 -> LED_TON_F
 *  pin A14                         pin 19 -> LED_TON_G
 *  pin A15                         pin 20 -> LED_TON_A
 *                                  pin 21 -> LED_TON_B
 *  -----------------------------------------------------                            
 * 
 * Il programma legge la durata impulso (proporzionale alla freq 
 * dell'astabile con 555) generato dalla variazione della impedenza in ingresso.
 * Normalizzato ai suoi valori Max e min, viene utilizzato per la creazione delle note.
 * Nella creazione note si tiene conto di:
 * - estensione ottave (scelto con pot Arancio, 1 - 9)
 * - tonalità (scelta con selettore Rosso, C, C#, D, D#, E, F, F#, G, G#, A, A#, B)
 * - modo (scelta con BTN2, Chromatic, Major, Minor, Minor Diatonic)
 * - histeresi (scelta con pot Bianco, 0 - 50, e utilizzata come variazione minima dalla nota precedente per creazione nota)
 * - volume (scelto con pot Blu, 0 - 127)
 * Le note vengono create in MIDI, dove nota==1 -> C0(16Hz) e nota==127 -> B9(8350Hz).
 * Con BTN1 vengono creati accordi Maggiori sulla nota.
*/
  
const byte btn1Pin = A0; //btn1 Polifonia
const byte btn2Pin = A1; //btn2 Tonalità
const byte volPin = A5; //pin pot volume
const byte histPin = A3; //pin pot Histeresi (soglia)
const byte octPin = A4; //pin pot Estensione Ottave
const byte in_555 = 2; //pin collegato all'Out del 555
//leds scala scelta
const byte led_blue_chrom = A8; //scala Chromatica 
const byte led_red_mag = A9; //scala Maggiore 
const byte led_yellow_min_dia = A10; //scala Minore Diatonica 
const byte led_green_min= A11; //scala Minore 
//leds tonalità
const byte led_diesis = 14; 
const byte led_C = 15;
const byte led_D = 16;
const byte led_E = 17;
const byte led_F = 18;
const byte led_G = 19;
const byte led_A = 20;
const byte led_B = 21;

/* Selettore tonalità
 * ------------------
 * ton    seq_in_Ard
 * C      011111111111
 * C#     101111111111
 * D      110111111111
 * D#     111011111111
 * E      111101111111
 * F      111110111111
 * F#     111111011111
 * G      111111101111
 * G#     111111110111
 * A      111111111011
 * A#     111111111101
 * B      111111111110
 */
const int C_pin = 3;
const int Cd_pin = 4;
const int D_pin = 5;
const int Dd_pin = 6;
const int E_pin = 7;
const int F_pin = 8;
const int Fd_pin = 9;
const int G_pin = 10;
const int Gd_pin = 11;
const int A_pin = 12;
const int Ad_pin = 13;
const int B_pin = A2;
// ------------------

//Generazione nota con elaborazione_segnale()
unsigned long _pulse;
unsigned long maxSignal = 0;
unsigned long minSignal = 1000000;
int mediaSignal, deltaSignal, notaSignal;
int nota, nota_temp;
unsigned long loopMillis = 0;
bool btn_isPressed = false;

//Impostazione note MIDI
byte _channel = 1;  //setting channel to 11 or 12 often helps simply computer midi routing setups
byte _velocity = 0; // 0 -> 127
int _estensione_ottave;
int noteMin; //C0  - keyboard note minimum
int noteMax; //C7  - keyboard note maximum
int tonalita; // 1->C, 2->C#, 3->D, 4-D#, 5->E, 6->F, 7->F#, 8->G, 9->G#, 10->A, 11->A#, 12->B
int tipo_scala = 0; //Maggiore
int indice_nota;
int nota_base_tonalita[13];
//int nota_base_tonalita[13] = {0,60,61,62,63,64,65,66,67,68,69,70,71};
int scale[4][13] = {                // scale[tipo][nota]
  {12, 1,2,3,4,5,6,7,8,9,10,11,12}, //Chromatic
  {7, 1, 3, 5, 6, 8, 10, 12},       //Major
  {7, 1, 3, 4, 6, 8, 9, 11},        //DiaMinor
  //{7, 1, 2, 2, 5, 6, 9, 11},        //Indian
  {7, 1, 3, 4, 6, 8, 9, 11}         //Minor
};
//per test Serial
int ottave[8] = {0,1,2,3,4,5,6,7};
String note_ottave[8][13] = { //A4 = 440 Hz
  {"0","C0","C0#","D0","D0#","E0","F0","F2#","G0","G0#","A0","A0#","B0"}, //12->C0(16Hz) a 107->B7(3951Hz)
  {"1","C1","C1#","D1","D1#","E1","F1","F1#","G1","G1#","A1","A1#","B1"},
  {"2","C2","C2#","D2","D2#","E2","F2","F2#","G2","G2#","A2","A2#","B2"},
  {"3","C3","C3#","D3","D3#","E3","F3","F3#","G3","G3#","A3","A3#","B3"},
  {"4","C4","C4#","D4","D4#","E4","F4","F4#","G4","G4#","A4","A4#","B4"},
  {"5","C5","C5#","D5","D5#","E5","F5","F5#","G5","G5#","A5","A5#","B5"},
  {"6","C6","C6#","D6","D6#","E6","F6","F6#","G6","G6#","A6","A6#","B6"},
  {"7","C7","C7#","D7","D7#","E7","F7","F7#","G7","G7#","A7","A7#","B7"}
};

//utilizzo checkBattery
byte controlNumber = 80; //set to mappable control, low values may interfere with other soft synth controls!!
byte controlVoltage = 1; //output PWM CV on controlLED, pin 17, PB3, digital 11 *lowpass filter
long batteryLimit = 3000; //voltage check minimum, 3.0~2.7V under load; causes lightshow to turn off (save power)
byte checkBat = 1;
unsigned long previousMillis = 0;
unsigned long currentMillis = 1;
unsigned long batteryCheck = 0; //battery check delay timer

// utilizzo potenziometro creazione isteresi generazione nota
int _threshold; 
int threshMin = 0; 
int threshMax = 50; // valore max isteresi per esecuzione nota
int knobMin = 1;
int knobMax = 1023;

void setup()
{
  pinMode(btn1Pin, INPUT_PULLUP);
  pinMode(btn2Pin, INPUT_PULLUP);
  pinMode(histPin, INPUT);
  pinMode(volPin, INPUT);
  pinMode(in_555, INPUT);
  pinMode(C_pin, INPUT_PULLUP);
  pinMode(Cd_pin, INPUT_PULLUP);
  pinMode(D_pin, INPUT_PULLUP);
  pinMode(Dd_pin, INPUT_PULLUP);
  pinMode(E_pin, INPUT_PULLUP);
  pinMode(F_pin, INPUT_PULLUP);
  pinMode(Fd_pin, INPUT_PULLUP);
  pinMode(G_pin, INPUT_PULLUP);
  pinMode(Gd_pin, INPUT_PULLUP);
  pinMode(A_pin, INPUT_PULLUP);
  pinMode(Ad_pin, INPUT_PULLUP);
  pinMode(B_pin, INPUT_PULLUP);
  pinMode(led_blue_chrom, OUTPUT);
  pinMode(led_red_mag, OUTPUT);
  pinMode(led_yellow_min_dia, OUTPUT);
  pinMode(led_green_min, OUTPUT);
  pinMode(led_diesis, OUTPUT);
  pinMode(led_C, OUTPUT);
  pinMode(led_D, OUTPUT);
  pinMode(led_E, OUTPUT);
  pinMode(led_F, OUTPUT);
  pinMode(led_G, OUTPUT);
  pinMode(led_A, OUTPUT);
  pinMode(led_B, OUTPUT);
  
  Serial.begin(31250);  //initialize at MIDI rate
  //Serial.begin(9600);  //for TEST 555
}

void loop()
{
  loopMillis = millis(); //controllo istante di ingresso loop
  //checkBattery(); //on low power, shutoff lightShow, continue MIDI operation

  while(millis() <= (loopMillis + 2000))
  {
    checkKnob(); // check isteresi potenziometro
    scelta_tonalita();
    //impostazione nota minima e massima (estensione ottave)//
    noteMin = nota_base_tonalita[1];                        //
    noteMax = noteMin + (12 * _estensione_ottave);          //
    elaborazione_segnale(); // elaborazione nota
    creazione_nota();
  }
  //Reset valori maxSignal e minSignal
  maxSignal = 0;
  minSignal = 1000000;
}

void elaborazione_segnale() {
  _pulse = pulseInLong(in_555,HIGH); //for TEST 555
  // determinazione delta SignalIn
  if(_pulse > maxSignal) maxSignal = _pulse;
  if(_pulse < minSignal) minSignal = _pulse;
  deltaSignal = maxSignal - minSignal;
  mediaSignal = (maxSignal + minSignal) / 2;
  notaSignal = _pulse - minSignal;
  nota =  map(notaSignal, 0, deltaSignal, noteMin, noteMax);
  if(nota < noteMin) nota = noteMin;
  if(nota > noteMax) nota = noteMax;
  /*
  Serial.print("nota = ");Serial.println(nota); //for TEST 555
  Serial.print("_pulse = ");Serial.println(_pulse);
  Serial.print("maxSignal = ");Serial.println(maxSignal);
  Serial.print("minSignal = ");Serial.println(minSignal);
  delay(500);
  */
}

void creazione_nota()
{
  if(nota >= (nota_temp + _threshold) || nota <= (nota_temp - _threshold))  //Isteresi note
    {
      //Serial.print("NOTA = ");Serial.println(nota);
      int base = nota_base_tonalita[tonalita]; // nota iniziale ottave
      int ottava = nota/12 - 1; // 0->C0, 1->C1, 2->C2, 3->C3, 4->C4, 5->C5, 6->C6, 7->C7
      int nota_ottava = (nota%12) + 1; // determino la nota all'interno dell'ottava
      lettura_scelta_scala();
      /*
      Serial.println("-----------------------------");
      Serial.print("base = ");Serial.println(base);
      Serial.print("nota = "); Serial.print(nota); Serial.print(" - "); Serial.println(note_ottave[ottava][nota_ottava]);
      Serial.print("ottava = "); Serial.println(ottava);
      Serial.print("nota_ottava = "); Serial.println(nota_ottava); 
      Serial.print("valori scala = ");
      */
      for(int i=1; i<=scale[tipo_scala][0]; i++) 
      { 
        /*
        Serial.print((scale[tipo_scala][i] - 1) + base); Serial.print(",");
        Serial.print((scale[tipo_scala][i] - 1) + base + 12); Serial.print(",");
        Serial.print((scale[tipo_scala][i] - 1) + base + 24); Serial.print(",");
        Serial.print((scale[tipo_scala][i] - 1) + base + 36); Serial.print(",");
        Serial.print((scale[tipo_scala][i] - 1) + base + 48); Serial.print(",");
        Serial.print((scale[tipo_scala][i] - 1) + base + 60); Serial.print(",");
        */
        // Verifico se la nota è nella tonalità
        if(nota == ((scale[tipo_scala][i] - 1) + base)
        || nota == ((scale[tipo_scala][i] - 1) + base + 12) 
        || nota == ((scale[tipo_scala][i] - 1) + base + 24) 
        || nota == ((scale[tipo_scala][i] - 1) + base + 36) 
        || nota == ((scale[tipo_scala][i] - 1) + base + 48) 
        || nota == ((scale[tipo_scala][i] - 1) + base + 60) 
        || nota == ((scale[tipo_scala][i] - 1) + base + 72) 
        || nota == ((scale[tipo_scala][i] - 1) + base + 84)) 
        {
          // creazione note
          
          midiSerial(144, _channel, nota, _velocity);
          if(!digitalRead(btn1Pin))  //creazione polifonia con BTN1
          {
            midiSerial(144, _channel+1, nota+5, _velocity); // 3 maggiore
            midiSerial(144, _channel+2, nota+8, _velocity); // 5 
            midiSerial(144, _channel+3, nota+10, _velocity); // 7 minore
          }
          //interruzione note precedentemente create
          else 
          {
            midiSerial(144, _channel+1, nota_temp+5, 0);
            midiSerial(144, _channel+2, nota_temp+8, 0);
            midiSerial(144, _channel+3, nota_temp+10, 0);
          }
          midiSerial(144, _channel, nota_temp, 0); 
          
          nota_temp = nota; //memorizzo valore precedente nota
          delay(50); // ?
          //Serial.println(""); Serial.print("NOTA = "); Serial.print(nota); Serial.print(" - "); Serial.println(note_ottave[ottava][nota_ottava]); // for TEST 555
          break;
        }
        else 
        {
          
          midiSerial(144, _channel, nota, 0);
          if(!digitalRead(btn1Pin))  //creazione polifonia con BTN1
          {
            midiSerial(144, _channel+1, nota+5, 0); // 3 maggiore
            midiSerial(144, _channel+2, nota+8, 0); // 5 
            midiSerial(144, _channel+3, nota+10, 0); // 7 minore
          }
          else 
          {
            midiSerial(144, _channel+1, nota_temp+5, 0);
            midiSerial(144, _channel+2, nota_temp+8, 0);
            midiSerial(144, _channel+3, nota_temp+10, 0);
          }
          
          //Serial.println("NOTA FUORI TONALITà -------------------");
        }
        //Serial.println("");
      }
    }
}

void scelta_tonalita()
{
  int _C = digitalRead(C_pin);
  int _Cd = digitalRead(Cd_pin);
  int _D = digitalRead(D_pin);
  int _Dd = digitalRead(Dd_pin);
  int _E = digitalRead(E_pin);
  int _F = digitalRead(F_pin);
  int _Fd = digitalRead(Fd_pin);
  int _G = digitalRead(G_pin);
  int _Gd = digitalRead(Gd_pin);
  int _A = digitalRead(A_pin);
  int _Ad = digitalRead(Ad_pin);
  int _B = digitalRead(B_pin);
  if(_C == 0) {
    tonalita = 1;
    digitalWrite(led_C, HIGH);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, LOW);
  }
  if(_Cd == 0) {
    tonalita = 2;
    digitalWrite(led_C, HIGH);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, HIGH);
  }
  if(_D == 0) {
    tonalita = 3;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, HIGH);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, LOW);
  }
  if(_Dd == 0) {
    tonalita = 4;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, HIGH);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, HIGH);
  }
  if(_E == 0) {
    tonalita = 5;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, HIGH);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, LOW);
  }
  if(_F == 0) {
    tonalita = 6;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, HIGH);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, LOW);
  }
  if(_Fd == 0) {
    tonalita = 7;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, HIGH);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, HIGH);
  }
  if(_G == 0) {
    tonalita = 8;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, HIGH);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, LOW);
  }
  if(_Gd == 0) {
    tonalita = 9;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, HIGH);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, HIGH);
  }
  if(_A == 0) {
    tonalita = 10;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, HIGH);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, LOW);
  }
  if(_Ad == 0) {
    tonalita = 11;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, HIGH);
    digitalWrite(led_B, LOW);
    digitalWrite(led_diesis, HIGH);
  }
  if(_B == 0) {
    tonalita = 12;
    digitalWrite(led_C, LOW);
    digitalWrite(led_D, LOW);
    digitalWrite(led_E, LOW);
    digitalWrite(led_F, LOW);
    digitalWrite(led_G, LOW);
    digitalWrite(led_A, LOW);
    digitalWrite(led_B, HIGH);
    digitalWrite(led_diesis, LOW);
  }
  //Serial.print("selettore = "); Serial.print(_C);Serial.print(_Cd);Serial.print(_D);Serial.print(_Dd);Serial.print(_E);Serial.print(_F);Serial.print(_Fd);Serial.print(_G);Serial.print(_Gd);Serial.print(_A);Serial.print(_Ad);Serial.println(_B);
  //Serial.print("tonalità = "); Serial.println(tonalita);
}

void lettura_scelta_scala() {
  //shift scala sul button release
  if(!digitalRead(btn2Pin)) btn_isPressed = true;
  if(digitalRead(btn2Pin) && btn_isPressed == true) 
  {
    btn_isPressed = false;
    tipo_scala ++;
    if(tipo_scala > 3) tipo_scala = 0;
  }
  if(tipo_scala == 0) 
  {
    digitalWrite(led_blue_chrom,HIGH);
    digitalWrite(led_red_mag,LOW);
    digitalWrite(led_yellow_min_dia,LOW);
    digitalWrite(led_green_min,LOW);
  }
  else if(tipo_scala == 1) 
  {
    digitalWrite(led_blue_chrom,LOW);
    digitalWrite(led_red_mag,HIGH);
    digitalWrite(led_yellow_min_dia,LOW);
    digitalWrite(led_green_min,LOW);
  }
  else if(tipo_scala == 2) 
  {
    digitalWrite(led_blue_chrom,LOW);
    digitalWrite(led_red_mag,LOW);
    digitalWrite(led_yellow_min_dia,HIGH);
    digitalWrite(led_green_min,LOW);
  }
  else if(tipo_scala == 3) 
  {
    digitalWrite(led_blue_chrom,LOW);
    digitalWrite(led_red_mag,LOW);
    digitalWrite(led_yellow_min_dia,LOW);
    digitalWrite(led_green_min,HIGH);
  }
  else 
  {
    digitalWrite(led_blue_chrom,LOW);
    digitalWrite(led_red_mag,LOW);
    digitalWrite(led_yellow_min_dia,LOW);
    digitalWrite(led_green_min,LOW);
  }
  //Serial.print("tipo_scala = "); Serial.println(tipo_scala);
}

void checkKnob() {
  //funzione lettura potenziometri 
  _velocity = analogRead(volPin);
  _threshold = analogRead(histPin);  
  _estensione_ottave = 1024 - analogRead(octPin);
  //set estensione_ottave
  if(_estensione_ottave < 114) {
    _estensione_ottave = 1;
    nota_base_tonalita[0] = 0;
    for(int i=60; i<72; i++) nota_base_tonalita[i-59] = i; //0,C4,C4#,D4,D4#,E4,F4,F4#,G4,G4#,A4,A4#,B4
    /*Serial.print("nota_base_tonalita[] = ");
    Serial.print(nota_base_tonalita[1]);
    Serial.print(nota_base_tonalita[2]);
    Serial.print(nota_base_tonalita[3]);
    Serial.print(nota_base_tonalita[4]);
    Serial.print(nota_base_tonalita[5]);
    Serial.print(nota_base_tonalita[6]);
    Serial.print(nota_base_tonalita[7]);
    Serial.print(nota_base_tonalita[8]);
    Serial.print(nota_base_tonalita[9]);
    Serial.print(nota_base_tonalita[10]);
    Serial.print(nota_base_tonalita[11]);
    Serial.println(nota_base_tonalita[12]);*/
  }
  else if(_estensione_ottave >= 114 && _estensione_ottave < 228) {
    _estensione_ottave = 2;
    nota_base_tonalita[0] = 0;
    for(int i=54; i<66; i++) nota_base_tonalita[i-53] = i; //0,F3#,G3,G3#,A3,A3#,B3,C4,C4#,D4,D4#,E4,F4
  }
  else if(_estensione_ottave >= 228 && _estensione_ottave < 352) {
    _estensione_ottave = 3;
    nota_base_tonalita[0] = 0;
    for(int i=48; i<60; i++) nota_base_tonalita[i-47] = i; //0,C3,C3#,D3,D3#,E3,F3,F3#,G3,G3#,A3,A3#,B3
  }
  else if(_estensione_ottave >= 352 && _estensione_ottave < 446) {
    _estensione_ottave = 4;
    nota_base_tonalita[0] = 0;
    for(int i=42; i<54; i++) nota_base_tonalita[i-41] = i; //0,F2#,G2,G2#,A2,A2#,B2,C3,C3#,D3,D3#,E3,F3
  }
  else if(_estensione_ottave >= 466 && _estensione_ottave < 580) {
    _estensione_ottave = 5;
    nota_base_tonalita[0] = 0;
    for(int i=36; i<48; i++) nota_base_tonalita[i-35] = i; //0,C2,C2#,D2,D2#,E2,F2,F2#,G2,G2#,A2,A2#,B2
  }
  else if(_estensione_ottave >= 580 && _estensione_ottave < 694) {
    _estensione_ottave = 6;
    nota_base_tonalita[0] = 0;
    for(int i=30; i<42; i++) nota_base_tonalita[i-29] = i; //0,F1#,G1,G1#,A1,A1#,B1,C2,C2#,D2,D2#,E2,F2
  }
  else if(_estensione_ottave >= 694 && _estensione_ottave < 808) {
    _estensione_ottave = 7;
    nota_base_tonalita[0] = 0;
    for(int i=24; i<36; i++) nota_base_tonalita[i-23] = i; //0,C1,C1#,D1,D1#,E1,F1,F1#,G1,G1#,A1,A1#,B1
  }
  else if(_estensione_ottave >= 808 && _estensione_ottave < 922) {
    _estensione_ottave = 8;
    nota_base_tonalita[0] = 0;
    for(int i=18; i<30; i++) nota_base_tonalita[i-17] = i; //0,F0#,G0,G0#,A0,A0#,B0,C1,C1#,D1,D1#,E1,F1
  }
  else {
    _estensione_ottave = 9;
    nota_base_tonalita[0] = 0;
    for(int i=12; i<24; i++) nota_base_tonalita[i-11] = i; //0,C0,C0#,D0,D0#,E0,F0,F0#,G0,G0#,A0,A0#,B0
  }
  //set threshold to knobValue mapping
  _velocity = map(_velocity, 0, 255, 127, 0);
  _threshold = map(_threshold, knobMin, knobMax, threshMax, threshMin);
  //Serial.print("_estensione_ottave = "); Serial.println(_estensione_ottave);
  //Serial.print("_velocity = "); Serial.println(_velocity);
  //Serial.print("_threshold = "); Serial.println(_threshold);
}

long readVcc() {  //https://code.google.com/p/tinkerit/wiki/SecretVoltmeter
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
}
void checkBattery(){
  //check battery voltage against internal 1.1v reference
  //if below the minimum value, turn off the light show to save power
  //don't check on every loop, settle delay in readVcc() slows things down a bit
 if(batteryCheck < currentMillis){
  batteryCheck = currentMillis+10000; //reset for next battery check
   
  if(readVcc() < batteryLimit) {   //if voltage > valueV
    //battery failure  
    if(checkBat) { //first battery failure
      //for(byte j=0;j
Risorse in rete: