Lo sketch per l’Arduino con il Waveshield

Lo sketch per l’Arduino con il Waveshield

La scheda arduino con lo schemo Waveshield diventa un sistema che suona i file indicati nella stringa ricevuta tramite I2C. Preparate a parte una scheda Arduino con un piccolo sketch capace di inviare dati via I2C all’indirizzo 4 al quale risponde il sistema visibile in foto. Si noti che il waveshield non è montato sopra alla scheda arduino come si usa solitamante, ma è sistemata sotto e quindi la maggior parte dei fili che le uniscono servono per collegare i vari piedini che altrimenti si sarebbero innestati tra loro. Sotto il waveshield una piccola basetta con un transistor, una resistenza ed un relè che serve per alimentare l’amplificatore in basso. La sketch di seguito descritto porta ad uno un pin che attiva il rele qualche frazione di secondo prima di suonare il file wav secondo le istruzioni ricevute via I2C.

 

Il formato del comando da inviare al sistema tramite I2C è il seguente:

**xyz

che il sistema intepreta come comando valido (la presenza dei due **) e quindi suona il file xyz.wav contenuto nella scheda di memoria SD (es: il comando I2C **145 suona il file 145.wav)

Se riceve il numero di file 099 allora il sistema lo suona e lo rimette in coda al buffer in modo da suonarlo ripetutamente fino a che, non arrivi il numero file 098 che oltre ad essere suonato elimina tutte ricorrenze 99 nel buffer.
Il file 99 contiene un paio di toni di che ripetuta continamente produce l’effetto sirena di allarme. Una soluzione che permette di interrompere la sirena sempre al termine delle due tonalità e quindi senza l’effetto di brusca interruzione.

Il programma è una implementazione di uno sketch di base che si trova sul sito http://www.ladyada.net/make/waveshield/use.html.

E’ liberamente utilizzabile a patto di mantenere il nome dell’autore nei commenti iniziali.

/***********************************/
/*                                 */
/*  Written by Corrado Bevilacqua  */
/*                                 */
/***********************************/

//per la comunicazione sui pin 4 e 5 analogici di aruino. Wire è il nome che usa Arduino per lo standard I2C Bus
#include <Wire.h>
//funziona 19/05/2010
//domenica 16 maggio 2010 ok. Se il binary sketch supera circa 12000, 12500 byte, il wire non funziona.
//sabato 15 maggio 2010

//definizioni per il wave
// Funziona – i pin 2 3 4 5 e 10 poi 11 12 13
int numwave=0;
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include “WaveUtil.h”
#include “WaveHC.h”

SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the filesystem on the card
FatReader f; // This holds the information for the file wère play

WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time

char a9[8]=” ” ; //buffer di input per i2c
char wav0[10]; //stringa contenente il nomefile da suonare

int Vett_arrivo[90]; //vett con i valori in arrivo
// int Vett_suona[9]; //vett con i valori da suonare

int dim_vettore=89;
int e=0;

long old_millis=0;

boolean ampli_acceso = 0;

/*************************/
/*                       */
/*                       */
/*                       */
/*************************/
void sdErrorCheck(void)
{
if (!card.errorCode()) return;
putstring(“\n\rSD I/O error: “);
putstring(“, “);
while(1);
}

/*************************/
/*                       */
/*                       */
/*                       */
/*************************/
void setup() {
// byte i;
// set up serial port
Serial.begin(115200);
Serial.println(“File: PerArduinoConWaveShield_Slave_VersionFinale”);
putstring_nl(“WaveHC “);

// Set the output pins for the DAC control. This pins are defined in the library
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);

int i=0;

for (i = 0; i<=dim_vettore; i++)
{
Vett_arrivo[i] = 0;
}

// pin8 Accendo l’amplificatore
pinMode(8, OUTPUT);

// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn’t working for you
if (!card.init()) { //play with 8 MHz spi (default faster!)
putstring_nl(“Card init. failed!”); // Something went wrong, lets print out why
sdErrorCheck();
while(1); // then ‘halt’ – do nothing!
}

