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 secondo il protocollo MIDI (Musical Instruments Digital Interface).
Il progetto si avvale di una scheda elettronica progettata ad hoc e della tecnologia Arduino per ciò che concerne la manipolazione della grandezza rilevata attraverso i sensori e la generazione MIDI.

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 sterminare l’83% dei mammiferi esistenti ed il 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 del 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 un diverso approccio, come nel caso di BIO Sound Machine, è possibile dar loro voce utilizzando sensori che traducono alcuni dei loro propri processi biologici in musica tramite un sintetizzatore.
Processi biologici della fotosintesi e 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 (campi elettromagnetici statici e variabili..).

Naturalmente, le piante non producono direttamente la musica.
Il suono che sentiamo come musica, viene generato attraverso un sintetizzatore controllato dai segnali captati da sensori e trasformato in un concerto di piante, con la associazione e la elaborazione attraverso il coding informatico di queste variazioni con suoni artificiali.

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 v1
BIO Sound v2
BIO Sound v2
BIO Sound v3

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
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: