Redesigning Sound

From Wikicliki
Jump to: navigation, search

Process

Tutorial with Yuri, 31 oct

  • surround haptics - sound / haptic / visual / feedback
  • usb sound output for playing back sounds

Guides / Tutorials / Gear

Interesting links

Brainstorming, 31 oct

Bucket of links

Tutorial with Mike, 1 nov

  • Recommended to use triple axis accelerometer - ADXL362 - already has arduino library written for it
  • accelerometer only measures acceleration. think of acceleration in terms of integration, velocity, position...
  • with regards to printing our own pcb - can do laser cut or acetate / pcb toner transfer
  • sound - look up trigger mp3 with sd card slot
  • also think about amplifier and power source

Weekend + Tutorial with Mike and Dave, 4 Nov 2013

4 Nov 2013

  • Walkie Talkie and Baby Monitor were tested but had too short a range to be useful

ACTION PLAN

LOBBY TO-DO
Description: Muzak that blends into an annoying sound if there are too many people in the lobby.
Goal: Make people leave if they are too many.

  1. Lasers
  2. Mirror arrangement
  3. Light Sensors Soldering
  4. Laser/Light Testing in Lobby
  5. Speaker soldering/set up
  6. Script for Sound
  7. Sound Design


LIFT TO-DO
Description: Inside-out lift
Goal: Making the inaudible AUDIBLE

  1. Accelerometer Soldering
  2. Accelerometer Testing in Lift
  3. Record Lift door timings
  4. SD Card Module Soldering
  5. SD Card Testing
  6. Laser and Light Sensor arrangement
  7. Speakers soldering/set up
  8. External Power for both arduino and speaker.
  9. Sound Design
  10. Script for Sound

Testing the Accelerometer

ADXL362wat.png

Understanding the need for llc

Using another accelerometer

Testing RC Switch

Testing the SD Library

Sdcardarduino.png

  • next goal: audio playback of wav file on sd card reader......

WORKING SCRIPT FOR PLAYING BACK A WAV FILE ON THE SD CARD READER!!!!

#include <SD.h>
//#define SD_ChipSelectPin 10
#include <TMRpcm.h>
const int chipSelect = 4;

TMRpcm tmrpcm;
char mychar;

void setup(){
  
  tmrpcm.speakerPin = 9;
  
   Serial.begin(9600);
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  
  if (SD.exists("SS.WAV")) {
    Serial.println("SS.WAV exists.");
  }
  else {
    Serial.println("SS.WAV doesn't exist.");  
  }  
  
   tmrpcm.play("SS.WAV");
}
    
void loop(){
 return;}
  • on mac to see all files go to terminal and type this: "defaults write com.apple.Finder AppleShowAllFiles YES"