// enable optimize read – some cards may timeout. Disable if you’re having problems
card.partialBlockRead(true);

// Now we will look for a FAT partition!
uint8_t part;
for (part = 0; part < 5; part++) { // we have up to 5 slots to look in
if (vol.init(card, part))
break; // we found one, lets bail
}
if (part == 5) { // if we ended up not finding one 🙁
putstring_nl(“No valid FAT partition!”);
sdErrorCheck(); // Something went wrong, lets print out why
while(1); // then ‘halt’ – do nothing!
}

// Lets tell the user about what we found
putstring(“Using partition “);
putstring(“, type is FAT”);

// Try to open the root directory
if (!root.openRoot(vol)) {
putstring_nl(“Can’t open root dir!”); // Something went wrong,
while(1); // then ‘halt’ – do nothing!
}

//parte wire
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event

}

/*************************/
/*                       */
/*                       */
/*                       */
/*************************/
void loop()
{

display(10);

int k;
int i;
k=0;
//se ci sono dati allora ricevili
if (Wire.available() != 0)
{
//prendo tutta la stringa ricevuta e la metto in appo
while (Wire.available() != 0)
{
//Serial.print(“?”);
if (k<8)
{
a9[k]= Wire.receive();

Serial.print(a9[k]);

k=k+1;
}
}
//se ha due * allora lo prendo come file da suonare
if (a9[0]==’*’ && a9[1]==’*’ )
{
//ha due * per cui è un suono. Allora accendo subito l’amplificatore
//cerco la posizionedove scrivere nel vettore di arrivo

int appo=0;
appo=trovaaritroso();

Vett_arrivo[appo] = a9[2]*100 + a9[3]*10 + a9[4];

}
}

display(30);

Compatta();

display(50);
//prendi il file da suonare e rimpiazzalo con -1
i = -1;
int esci=0;
while (i < dim_vettore and esci == 0)
{
i = i + 1;
if (Vett_arrivo[i] > 0) //prendo il caso 0 e -1
{
esci = 1;
}
}

if (wave.isplaying == false)
{

if (Vett_arrivo[i] != 0) //prendo il caso 0 e -1
{

old_millis=millis(); //Memorizzo quando ho acceso l’amplificatore perspegenerlo dopo

int centinaia=0;
int decine=0;
int unita=0;
centinaia=(Vett_arrivo[i]-(Vett_arrivo[i] % 100))/100;
decine=(Vett_arrivo[i] % 100 – Vett_arrivo[i] % 10)/10;
unita= Vett_arrivo[i] % 10;

sprintf(wav0,”%d%d%d.wav”,centinaia,decine,unita);

//se devo suonare un wav ritardo di un seconso per aspettare che l’amplificatore si sia acceso bene. Però se è già acceso allora non ritardo.
if (ampli_acceso==0)
{
digitalWrite(8, 1); //accendi amplificatore
ampli_acceso = 1;

Serial.println(“ritardo”);
delay(1000);
}

Serial.println(wav0);
playfile(wav0);

}

if (Vett_arrivo[i] == 99)
{

int aa =0;
aa = trovaaritroso();
Vett_arrivo[aa] = 99;
//un giro per cancellare i 99
int trovato = 0;
for (aa = dim_vettore; aa>=1 ;aa–) //deve essere 1
{
if (Vett_arrivo[aa] == 99)
{
if (trovato == 1)
{
Vett_arrivo[aa] = -1;
}
else
{trovato = 1;}
}
}

}

int j =0;
if (Vett_arrivo[i] == 98)
{
for (j = 0; j<= dim_vettore; j++)
{
if (Vett_arrivo[j] == 99)
{
Vett_arrivo[j] = -1;
}
}
}

if (Vett_arrivo[i] != 0)
{Vett_arrivo[i] = -1;}

}
else
{
//Serial.println(“”);
//Serial.println(“Suona Suona”);
}
display(90);

//*************************************************************
e=e+1;

if (e<79)
{Serial.print(“.”);}
else
{Serial.println(“.”); e=0;}

if (wave.isplaying == false)
{
if (millis() – old_millis >5000) //se sono passati 5 secondi dall’accensione dell’amplificatore senza suoni allora spegnilo
{
digitalWrite(8, 0); //spegni amplificatore
ampli_acceso=0;
}
}
else
{
//se suona aggiorno oldmillis per garantire che si spenga dopo 5 sec dall’ultimo file suonato
old_millis=millis();
}

delay(20);

}

