Lab_interaccio/2019/Vermell/2_Vermell/2_Vermell.ino
2025-02-25 21:29:42 +01:00

732 lines
18 KiB
C++

#include <SPI.h>
#include <SD.h>
#include <Adafruit_VS1053.h>
#include <Wire.h>
#include "PCA9634.h"
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
#include "nRF24L01MOD.h"
#include "RF24MOD.h"
#include "printfMOD.h"
#define DEBUG 0
#define ID 1
#define VS1053_RESET -1 // VS1053 reset pin (not used!)
#define VS1053_CS 6 // VS1053 chip select pin (output)
#define VS1053_DCS 10 // VS1053 Data/command select pin (output)
#define CARDCS 5 // Card chip select pin
// DREQ should be an Int pin *if possible* (not possible on 32u4)
#define VS1053_DREQ 9 // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(VS1053_RESET, VS1053_CS, VS1053_DCS, VS1053_DREQ, CARDCS);
PCA9634 leds( 0x68 );
#define CE_PIN 19 // A5
#define CSN_PIN 18 // A4
int radioId;
uint32_t CMD[ 8 ]; // CMD + Ch + 2
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
const uint64_t pipes[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};
//int ch = 0x4C ; // 76 por defecto es el canal 76 (showroom)
Adafruit_LIS3DH lis = Adafruit_LIS3DH();
#define CLICKTHRESHHOLD 80
byte neopix_gamma[] = { // adaptada a este LED con el umbral en 13
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 17,
17, 17, 17, 17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20,
20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 26,
26, 26, 27, 27, 28, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33,
34, 34, 35, 35, 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 42, 43,
44, 44, 45, 46, 47, 47, 48, 49, 50, 51, 51, 52, 53, 54, 55, 56,
57, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72,
73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 85, 86, 87, 89, 90, 91,
93, 94, 95, 97, 98, 100, 101, 102, 104, 105, 107, 108, 110, 112, 113, 115,
116, 118, 120, 121, 123, 125, 126, 128, 130, 132, 133, 135, 137, 139, 141, 142,
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 171, 173, 175,
177, 179, 181, 184, 186, 188, 191, 193, 195, 198, 200, 202, 205, 207, 210, 212,
215, 217, 220, 222, 225, 228, 230, 233, 236, 238, 241, 244, 247, 249, 252, 255
};
// Globales LED
unsigned long delayed = 0; // control de tiempo de funciones de neon
unsigned long launchTime = 0;
int countFrame = 0;
short stroboFlag = 0;
short ledFlag = 0;
short stroboOn = 0;
int globalWhite = 0;
int selectedScene = 1;
unsigned char data;
unsigned long previousMillis;
int interval = 1000;
int compas;
bool fadeFlag = 0;
int pases;
const char* fx[] = {"fx1.mp3", "fx2.mp3", "fx3.mp3", "fx4.mp3", "fx5.mp3", "fx6.mp3", "fx7.mp3", "fx8.mp3",
"fx9.mp3", "fx10.mp3", "fx11.mp3", "fx12.mp3", "fx13.mp3", "fx14.mp3", "fx15.mp3", "fx16.mp3"};
const char* voz[] = {"voz1.mp3", "voz2.mp3", "voz3.mp3", "voz4.mp3", "voz5.mp3", "voz6.mp3", "orc2.mp3", "orc4.mp3" };
const char* piano[] = {"piano1.mp3", "piano2.mp3", "piano3.mp3"};
const char* orc[] = {"orc1.mp3", "orc2.mp3", "orc3.mp3", "orc4.mp3", "orc5.mp3"};
const char* pianomix[] = {"piano1.mp3", "piano2.mp3", "piano3.mp3", "voz1.mp3","voz4.mp3", "voz5.mp3", "voz6.mp3", "orc3.mp3", "orc1.mp3", "orc5.mp3"};
void resetBoard()
{
//Serial.println("reset");
NVIC_SystemReset(); // esta funcion en teoria si funciona en SAMD
}
void sceneRF( char num ) // Disparo DE ESCENA via Radio
{
if(DEBUG)
{
Serial.print("Scene RF received: ");
Serial.println(num);
}
if ( num == '1' )
{
selectedScene = 4; // TORMENTA
compas=0;
ledFlag = 0;
}
}
/// File listing helper
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
int16_t v = 0;
int8_t inc = 1;
void test_pwm()
{
for (int i = 0; i < 8; i++)
{
leds.set_brightness(i, 255);
delay(10);
}
delay(1000);
for (int i = 0; i < 8; i++)
{
leds.set_brightness(i, 13); // valor a partir del cual empieza a encenderse
delay(10);
}
}
void test_pwm_fade()
{
int i, r;
//Serial.print("Set brightness: ");
//Serial.println(v);
for (i = 1; i < 8; i++) {
r = leds.set_brightness(i, v);
//delay(2);
}
v = v + inc;
if ( inc > 0 && v >= 255) {
inc = -1;
} else if (inc < 0 && v <= 0) {
inc = 1;
}
// delay (1);
//delayMicroseconds(100);
}
void ledValue(byte white)
{
globalWhite = white;
int i, r;
//for (i = 4; i < 8; i++) {
r = leds.set_brightness(7, globalWhite);
//delay(2);
//}
}
void acel_click()
{
uint8_t click = lis.getClick();
if (click == 0) return;
if (! (click & 0x30)) return;
//Serial.print("Click detected (0x"); Serial.print(click, HEX); Serial.print("): ");
if (click & 0x10)
{
Serial.println("Single click");
selectedScene = 4;
ledFlag = 0;
compas = 0;
}
else if (click & 0x20)
{
Serial.println("Double click");
}
//Serial.println();
radio.stopListening();
data = '1'; // puede ser un random de estados agitados (diferentes sonidos) -> 4,5,6 (dejamos 1, 2, 3 para estatico)
Serial.println("stop listening");
radio.openWritingPipe(pipes[1]); // modo TRANSMITTER
radio.openReadingPipe(1, pipes[0]); // modo TRANSMITTER
radio.write( &data, sizeof(char) );
Serial.println(data);
radio.openWritingPipe(pipes[0]); // modo RECEIVER
radio.openReadingPipe(1, pipes[1]); // modo RECEIVER
radio.startListening();
Serial.println("Start listening...");
delay(100);
return;
}
void ledFade(int value, int fadeTime, int frameTime)
{
if ( millis() > delayed )
{
delayed = millis() + frameTime - 4 ; // compensacion de bloqueo de millis y otras latencias
float w;
float totalFrames = fadeTime / frameTime;
static byte startWhite;
byte endWhite = value;
if (!ledFlag)
{
launchTime = millis();
if (DEBUG)
{
Serial.print("fadeTime: ");
Serial.println(fadeTime);
Serial.print("LaunchTime: ");
Serial.println(launchTime);
Serial.print("totalFrames: ");
Serial.println(totalFrames);
}
countFrame = 0; // RESET DE VARIABLES ANTES DE ARRANCAR
ledFlag = true;
startWhite = globalWhite;
}
if (countFrame < totalFrames)
{
countFrame++;
w = map(countFrame * 255. / totalFrames, 0, 255, startWhite, endWhite);
globalWhite = w;
//Serial.print("w: ");
//Serial.println( w );
//Serial.println( neopix_gamma[(int)globalWhite] );
leds.set_brightness(7, neopix_gamma[(int)globalWhite]);
// int i,r;
// for (i=4; i<8; i++){
// r = leds.set_brightness(i, globalWhite);
// //delay(2);
// }
}
}
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
if (DEBUG)
{
while (!Serial) {
delay(1);
}
}
Serial.println("\n\nAdafruit VS1053 Feather Test");
if (! musicPlayer.begin()) { // initialise the music player
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
//while (1);
}
Serial.println(F("VS1053 found"));
musicPlayer.sineTest(0x44, 500); // Make a tone to indicate VS1053 is working
if (!SD.begin(CARDCS)) {
Serial.println(F("SD failed, or not present"));
//while (1); // don't do anything more
}
Serial.println("SD OK!");
// list files
printDirectory(SD.open("/"), 0);
// Set volume for left, right channels. lower numbers == louder volume!
musicPlayer.setVolume(1, 1);
musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); // DREQ int
Serial.println("\n\nNRF24 Feather Test");
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.setPALevel( RF24_PA_MAX );
radio.setAutoAck(0);
radio.setPayloadSize(8);
radio.setChannel(76);
radio.openWritingPipe(pipes[0]); // modo RECEIVER
radio.openReadingPipe(1, pipes[1]); // modo RECEIVER
radio.printDetails();
radio.startListening();
Wire.begin();
Wire.setClock(100000);
leds.begin( );
Serial.println("LIS3DH test!");
if (! lis.begin(0x18)) { // change this to 0x19 for alternative i2c address
Serial.println("Couldnt start");
//while (1);
}
Serial.println("LIS3DH found!");
lis.setRange(LIS3DH_RANGE_2_G); // 2, 4, 8 or 16 G!
lis.setClick(2, CLICKTHRESHHOLD);
Serial.print("Range = "); Serial.print(2 << lis.getRange());
Serial.println("G");
randomSeed(analogRead(0));
if (DEBUG)
{
Serial.println(F("Playing Brian Eno"));
musicPlayer.startPlayingFile("/brian.mp3");
}
}
void loop()
{
///////////////////////////// SERIAL /////////////////////////////
if (Serial.available()) {
char c = Serial.read();
///////////// EFFECT //////////////////
if ( c == '0')
selectedScene = 0; // CMD 0 = off
else if ( c == '1')
{
selectedScene = 1;
ledFlag = 0;
compas = 0;
}
else if ( c == '2')
{
selectedScene = 2;
ledFlag = 0;
compas = 0;
}
else if ( c == '3')
{
selectedScene = 3;
ledFlag = 0;
compas = 0;
}
else if ( c == '4')
{
selectedScene = 4;
ledFlag = 0;
compas = 0;
}
else if ( c == '5')
{
selectedScene = 5;
ledFlag = 0;
compas = 0;
}
else if ( c == '6')
{
selectedScene = 6;
ledFlag = 0;
compas = 0;
}
else if ( c == '7')
{
selectedScene = 7;
ledFlag = 0;
compas = 0;
}
else if ( c == '8')
{
selectedScene = 8;
ledFlag = 0;
compas = 0;
}
}
///////////////////////////// EFFECTS /////////////////////////////
switch (selectedScene)
{
case 0 : { // OFF - no parameters
break;
}
case 1 : { // MODO RELAX 1 (voces + orc)
if (millis() > previousMillis + interval - 290 ) // 32000 -> 32 compases a 120 bpm + COMPENSACION RETARDO
{
previousMillis = millis();
if (DEBUG)
{
Serial.print("compas: ");
Serial.println(compas);
}
if(compas == 0)
{
ledFade( 255, 1000, 16);
if(!musicPlayer.stopped())
musicPlayer.stopPlaying();
int randomAudio = random(8);
//Serial.println(voz[randomAudio]);
musicPlayer.startPlayingFile(voz[randomAudio]); // play sample aleatorio cada 8 compases
}
if(!compas % 8 == 0)
{
fadeFlag = !fadeFlag;
ledFlag = 0;
}
compas++;
if (compas > 31)
{
compas = 0;
pases++;
}
if( pases > 4)
{
pases = 0;
selectedScene = random(3)+1;
//Serial.print("random ");
//Serial.println(selectedScene);
}
}
if(!musicPlayer.stopped())
{
if(fadeFlag)
ledFade( 150, (interval-290), 16);
else
ledFade( 255, (interval-290), 16);
}
else
ledFade( 0, (interval-290)*2, 16);
break;
}
case 2 : { // MODO RELAX 2 pianomix
if (millis() > previousMillis + interval - 290 ) // 32000 -> 32 compases a 120 bpm
{
previousMillis = millis();
if (DEBUG)
{
Serial.print("compas: ");
Serial.println(compas);
}
if(compas == 0)
{
ledFade( 255, 1000, 16);
if(!musicPlayer.stopped())
musicPlayer.stopPlaying();
int randomAudio = random(10);
//Serial.println(pianomix[randomAudio]);
musicPlayer.startPlayingFile(pianomix[randomAudio]); // play sample aleatorio cada 8 compases
}
if(!compas % 8 == 0)
{
fadeFlag = !fadeFlag;
ledFlag = 0;
}
compas++;
if (compas > 31)
{
compas = 0;
pases++;
}
if( pases > 4)
{
pases = 0;
selectedScene = random(3)+1;
//Serial.print("random ");
//Serial.println(selectedScene);
}
}
if(!musicPlayer.stopped())
{
if(fadeFlag)
ledFade( 150, (interval-290)*2, 16);
else
ledFade( 255, (interval-290)*2, 16);
}
else
ledFade( 0, (interval-290)*2, 16);
break;
}
case 3 : { // MODO RELAX 3 - PIANO SOLO
if (millis() > previousMillis + interval - 290 ) // 32000 -> 32 compases a 120 bpm
{
previousMillis = millis();
if (DEBUG)
{
Serial.print("compas: ");
Serial.println(compas);
}
if(compas == 0)
{
ledFade( 255, 1000, 16);
if(!musicPlayer.stopped())
musicPlayer.stopPlaying();
int randomAudio = random(3);
//Serial.println(pianomix[randomAudio]);
musicPlayer.startPlayingFile(pianomix[randomAudio]); // play sample aleatorio cada 8 compases
}
if(!compas % 8 == 0)
{
fadeFlag = !fadeFlag;
ledFlag = 0;
}
compas++;
if (compas > 31)
{
compas = 0;
pases++;
}
if( pases > 4)
{
pases = 0;
selectedScene = random(3)+1;
//Serial.print("random ");
//Serial.println(selectedScene);
}
}
if(!musicPlayer.stopped())
{
if(fadeFlag)
ledFade( 150, (interval-290)*2, 16);
else
ledFade( 255, (interval-290)*2, 16);
}
else
ledFade( 150, (interval-290)*2, 16);
break;
}
case 4 : { // MODO TORMENTA 1
//if (millis() > previousMillis + interval - (32-compas)*30 ) // 8000 -> 8 compas a 120 bpm
if (millis() > previousMillis + interval - 290 ) // 8000 -> 8 compas a 120 bpm
{
previousMillis = millis();
if (DEBUG)
{
Serial.print("compas: ");
Serial.println(compas);
}
//musicPlayer.stopPlaying();
int _random = random(100);
//Serial.print("random: ");
//Serial.println(_random);
if ((_random) > compas*4) // prob decreciente en %
{
if(!musicPlayer.stopped())
musicPlayer.stopPlaying();
ledValue(255);
ledFlag = 0;
int randomAudio = random(16);
//Serial.println(fx[randomAudio]);
musicPlayer.startPlayingFile(fx[randomAudio]); // play sample aleatorio cada 8 compases
}
compas++;
if (compas > 31)
{
compas = 0;
selectedScene = random(3)+1; //Latido OFF no sincroniza bien
if (DEBUG)
{
Serial.print("random ");
Serial.println(selectedScene);
}
break;
}
}
ledFade( 0, interval*4, 16);
break;
}
case 5 : { //MODO PULSACION
if (millis() > previousMillis + interval - 290 ) // 8000 -> 8 compas a 120 bpm
{
previousMillis = millis();
if (DEBUG)
{
Serial.print("compas: ");
Serial.println(compas);
Serial.print("compas%4: ");
Serial.println(compas%4);
}
if ( ( compas%2 == 0) && (compas<30))
{
if(!musicPlayer.stopped())
musicPlayer.stopPlaying();
ledValue(255);
ledFlag = 0;
//Serial.println("pulso.mp3");
musicPlayer.startPlayingFile("corazon.mp3"); // play sample aleatorio cada 8 compases
}
else if(( compas%1 == 0) && (compas<30) )
{
ledValue(255);
ledFlag = 0;
}
compas++;
if (compas > 31)
{
compas = 0;
selectedScene = random(3)+1;
}
}
ledFade( 0, (interval-290)*2, 16);
}
break;
}
///////////////////////////// RADIO RX /////////////////////////////
if ( radio.available() )
{
while (radio.available())
{
radio.read( CMD, sizeof(CMD) );
sceneRF(CMD[0]);
//musicPlayer.startPlayingFile("/miles.mp3");
//Serial.println("playing miles");
if (DEBUG)
{
Serial.println("Got command");
for (int i = 0 ; i < 8 ; i++)
{
Serial.print(CMD[i]);
Serial.print(",");
}
Serial.println();
}
}
}
///////////////////////////// ACELEROMETRO /////////////////////////////
acel_click();
}