Testing the Wifi shield

  • Result: Does not connect to Eduroam because its WPA2 Enterprise. :-(
  • Solution: Project wifi network from smartphone.

Wifiarduino.png

Fixing up the Audio Jack

Audiojack.png Audiosocket.png

WORKING AUDIO OUTPUT FOR ARDUINO CIRCUIT

Workingaudio.png

  • Adapted from: http://apcmag.com/arduino-project-5-digital-audio-player.htm
  • iTunes Conversion:
    • Click > Edit > Preferences > Import Settings
    • Change the dropdown to WAV Encoder and Setting: Custom > 16.000kHz, 8-bit, Mono
    • Right click any file in iTunes, and select "Create WAV Version"
    • Copy file to SD card using computer
  • Playback is working!

Combining the accelerometer and the audio

  • both audio and accelerometer work on their own but then when put together it returns this error in the serial monitor: "DMP Initialization failed (code 1)"
  • The DMP, or Digital Motion Processor, is an internal processing unit contained within the MPU-6050 and its successors (MPU-6150, MPU-9150, possibly more in the future). The processor has been described by InvenSense employees as a sort of limited CPU, or alternatively as an enhanced ALU (arithmetic logic unit), which is built with an instruction set designed for very specific 3D math operations necessary for orientation calculation. There is currently no known resource for understanding what this instruction set is or how it works. - http://www.i2cdevlib.com/devices/mpu6050#help
  • Current error log:
card initialized.
SS.WAV exists.
DMP Initialization failed (code 1)
Card failed, or not present

Libraries

Connecting Two Arduinos through serial comms - first test

Connect TX 1 of Sender to RX 0 of Receiver Connect both vcc and gnd

SENDER

//This is the sender

void setup()
{
 Serial.begin(115200); // set up Serial library at 9600 bps
}

void loop()
{
 Serial.println("This is a test ");
 delay(1000);
}

RECEIVER

//This is the receiver
char recievedChar = 'a';
void setup()
{
 Serial.begin(115200); // set up Serial library at 9600 bps
 Serial.println(recievedChar); //Check to see if Monitor is working
}

void loop()
{
 if (Serial.available()){
 recievedChar = Serial.read();
 Serial.print(recievedChar);
 }

}

NEW RECEIVER

char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character

void setup() {
    Serial.begin(115200);
//    Serial.write("Power On");
}

char Comp(char* This) {
    while (Serial.available() > 0) // Don't read unless
                                   // there you know there is data
    {
        if(index < 19) // One less than the size of the array
        {
            inChar = Serial.read(); // Read a character
            inData[index] = inChar; // Store it
            index++; // Increment where to write next
            inData[index] = '\0'; // Null terminate the string
        }
    }

    if (strcmp(inData,This)  == 0) {
        for (int i=0;i<19;i++) {
            inData[i]=0;
        }
        index=0;
        return(0);
    }
    else {
        return(1);
    }
}

void loop()
{
    if (Comp("playSoundNow")==0) {
        Serial.write("PLAY THAT MOTHERFUCKER!");
    }
}

NEW Sender M


boolean debug = false;
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"
#include <math.h>

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
#define AVERAGEBUFFER 40
#define DEVIATIONBUFFER 40

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;

const int sampleInterval = 10;
const int deviationThreshold = 70;
const int topIntegral = 70;
const int bottomIntegral = -70;
const int zero = 820;

boolean hasBeenPlaying;

bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
volatile bool mpuInterrupt = false; 
bool blinkState = false;

unsigned long prevTimer;
unsigned long timer;
long integral;
long secondIntegral;
long integralTarget;
long prevSecondIntegral;
long runningTotal;
int index;
int sampleHistory[AVERAGEBUFFER];
int deviationHistory[DEVIATIONBUFFER];
int deviation;
int prevDeviation;
int mean;

const int chipSelect = 4;

//TMRpcm tmrpcm;
char mychar;

int16_t ax, ay, az;
int16_t gx, gy, gz;

void setup() {

  //tmrpcm.speakerPin = 10;

  //SD.begin(chipSelect);

  // join I2C bus (I2Cdev library doesn't do this automatically)
  //Wire.begin();
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);

  // initialize serial communication
  // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
  // it's really up to you depending on your project)
  Serial.begin(115200);

  // initialize device
  //Serial.println("Initializing I2C devices...");

  //mpu.initialize();
  // verify connection
  if(debug) {
    Serial.println("Testing device connections...");
    Serial.println(mpu.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  }
  enableMPU();
  // configure Arduino LED for
  pinMode(LED_PIN, OUTPUT);


  for (int thisReading = 0; thisReading < AVERAGEBUFFER; thisReading++){
    sampleHistory[thisReading] = 0;  
  }
}

void loop() {
  // read raw accel/gyro measurements from device
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  while (!mpuInterrupt && fifoCount < packetSize) {
  }

  //if(!tmrpcm.isPlaying()) { // If there are no songs playing...
  timer = millis();
  if(timer-prevTimer >= sampleInterval) {
    prevTimer = timer;

    fifoCount = mpu.getFIFOCount();

    mean = rollingAverage(ax/20-zero, sampleHistory);
    deviation = rollingDeviation(mean, sampleHistory);

    if(deviation <= 30) {
      integralTarget = 0;
      chaseZero();
      secondIntegral = prevSecondIntegral;
    }
    else if(deviation > 30 && deviation-prevDeviation < 10) {
      integral += mean * sampleInterval;
      chaseZero();
      secondIntegral += integral * sampleInterval / 100;
    }
      else {
      mean = discardPrevMean(sampleHistory);
    }

    if(debug) {
      Serial.print("M: ");
      Serial.print(mean);
      Serial.print("\tI: ");
      Serial.print(integral/100);
      Serial.print("\tS: ");
      Serial.print(secondIntegral);
      Serial.print("\tD: ");
      Serial.println(deviation);
    }
    if(deviation > 90) {
      Serial.write(0);
    }
    prevSecondIntegral = secondIntegral;
    prevDeviation = deviation;
  }

}

void chaseZero() {
  int delta = 0;
  delta = integralTarget - integral;
  if(delta > 0 && delta < 8) integral++;
  else if(delta > -8 && delta < 0) integral--;
  else integral += delta/8;
}

ARGHH??????

NEW Receiver M

#include <SD.h>
//#define SD_ChipSelectPin 10
#include <TMRpcm.h>
const int chipSelect = 4;

TMRpcm tmrpcm;
char mychar;
char recievedChar;
byte receivedByte;

char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
char wavArray[]={
  'TONE.WAV', 'SS.WAV', 'ANDROMEDA.WAV'};

void setup() {
  tmrpcm.speakerPin = 10;
  Serial.begin(115200);
  pinMode(10, OUTPUT);
  if (!SD.begin(chipSelect)) {
    //Serial.println("Card failed, or not present");
    return;
  }
  tmrpcm.play("TONE.WAV"); //the sound file will play each time the arduino powers up, or is reset

}


void loop()
{

  if (Serial.available() > 0) {

    receivedByte = Serial.read();
    //Serial.print(recievedChar);
    switch (receivedByte) {

    case 0:   
      tmrpcm.play("SS.WAV"); 
      break;

    case 1:    
      Serial.println("dim");
      break;
    }
  }

}

WORKING 4pm

sender


boolean debug = false;
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"
#include <math.h>

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
#define AVERAGEBUFFER 40
#define DEVIATIONBUFFER 40

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;

const int sampleInterval = 10;
const int deviationThreshold = 70;
const int topIntegral = 70;
const int bottomIntegral = -70;
const int zero = 820;

byte receivedByteBack;

boolean hasBeenPlaying;

bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
volatile bool mpuInterrupt = false; 
bool blinkState = false;

unsigned long prevTimer;
unsigned long timer;
long integral;
long secondIntegral;
long integralTarget;
long prevSecondIntegral;
long runningTotal;
int index;
int sampleHistory[AVERAGEBUFFER];
int deviationHistory[DEVIATIONBUFFER];
int deviation;
int prevDeviation;
int mean;

const int chipSelect = 4;

//TMRpcm tmrpcm;
char mychar;

int16_t ax, ay, az;
int16_t gx, gy, gz;


void setup() {

  //tmrpcm.speakerPin = 10;

  //SD.begin(chipSelect);

  // join I2C bus (I2Cdev library doesn't do this automatically)
  //Wire.begin();
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);

  // initialize serial communication
  // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
  // it's really up to you depending on your project)
  Serial.begin(115200);

  // initialize device
  //Serial.println("Initializing I2C devices...");

  //mpu.initialize();
  // verify connection
  if(debug) {
    Serial.println("Testing device connections...");
    Serial.println(mpu.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  }
  enableMPU();
  // configure Arduino LED for
  pinMode(LED_PIN, OUTPUT);


  for (int thisReading = 0; thisReading < AVERAGEBUFFER; thisReading++){
    sampleHistory[thisReading] = 0;  
  }
}

void loop() {
  // read raw accel/gyro measurements from device
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  while (!mpuInterrupt && fifoCount < packetSize) {
  }

  //if(!tmrpcm.isPlaying()) { // If there are no songs playing...
  timer = millis();
  if(timer-prevTimer >= sampleInterval) {
    prevTimer = timer;

    fifoCount = mpu.getFIFOCount();

    mean = rollingAverage(ax/20-zero, sampleHistory);
    deviation = rollingDeviation(mean, sampleHistory);

    if(deviation <= 30) {
      integralTarget = 0;
      chaseZero();
      secondIntegral = prevSecondIntegral;
    }
    else if(deviation > 30 && deviation-prevDeviation < 10) {
      integral += mean * sampleInterval;
      chaseZero();
      secondIntegral += integral * sampleInterval / 100;
    }

    // above val was 30 , 30 , 10


      else {
      mean = discardPrevMean(sampleHistory);
    }

    if(debug) {
      Serial.print("M: ");
      Serial.print(mean);
      Serial.print("\tI: ");
      Serial.print(integral/100);
      Serial.print("\tS: ");
      Serial.print(secondIntegral);
      Serial.print("\tD: ");
      Serial.println(deviation);
    }

    if(deviation > 90) {
      Serial.write(0);
    }

    prevSecondIntegral = secondIntegral;
    prevDeviation = deviation;

  }
  

}

void chaseZero() {
  int delta = 0;
  delta = integralTarget - integral;
  if(delta > 0 && delta < 8) integral++;
  else if(delta > -8 && delta < 0) integral--;
  else integral += delta/8;
}


void playSound() {
  hasBeenPlaying = true;
  delay(1000);
  interrupts();
}

void enableMPU() {
  Wire.begin();
  interrupts();
  mpu.initialize();
}

void disableMPU() {
  noInterrupts();
}

void reEnableMPU() {
  Wire.begin();
  enableMPU();
  mpu.initialize();
}

receivr

#include <SD.h>
//#define SD_ChipSelectPin 10
#include <TMRpcm.h>
const int chipSelect = 4;

TMRpcm tmrpcm;
char mychar;
char recievedChar;
byte receivedByte;

char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
char wavArray[]={
  'TONE.WAV', 'SS.WAV', 'ANDROMEDA.WAV'};

void setup() {
  tmrpcm.speakerPin = 10;
  Serial.begin(115200);
  pinMode(10, OUTPUT);
  if (!SD.begin(chipSelect)) {
    //Serial.println("Card failed, or not present");
    return;
  }
  tmrpcm.play("TONE.WAV"); //the sound file will play each time the arduino powers up, or is reset

}


void loop()
{

  if (Serial.available() > 0) {

    receivedByte = Serial.read();
    //Serial.print(recievedChar);
    switch (receivedByte) {

    case 0:   
      tmrpcm.play("BELL.WAV"); 
      break;

    case 1:    
      Serial.println("dim");
      break;
    }
  }

}

Calling up files

  • if getting the error "avrdude: stk500_getsync(): not in sync: resp=0x49" then take pin out of rx on receiver when uploading sketch
  • VCC FROM SENDER AND RECEIVER DO NOT NEED TO BE CONNECTED ONLY THE GND OF BOTH SHOULD BE CONNECTED!!!!
  • in Arduino: Command-T to autoformat
  • in Arduino: Command-/ over highlighted text to comment it out
  • Nifty trick:
boolean debug = false;
// this will not print to serial if debug is false...
    if(debug) {
      Serial.print("M: ");
      Serial.print(mean);
      Serial.print("\tI: ");
      Serial.print(integral/100);
      Serial.print("\tS: ");
      Serial.print(secondIntegral);
      Serial.print("\tD: ");
      Serial.println(deviation);
    }

Listing all the files in the SD card (wav format only)

#include <SdFat.h>
#include <SdFatUtil.h> // use functions to print strings from flash memory

const uint8_t SD_CHIP_SELECT = 4;
const size_t MAX_FILE_COUNT = 50;
const char* FILE_EXT = "WAV";

SdFat sd;
SdFile file;

size_t fileCount = 0;
uint16_t fileIndex[MAX_FILE_COUNT];

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

void setup(void) {
  dir_t dir;
  char name[13];
  
  Serial.begin(9600);
//  while (!Serial) {} 
//  PgmPrintln("Type any character to start");
//  while (Serial.read() <= 0) {}
//  delay(200);  // Catch Due reset problem
  
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) sd.initErrorHalt();
  
  // start at beginning of root directory
  sd.vwd()->rewind();
  
  // find files
  while (sd.vwd()->readDir(&dir) == sizeof(dir)) {
    if (strncmp((char*)&dir.name[8], FILE_EXT, 3)) continue;
    if (fileCount >= MAX_FILE_COUNT) error("Too many files");
    fileIndex[fileCount++] = sd.vwd()->curPosition()/sizeof(dir) - 1;
  }
  
  PgmPrint("Found count: ");
  Serial.println(fileCount);
 
  for (size_t i = 0; i < fileCount; i++) {
    if (!file.open(sd.vwd(), fileIndex[i], O_READ)) error("open failed");
    file.getFilename(name);
    PgmPrint("Opened: ");
    Serial.println(name);
    // process file here
    file.close();
  }
  PgmPrintln("Done");
}
void loop(void) {
}

Unfortunately this too smart for itself - shows hidden files too....

Sdfilecount.png

Picking Random File to play

Since the previous method was too "effective", this is a more manual method since we know that we will have a fixed number of files and we can name them from 1 to 10.wav.

#include <SD.h>
//#define SD_ChipSelectPin 10
#include <TMRpcm.h>
const int chipSelect = 4;
int totalFiles = 10;

int randWAV;
char FileName[7]; // DO NOT make this buffer too small

TMRpcm tmrpcm;
char mychar;

void setup(){

  tmrpcm.speakerPin = 9;
  randomSeed(analogRead(0));

  Serial.begin(9600);
  //Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  //Serial.println("card initialized.");

  randWAV = random(1, 10); 
  sprintf(FileName, "%i.WAV", randWAV );
  //Serial.println(FileName);

  if (SD.exists(FileName)) {
    Serial.println();
    Serial.print(FileName);
    Serial.print(" exists.");
  }
  else {
    Serial.println();
    Serial.print(FileName);
    Serial.print(" does not exist.");
  }  
  //tmrpcm.play("SS.WAV");
}

void loop(){
  return;
}

Randomfilepicker.png

End product

See also