Created
November 3, 2017 16:07
-
-
Save zenwerk/c0fd6a7ecbd5e227a2b280279b0d294b to your computer and use it in GitHub Desktop.
arduino_laser_harp.pde
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// MAKE MAGAZINE - LASER HARP FOR ARDUINO | |
// Stephen Hobley 2008 | |
// www.stephenhobley.com | |
//////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Variables: /////////////////////////////////////////////////////////////////////////////////////////// | |
#define BEAMCOUNT 6 // レーザーの数 | |
#define MIDICMD_NOTEON 0x90 // MIDIコマンド (Note On, Channel 0) | |
#define MIDICMD_CTRL 0xb0 // MIDI Controller message - channel 0 | |
#define MIDICMD_PB 0xe0 // MIDI Pitchbend message - channel 0 | |
#define MIDI_ROOT_NOTE 60 // テルミンのRoot note | |
#define MIDI_CONTROLLER 74 // Controller number | |
#define LOOPDELAY 10 | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// データ構造 | |
// These structures govern the behaviour of each of the 6 laser beams in harp mode | |
// access any of these arrays in the main polling loop <array>[i] | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
byte pinarray[BEAMCOUNT] = {2,3,4,5,6,7}; // Digital pins to read for laser beam breaks | |
byte analogarray[BEAMCOUNT] = {0,1,2,3,4,5}; // Analog pins to read for continuous data | |
byte notearray[BEAMCOUNT] = {64,63,62,60,59,58}; // MIDI note array - these are the notes that will play for each beam | |
// これがHIGHとなるpinは音を出す -> playarrayとは音を出す配列 | |
// レーザーハープは光センサ(CDS)に光が当たっているときは, 音が出ない | |
// つまり,HIGH -> 無音, LOW -> 音を出す, ということに注意 | |
byte playarray[BEAMCOUNT] = {HIGH,HIGH,HIGH,HIGH,HIGH,HIGH}; // The state of all beams to start with | |
// 距離センサの最大値 (浮動小数点数) | |
// TODO ここの値は環境によって微調整が必要 | |
#define SENSORSCALE 1000.0 // Floating point maximum range for sensor - tweak this to find the best range | |
int iCounter = 0; // Counter used to reduce the sample rate | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// This function takes the value from the GP2 sensor and calculates the MIDI controller value from it | |
// this is a bit slow as it uses floating point math | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// 距離センサの値からMidiコントローラの値を計算する関数 | |
// 浮動小数点数演算のため若干動作が遅い | |
int ProcessAnalogValue(byte i) | |
{ | |
// get a value for the GP sensor on pin i | |
// 指定されたpinの距離センサの値を読み込む | |
float _x = read_gp2d12_range_float(i); | |
// Truncate at 1000 | |
// 1000より大きい値は切り捨て | |
if (_x > 1000.0) | |
_x = 1000.0; | |
// 0 - 127 is the full velocity range | |
// Midiベロシティの値は (1 - 127) の範囲 | |
int _converted = (int)(_x/SENSORSCALE * 127.0); | |
// Now reverse the scale - louder closer to sensor | |
// scaleを反転する - センサに近いほど大きくする | |
//_converted = 127 - _converted; | |
// Midi信号送信 | |
SendMIDI(MIDICMD_CTRL, MIDI_CONTROLLER, _converted ); | |
return _converted; | |
} | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Reads the GP2 sensor and returns the value in cms - floating point version - provided by Javier Valencia 2008 | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// 距離センサの読み込み、cmsに変換して返す | |
float read_gp2d12_range_float(byte pin) | |
{ | |
int tmp; | |
tmp = analogRead(pin); // pinからアナログ読み込み | |
if (tmp < 3) // 読み込まれる値は3未満を想定している | |
return -1.0; // invalid value | |
return (6787.0 /((float)tmp - 3.0)) - 4.0; | |
} | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Plays a MIDI note. | |
// Format of MIDI note on | |
// 1<xxx><yyyy> - xxx is 001 (Note On), yyyy is the channel number - in our case 0000 - which is channel 0 | |
// 0<xxxxxxx> - note number 0-127 | |
// 0<yyyyyyy> - note velocity 0-127 - instead of sending a note off, you can send 0 in this field to silence a note | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
void SendMIDI(char cmd, char data1, char data2) | |
{ | |
Serial.print(cmd); | |
Serial.print(data1); | |
Serial.print(data2); | |
} | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// SETUP FUNCTION | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
void setup() | |
{ | |
// Set MIDI baud rate: | |
Serial.begin(31250); | |
//Serial.begin(9600); | |
pinMode(13, OUTPUT); // sets the digital pin as output | |
// 13pinから信号を出すので、midiケーブルとかは13pinにつなぐ | |
} | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// MAIN LOOP | |
///////////////////////////////////////////////////////////////////////////////////////////////////////// | |
void loop() | |
{ | |
// Loop through 6 inputs and find one that is different to how it was before | |
// if is is LOW, then note on, HIGH then note off.. | |
// レーザーの数だけループ | |
for (int i= 0; i < BEAMCOUNT; i++) | |
{ | |
// 1 Loop through 6 inputs and find one that is different to how it was before | |
// 読み込んだpinの状態が, 現在(一個前)の状態と違うか? | |
if ( digitalRead(pinarray[i]) != playarray[i] ) | |
{ | |
if (playarray[i] == HIGH) | |
{ | |
// 音をだす (NOTE ON) | |
SendMIDI(MIDICMD_NOTEON, notearray[i], 127); | |
} | |
else | |
{ | |
// 音を消す (NOTE OFF) | |
// Sound the MIDI note | |
SendMIDI(MIDICMD_NOTEON, notearray[i], 0); // Silence the note | |
} | |
// Finally flip the state of the playarray | |
// 最後に現在の状態を更新する | |
playarray[i] = !playarray[i]; | |
} | |
// TODO ここの条件を変えると、回路側のCDSと抵抗を逆に接続可能 | |
else if (playarray[i] == LOW) // 読み込んだ状態に変化がなく, かつ状態はLOWのまま | |
{ | |
// Note: the update rate of the sensor is 25Hz - so we only need to read about once every 40ms - let's make it 30ms (3xLOOPDELAY) to be safe. | |
// If it is LOW then read analog pin and send out a pitchbend message | |
// センサの更新レートは25Hz, よって40ミリ秒毎に読み込めばよい. | |
// なので, 安全のため30ミリ秒 (3 x LOOPDELAY) のdelayをする. | |
// つまり,forloopを抜けると, 最後のdelayで必ずdelayが発生するので, iCounterが3になるまではLOWのPINが更新されることはない. | |
if (iCounter == 3) // delayカウンターが3つたまったら.. | |
{ | |
ProcessAnalogValue(analogarray[i]); // 値読み込み | |
iCounter = 0; // delay用のカウンタを0に戻す | |
} | |
iCounter++; // delay用のカウンタを+1 | |
} | |
} | |
// Pause processing for 1/100 of a second - adjust this value to alter the response of the harp. | |
// 10ミリ秒処理止める. | |
// TODO この値は環境によって調整がいる | |
delay(LOOPDELAY); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment