Upload
neil-mendoza
View
349
Download
0
Embed Size (px)
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
Citation preview
@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
Mobile Music
+
@neilmendoza
DEMO
@neilmendoza
githhub.com/neilmendoza/musicalmachines !
www.neilmendoza.com !
@neilmendoza