/*************************/
/*                       */
/*                       */
/*                       */
/*************************/
void playfile(char *name) {
// see if the wave object is currently doing something
if (wave.isplaying) {// already playing something, so stop it!
wave.stop(); // stop it
}

// look in the root directory and open the file
if (!f.open(root, name)) {
putstring(“Couldn’t open file “); Serial.print(name); return;
}

// OK read the file and turn it into a wave object
if (!wave.create(f)) {
putstring_nl(“Not a valid WAV”); return;
}

// ok time to play! start playback
wave.play();

}

//****************************************************************************************
// function that executes whenever data is received from master
// this function is registered as an event, see setup()

/*************************/
/*                       */
/*                       */
/*                       */
/*************************/
void Compatta ()
{
int i=0;
//sostituisce i meno due con 0
for (i = 0; i<=dim_vettore ; i++)
{
if (Vett_arrivo[i] <= -1)
{Vett_arrivo[i] = 0;}
}

//Ultimo pezzo 22-Nov-2010
//elimina i valori del vettore che sono vicini e doppioni
for (i = dim_vettore -1; i>=0 ; i–)
{
if (Vett_arrivo[i] == Vett_arrivo[i+1]) //se il l’elemeno i è uguale all’elemento i+1 allora metti in i+1 il valore zero
{Vett_arrivo[i+1] = 0;}
}

int esci=0;
int j=0;
while (esci == 0)
{
esci = 1;

for (j = 0; j<= dim_vettore – 1; j++)
{
if (Vett_arrivo[j] <= 0 and Vett_arrivo[j + 1] !=0) //’comprende 0 e anche il -1
{
Vett_arrivo[j] = Vett_arrivo[j + 1];
Vett_arrivo[j + 1] = 0;
esci = 0;
}
}
}
}

/*************************/
/*                       */
/*                       */
/*                       */
/*************************/
void display(int indicatore)
{
if (1==0) //lo faccio uscire subito e quindi non visualizza messaggi
{
int i=0;
// Serial.println(“”);
for (i = 0; i <= dim_vettore; i++)
{
if (Vett_arrivo[i] != 0 )
{
i=99;

}
}

i=99;
if (i>50)
{
Serial.print(“Rif.=”);
Serial.print(indicatore);

Serial.print(” Vett_arrivo=> “);
for (i = 0; i < dim_vettore; i++)
{
Serial.print(” “);Serial.print(i);Serial.print(“=”);Serial.print(Vett_arrivo[i]);
delay(5);
}
Serial.print(” “);Serial.print(dim_vettore);Serial.print(“=”);Serial.println(Vett_arrivo[dim_vettore]);

}

}
}

/*************************/
/*                       */
/*    Trova a Ritroso    */
/*          OK           */
/*************************/
int trovaaritroso()
{
//trovo la posizione del primo valore diverso da zero a partire dal fondo del vettore
int i =0 ;
int esci=0;
i = dim_vettore;
esci = 0;

while (i >= 0 and i <= dim_vettore and esci == 0)
{
if (Vett_arrivo[i] == 0 )
{
esci = 0;
}
else
{
esci = 1;
}
i = i – 1;
}

if (esci == 0)
{i = 0;}
if (esci == 1)
{i = i + 1 + 1; } //più 2 per trovare il primo libero
if (i >= dim_vettore)
{i = dim_vettore;} //se il vettore è pieno sovrascrivi sempre l’ultimo elemento
int g;
g=i;
return g;

}

void receiveEvent(int howMany)
{
}