Musical Machines and Flapping Phones

Post on 31-Aug-2014

352 views 0 download

Tags:

description

Presentation about using the tech behind a couple of my projects in your own work. It contains tips about how to play music with machines and how to connect your cellphone to an Arduino. Code for the presentation can be found here - https://github.com/neilmendoza/musicalmachines

Transcript of Musical Machines and Flapping Phones

@neilmendoza

Musical Machines and Flapping Phones !

Neil Mendoza

@neilmendoza

Who are you?

@neilmendoza

@neilmendoza

@neilmendoza

@neilmendoza

@neilmendoza

@neilmendoza

@neilmendoza

What are musical notes?

@neilmendoza

@neilmendoza

Melody: Stepper

@neilmendoza

What is a stepper?

@neilmendoza

Stepper Drivers

@neilmendoza

So many wires…

@neilmendoza

Measure resistance of coils…

@neilmendoza

@neilmendoza

#include <Stepper.h>!// change this to fit the number of steps per revolution// for your motorconst int stepsPerRevolution = 48; !// initialize the stepper library on the motor shieldStepper myStepper(stepsPerRevolution, 12,13); !// give the motor control pins names:const int pwmA = 3;const int pwmB = 11;const int brakeA = 9;const int brakeB = 8;const int dirA = 12;const int dirB = 13;!void setup(){ // set the PWM and brake pins so that the direction pins // can be used to control the motor: pinMode(pwmA, OUTPUT); pinMode(pwmB, OUTPUT); pinMode(brakeA, OUTPUT); pinMode(brakeB, OUTPUT); digitalWrite(pwmA, HIGH); digitalWrite(pwmB, HIGH); digitalWrite(brakeA, LOW); digitalWrite(brakeB, LOW);! // set the motor speed (for multiple steps only): myStepper.setSpeed(2);}!void loop(){ myStepper.step(48); myStepper.step(-48);! delay(2000);}

Motor Shield R3 Code

@neilmendoza

Step Direction Driver Code

