基本情報

このページではIoTコンテンツ(空中シンセサイザー)をベースにして、新しいコンテンツを「フォーク」できます。フォークしたコンテンツは、プロジェクトの一覧ページに新しい項目として表示されます。元の項目を上書きしたい場合は編集してください。

※写真URLは.jpg, .jpeg, .pngのいずれかで終わるもの、またはGyazoへアップロードされたページのURL(https://gyazo.com/hogehogeなど)に対応しています。

※IoTコンテンツの説明、エントリポイントに関する情報 main: index.js およびf3jsモジュールへの依存情報 dependencies: { f3js: (略) } は、この欄の内容とマージされるため記入不要です。

カードのプレビュー
空中シンセサイザー
'16/7/17 16:31
超音波距離センサーとノブを用いて演奏する電子楽器です.
MMCK

プライベートコンテンツ

チェックを外すと、このコンテンツはすぐ一覧に公開され、誰でもアクセスできるようになります。 なるべくコンテンツを共有していただきたいので、チェックは初めから外れています。また、ログインしていない状態ではチェックをつけられません。 一度公開されたコンテンツは、プライベートにできません。(一度チェックを外すと、以降そのコンテンツを編集するときにはチェックをつけられなくなります。)

ソースコード

マイコン・小型コンピュータのプログラムのソースコードを記述してください。f3jsパッケージをrequireすることで筐体設計が可能です。詳しくはAPIドキュメントをご覧ください。

// 各種ドライバ var grove = require('jsupm_grove'); var buzzer = require('jsupm_buzzer'); var ultrasonic = require('jsupm_groveultrasonic'); var i2clcd = require('jsupm_i2clcd'); var lcd = require("jsupm_i2clcd"); // 各モジュールの初期化 var usonic = new ultrasonic.GroveUltraSonic(2); var rotary = new grove.GroveRotary(0); var buzzer = new buzzer.Buzzer(5); var button = new grove.GroveButton(3); var lcd = new i2clcd.Jhd1313m1(2, 0x3E, 0x62); // 距離から音量[0:1]への変換 (1だと大きすぎるので適当に) function distToVol(dist) { if (dist === 0) // 距離最小:音量最大 return 0.125; else if (dist > 1000) // 距離が一定以上:音量0 return 0; else // 中間 return 0.125 - (Math.sqrt(dist) / (10 * Math.sqrt(10)) / 8); } // 回転から周期の関数 ブザーに依り要変更? function rotToPer(rot) { return 1911 + rot * 2.58; } // 周期から音階の関数 function perToScale(per) { if (per > 4416) return 0; else if (per > 4168) return 1; else if (per > 3934) return 2; else if (per > 3713) return 3; else if (per > 3505) return 4; else if (per > 3308) return 5; else if (per > 3123) return 6; else if (per > 2947) return 7; else if (per > 2781) return 8; else if (per > 2626) return 9; else if (per > 2478) return 10; else if (per > 2339) return 11; else if (per > 2208) return 12; else if (per > 2084) return 13; else if (per > 1967) return 14; else return 15; } // 音量と周期の初期化 var vol = 0; var per = 0; // 距離の平滑化用配列2つ var dists = []; var sorted = []; // 距離初期化 for (var i = 0; i < 6; i++) dists.push(usonic.getDistance()); // 音量設定 function setVol() { dists.shift(); // 一番古いのを抜いて dists.push(usonic.getDistance()); // 現在の値を入れる sorted = dists.slice().sort(function (a, b) { if (a < b) return -1; if (a > b) return 1; return 0; }); vol = distToVol(sorted[2] + sorted[3] / 2); // 中央値 // console.log(vol, sorted); } // 周期設定 function setPer() { per = rotToPer(rotary.abs_value()); // console.log(per); } /* // for debug (音階,音量) var scales = ['A', 'AS', 'B', 'C', 'CS', 'D', 'DS', 'E', 'F', 'FS', 'G', 'GS', 'A', 'AS', 'B', 'C']; function volToString(vol) { var str = ''; for (var i = 0; i < vol * 100; i++) str += '*'; return str; } */ currentScale = 0; function display() { lcd.setCursor(1, currentScale); lcd.write(" "); currentScale = perToScale(per) lcd.setCursor(1, currentScale); lcd.write("*"); } // vol, perにしたがって音を鳴らす function ring() { if (vol === 0.0) buzzer.stopSound(); else { buzzer.setVolume(vol); buzzer.playSound(per, 0); } // for debug (音階,音量をシリアル送信 l87-95が必要) // console.log(scales[perToScale(per)] + ' ' + volToString(vol)); } // 周期的実行のハンドラ var handleV, handleP, handleR, handleD; // 各処理の開始 function start() { handleV = setInterval(setVol, 5); handleP = setInterval(setPer, 5); handleR = setInterval(ring, 5); lcd.setColor(255,255,255); lcd.setCursor(0, 0); lcd.write("AoBCoDoEFoGoAoBC"); handleD = setInterval(display, 5); } // 各処理の停止 function stop() { clearInterval(handleV); clearInterval(handleP); clearInterval(handleR); clearInterval(handleD); lcd.setColor(0,0,0); lcd.clear(); setTimeout(function () { buzzer.stopSound(); }, 100); // うまく消えないことがある? } // 開始 start(); // 状態定数 var STATE_SWITCHING = 0; var STATE_ON = 1; var STATE_OFF = 2; // 状態初期化 var state = STATE_ON; // ボタンによる状態遷移 // 1度状態遷移したら1000msはSTATE_SWITCHINGにとどまり再遷移しない setInterval(function () { if (button.value() === 1) { if (state === STATE_ON) { state = STATE_SWITCHING; stop(); setTimeout(function () { state = STATE_OFF }, 1000); } if (state == STATE_OFF) { state = STATE_SWITCHING; start(); setTimeout(function () { state = STATE_ON }, 1000); } } }, 10); // ---------------ロジックここまで--------------- // ---------------ここから筐体設計--------------- var f3js = require('f3js') , x = 10 , y = 10 , width = 150 // 幅[mm][140, 200] , height = 100 // 奥行き[mm][95, 120] , thickness = 50 // 厚さ[mm][45, 100] , topmargin = 8; // 天面 var rect = f3js.drawJointRectangle(x, y, width, height); // 各部品の追加 f3js.add(usonic, x + 25 + topmargin, y + height - 12.5 - topmargin, 180); f3js.add(rotary, x + width - 10 - topmargin, y + height - 10 - topmargin); f3js.add(buzzer, x + width / 2 + 10, y + height - 10 - topmargin, 90); f3js.add(button, x + 25 + topmargin, y + 20 + topmargin, 90); f3js.add(lcd, x + width - 40 - topmargin , y + 20 + topmargin); // 配線穴 f3js.drawRectangle(x + width / 2, y + height - 35 - topmargin, 20, 10); f3js.drawRectangle(x + 15 + topmargin, y + height - 40 - topmargin, 20, 10); f3js.drawRectangle(x + width - 20 - topmargin, y + height - 35 - topmargin, 20, 10); // その他の面 var planes = rect.extrude(thickness); var margin = 5; planes[0].x = x; planes[0].y = y + height + margin; f3js.add(planes[0]); planes[1].x = x + width; planes[1].y = y + height + margin; f3js.add(planes[1]); planes[2].x = x + height; planes[2].y = y + height + thickness + margin; f3js.add(planes[2]); planes[3].x = x; planes[3].y = y + height + thickness + margin; f3js.add(planes[3]); planes[4].x = width; planes[4].y = 0; f3js.add(planes[4]); // 側面配線用穴 f3js.drawRectangle( x + 5, y + height + thickness * 2 + margin - 2 - 15, height - 10, 10); // IoTボード固定穴x4 (Arduino互換) f3js.drawCircle(x + 2 * width - 10 - 15.234, y + 20 + 2.539, 1.6); f3js.drawCircle(x + 2 * width - 10 - 13.965, y + 20 + 50.761, 1.6); f3js.drawCircle(x + 2 * width - 10 - 65.995, y + 20 + 17.774, 1.6); f3js.drawCircle(x + 2 * width - 10 - 65.995, y + 20 + 45.683, 1.6);
カスタマイズ

このコンテンツにはカスタマイズできる項目がありません。

表示オプション
ソースコード中で変数宣言にコメントをつけるとカスタマイズ項目としてGUIウィジェットが表示されます。グレーアウトしているウィジェットはユーザが提案した項目で、ソースコード末尾の変数宣言に対応しています。

設計のダウンロード

モジュール

このプロジェクトは組み立てにモジュールを必要としません。

レイアウト
プログラム

ログインしないと使えない機能です。