int dirpin = 2;int steppin = 3;!void setup() { pinMode(dirpin, OUTPUT); pinMode(steppin, OUTPUT);}!void loop(){ int i;! digitalWrite(dirpin, LOW); // Set the direction. delay(100);!! for (i = 0; i<4000; i++) // Iterate for 4000 microsteps. { digitalWrite(steppin, LOW); // This LOW to HIGH change is what creates the digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step. delayMicroseconds(500); // This delay time is close to top speed for this } // particular motor. Any faster the motor stalls.! digitalWrite(dirpin, HIGH); // Change direction. delay(100);!! for (i = 0; i<4000; i++) // Iterate for 4000 microsteps { digitalWrite(steppin, LOW); // This LOW to HIGH change is what creates the digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step. delayMicroseconds(500); // This delay time is close to top speed for this } // particular motor. Any faster the motor stalls.}

@neilmendoza

Controller: MIDI

@neilmendoza

MIDI Circuit

@neilmendoza

Simple MIDI Code#include <SoftwareSerial.h>!int midiByte0 = -1;int midiByte1 = -1;int midiByte2 = -1;!#define HI_NIBBLE(b) (((b)>>4) & 0x0F)#define LO_NIBBLE(b) ((b) & 0x0F)!#define NOTE_ON_STATUS B1001#define NOTE_OFF_STATUS B1000#define CC_STATUS B1011#define PITCHBEND_STATUS B1110!#define MIDI_BAUD_RATE 31250!const int LED = 13;const int MIDI_IN = 8; !SoftwareSerial midiIn(MIDI_IN, 9); // RX, TX!void setup(){ pinMode(LED, OUTPUT); midiIn.begin(MIDI_BAUD_RATE);}!void loop(){ updateMidi(); }!void noteOn(int channel, int note, int vel){ digitalWrite(LED, HIGH);}!void noteOff(int channel, int note){ digitalWrite(LED, LOW);}

void updateMidi(){ int b = midiIn.read(); if(b!= -1) { midiByte2 = midiByte1; midiByte1 = midiByte0; midiByte0 = b; // only work if we've got a status byte // of some sort if(!(midiByte2 & B10000000)) return; int st = HI_NIBBLE(midiByte2); int channel = LO_NIBBLE(midiByte2); // now check to see if we have a midi if(st == NOTE_ON_STATUS) { if(midiByte0 == 0) { // if the volume is zero, it's a note off noteOff(channel, midiByte1); } else { noteOn(channel, midiByte1, midiByte0); } } else if(st == NOTE_OFF_STATUS) { noteOff(channel, midiByte1); } }}

@neilmendoza

MIDI to Frequency Code#include <SoftwareSerial.h> !int midiByte0 = -1; int midiByte1 = -1; int midiByte2 = -1; !#define HI_NIBBLE(b) (((b)>>4) & 0x0F) #define LO_NIBBLE(b) ((b) & 0x0F) !#define NOTE_ON_STATUS B1001 #define NOTE_OFF_STATUS B1000 #define CC_STATUS B1011 #define PITCHBEND_STATUS B1110 !#define MIDI_BAUD_RATE 31250 !const unsigned LED_PIN = 13; const unsigned STEP_PIN = 3; const unsigned DIR_PIN = 2; const unsigned MIDI_IN_PIN = 10; !SoftwareSerial midiIn(MIDI_IN_PIN, 9); // RX, TX !unsigned long halfPeriodMicros = 0; !void setup() { pinMode(LED_PIN, OUTPUT); pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); digitalWrite(STEP_PIN, LOW); digitalWrite(DIR_PIN, LOW); midiIn.begin(MIDI_BAUD_RATE); } !void loop() { if (halfPeriodMicros != 0) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(halfPeriodMicros); digitalWrite(STEP_PIN, LOW); delayMicroseconds(halfPeriodMicros); } }

!double midiToFrequency(int midiNote) { return 440.0 * exp(0.057762265 * (midiNote - 69.0)); } !void noteOn(int channel, int midiNote, int vel) { halfPeriodMicros = 0.5 * 1000000.0 / midiToFrequency(midiNote); digitalWrite(LED_PIN, HIGH); } !void noteOff(int channel, int midiNote) { halfPeriodMicros = 0; digitalWrite(LED_PIN, LOW); } !void updateMidi() { int b = midiIn.read(); if(b != -1) { midiByte2 = midiByte1; midiByte1 = midiByte0; midiByte0 = b; // only work if we've got a status byte // of some sort if(!(midiByte2 & B10000000)) return; int st = HI_NIBBLE(midiByte2); int channel = LO_NIBBLE(midiByte2); // now check to see if we have a midi if(st == NOTE_ON_STATUS) { if(midiByte0 == 0) { // if the volume is zero, it's a note off noteOff(channel, midiByte1); } else { noteOn(channel, midiByte1, midiByte0); } } else if(st == NOTE_OFF_STATUS) { noteOff(channel, midiByte1); } } }

@neilmendoza

Oscillator Code#include "Oscillator.h" unsigned long Oscillator::elapsedMicros = 0; !Oscillator::Oscillator(unsigned channel) : channel(channel), periodMicros(0), halfPeriodMicros(0) {} void Oscillator::noteOn(unsigned channel, unsigned note, unsigned vel) { if (this->channel == channel) { periodMicros = 1000000.0 / midiToFrequency(note); halfPeriodMicros = 0.5 * periodMicros; } }; !void Oscillator::noteOff(unsigned channel, unsigned note) { if (this->channel == channel) { periodMicros = 0; halfPeriodMicros = 0; } }; !void Oscillator::update() { if(periodMicros > 0) { unsigned long elapsedPeriodMicros = elapsedMicros % periodMicros; if(elapsedPeriodMicros > halfPeriodMicros != !wave) { // wave form has flipped wave = !wave; if (wave) risingEdge(); else fallingEdge(); } } }; !double Oscillator::midiToFrequency(int midiNote) { return 440.0 * exp(0.057762265 * (midiNote - 69.0)); }

@neilmendoza

DEMO

@neilmendoza

Percussion: Car Door Lock “Solenoid”

@neilmendoza

Driver Circuit

@neilmendoza

Car Door Lock Code = Blink

int carDoorPin = 10;!// the setup routine runs once when you press reset:void setup(){ // initialize the digital pin as an output. pinMode(carDoorPin, OUTPUT); }!// the loop routine runs over and over again forever:void loop(){ digitalWrite(carDoorPin, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(carDoorPin, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second}

@neilmendoza

DEMO

DEMO

@neilmendoza

Other Coily Things

@neilmendoza

https://github.com/isthisgood/scrapheap-orchestra

@neilmendoza

@neilmendoza@neilmendoza

@neilmendoza

@neilmendoza

@neilmendoza

@neilmendoza

VS

@neilmendoza

@neilmendoza

Many phones still speak the same language as 1990s modems (AT commands)

ATD0123456789 = Call 0123456789 AT+CHUP = Hang up call

@neilmendoza

Cheap phones that talk serial Sony Ericsson T237(US)/T230(UK)

@neilmendoza

Phone circuit

@neilmendoza

@neilmendoza

Make a Call#include <SoftwareSerial.h>!const String PHONE_NUMBER = “07956641707";!SoftwareSerial phone(2, 3);!void setup(){ // start talking to phone over serial phone.begin(9600); // start talking to computer over serial // to receive trigger and send debug // messages Serial.begin(9600);}!void loop(){}!void serialEvent(){ // received a serial event call number if (Serial.available()) { // prepare the AT command String command("ATD"); command += PHONE_NUMBER; command += ";"; // send it to the phone phone.println(command); // debug message Serial.print("Sent AT command: "); Serial.println(command); // clear the serial buffer and wait for // next time Serial.flush(); }}

@neilmendoza

Receive a Call

#include <SoftwareSerial.h>!SoftwareSerial phone(2, 3);!unsigned long lastCallTime = 0;String buffer;!void setup(){ // start talking to phone over serial phone.begin(9600); // start talking to computer over serial // to receive trigger and send debug // messages Serial.begin(9600);}!void loop(){ // check for calls bool callReceived = checkForCalls(); // if we got a call send a message to the computer if (callReceived) { Serial.println("I got a call :)"); }}

bool checkForCalls(){ bool callReceived = false; if (phone.available()) { char newChar = (char)phone.read(); if (isNewLine(newChar)) { if (!buffer.equals("") && !buffer.equals(" ")) { Serial.println(buffer); if (buffer.indexOf("RING") != -1) { lastCallTime = millis(); callReceived = true; } } buffer = ""; } else { buffer = buffer + newChar; } } return callReceived;}!bool isNewLine(char c){ return c == '\n' || c == '\r' || c == '\t';}

@neilmendoza

DEMO

@neilmendoza

Android

@neilmendoza

https://github.com/mik3y/usb-serial-for-android

USB On The Go (OTG) Cable

@neilmendoza

http://www.amarino-toolkit.net/

Bluetooth

@neilmendoza

Mobile Music

+

@neilmendoza

DEMO

@neilmendoza

githhub.com/neilmendoza/musicalmachines !

www.neilmendoza.com !

@neilmendoza