こんばんは。
さいぞうです。
この記事は、Arduino入門連載の6回目。
前回は、LEDを使ってモールス信号練習機を作った。
本来のチュートリアルからはかなり脱線してきたが、まあ面白かった。 hollywis.hatenablog.com
今回も脱線して、クリスマスなので、Soundcloudからクリスマスソングを取得し再生してそれに合わせてLEDをチカらせてみようと思う。
要はArduinoで簡単なオーディオビジュアライザを作る。
PWMでLEDの明るさを調整できる
一応、このセインスマートのチュートリアルに沿った連載として始めたのでやっておく。 http://www.sainsmart.com/starter-kits/uno-r3-smartkits/sainsmart-uno-r3-5v-servo-motor-starter-kit-with-basic-arduino-projects.html
今回やる4章のテーマは「PWM」。Pulse Width Modulationの略だ。
詳細はもうWikipediaでも見てください。 パルス幅変調 - Wikipedia
PWMで何ができるのかというと、LEDの例だと、これまで光らせるか光らせないかの2段階にしか制御できなかったのが、多段階でコントロールできるようになる!!
こんな感じの回路を作って...
こんな感じのコードを書いて.... gist.github.com
実行すればこうなる! www.youtube.com
かんたん!
音に合わせてひからせる
これではすぐ終わってつまらないので、クリスマスソングにあわせて光らせてみよう。 音の出どころはSoundcloudにして、Ruby経由でArduinoに情報を送って光らせるという連携をしてみる。
Soundcloudの音楽を再生し、出力を数字にする
Soundcloudってのは音楽共有サイト。いろんな音楽を作った人が曲をアップしてて、皆が聞ける。
それだけじゃなく、APIが用意されていて、音楽を他のサイトに埋め込んだり、いろいろできる。
まず、ブラウザ上でSoundcloudの音楽を再生して、その音楽のパワーバーみたいのを出してみよう。 こちらのサイトに詳しいやり方があったので、これを丸パクリして、つくってみた。
電脳ゴリラ: Audio visualization using Processing.js
以下がHTMLにjavascriptのコードも入れたもの。
<h1>クリスマスソング!</h1>
power:<span id="show_power"></span>
<br />
<audio id="audio" controls autobuffer></audio>
<br />
<canvas id="canvas" ></canvas>
<script src="https://connect.soundcloud.com/sdk.js"></script>
<input type="hidden" id="sc_client_id" value="<%= VALUES['sound_cloud']['client_id'] %>" />
<script>
var CLIENT_ID = document.getElementById('sc_client_id').value;
var TRACK_URL = 'https://soundcloud.com/officialmichaelbuble/michael-bubl-its-beginning-to'; // 好きな曲のURL
SC.initialize({
client_id: CLIENT_ID
});
SC.get('/resolve', {url: TRACK_URL}, function(sound){
if(sound.errors){
// エラー処理
for(var i = 0; i < sound.errors.length; i++){
console.log(sound.errors[i].error_message);
}
return;
}
// SoundcloudのストリームURLを取得
var audio = document.getElementById('audio');
audio.crossOrigin = "anonymous";
var streamUrl = sound.stream_url + '?client_id=' + CLIENT_ID;
audio.setAttribute('src', streamUrl);
// アナライザーを作る
var audioCtx = new (window.AudioContext || window.webkitAudioContext);
var analyser = audioCtx.createAnalyser();
analyser.fftSize = 256;
var source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
var showPowerElement = document.getElementById('show_power');
var bytes = new Uint8Array(analyser.frequencyBinCount);
var UNIT_COUNT = 80;
var averagePower = 0;
var draw = function(){
analyser.getByteFrequencyData(bytes);
averagePower = 0;
for(var i = 0; i < UNIT_COUNT; i++){
averagePower += bytes[i]
}
averagePower = averagePower/UNIT_COUNT;
if(averagePower >= 255){
averagePower = 254;
}
// 平均パワーを見せる
showPowerElement.innerText = String(averagePower);
};
setInterval(draw, 500); // 繰り返し実行
});
</script>
後でRubyを使う関係上、Railsでつくっているが、単にこの内容のHTMLファイルを作ってブラウザで読み込ませるだけでもうごくのではないか。
注意点としては"var CLIENT_ID = document.getElementById('sc_client_id').value;"ってとこの=以降を自分のクライアントIDに入れ替えること。
クライアントIDが以下のURLからアプリ登録をすればもらえる。 http://soundcloud.com/you/apps/new
Ruby経由でArduinoに情報を送る
もうここの通りです。
Rubyでserialportを操作してArduinoを動かす - Laboratory of Scarlet
ただし、シリアルポートは私のmacの場合 /dev/cu.usbmodem1411 になった。
上記を参考に、WebブラウザからArduinoに数字を送るRailsアプリを作る。 RailsというのはRuby on RailsというRuby言語でできたフレームワークで、簡単に動的なWebサイトを作れる。 Rails自体のチュートリアルは下のサイトでも見てくれ。
Ruby on Rails チュートリアル:実例を使って Rails を学ぼう
Railsなので、SoundControllerというコントローラをつくり、serial_sendアクションに上のサイトのを参考にしたコードを書く。
class SoundController < ApplicationController
def index
end
def serial_send
@serial_port = "/dev/cu.usbmodem1411" #シリアルのポートを指定
@serial_bps = 9600
sp = SerialPort.new(@serial_port,@serial_bps)
num = params["num"].to_i # 送る数字
sp.write(num.to_s + '/') #serialへの書き込み "/"を数字の終了コードにした
puts num.to_s
render text: num
end
end
ルーティングのroutes.rbにも以下のように設定
get 'sound/serial_send/:num' => 'sound#serial_send'
これで、Webブラウザで例えば、
http://localhost:3000/sound/serial_send/50
というURLをいれると、50という数字がArduinoに送られる。
ArudinoでRuby数字を受け取る
Rubyからというか、シリアルポートからデータを受け取るため、Arduinoのコードを以下のようにする。
注意点としては、この辺を見て欲しいが、受け取った生データはasciiになっているってこと。
1バイトずつ受け取ったデータから48を引いて数字にして保存するとともに、前に受け取ったデータを10倍して前の桁のデータと解釈してる。
final_value=(final_value*10)+(received-48);
送るデータの最後には"/"をつけることにして、"/"がきたらその数字をLEDの明るさにしている。
ここまでのコードを合体!! 音楽に合わせてLEDを光らせる。
Soundcloud→Javascript→Ruby→シリアル通信→Arduinoって感じの情報の流れでさいごにLEDを光らせる
クリスマスソング!
URL here
<input type="text" id="sound_cloud_url" onChange="start_music()" />
<br />
power:<span id="show_power"></span>
<br />
<audio id="audio" controls autobuffer autoplay></audio>
<br />
<canvas id="canvas" ></canvas>
<script src="https://connect.soundcloud.com/sdk.js"></script>
<input type="hidden" id="sc_client_id" value="<%= VALUES['sound_cloud']['client_id'] %>" />
<script>
function start_music(){
var CLIENT_ID = document.getElementById('sc_client_id').value;
var TRACK_URL = document.getElementById('sound_cloud_url').value;
SC.initialize({
client_id: CLIENT_ID
});
SC.get('/resolve', {url: TRACK_URL}, function(sound){
if(sound.errors){
// エラー処理
for(var i = 0; i < sound.errors.length; i++){
console.log(sound.errors[i].error_message);
}
return;
}
// SoundcloudのストリームURLを取得
var audio = document.getElementById('audio');
audio.crossOrigin = "anonymous";
var streamUrl = sound.stream_url + '?client_id=' + CLIENT_ID;
audio.setAttribute('src', streamUrl);
// アナライザーを作る
var audioCtx = new (window.AudioContext || window.webkitAudioContext);
var analyser = audioCtx.createAnalyser();
analyser.fftSize = 256;
var source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
var showPowerElement = document.getElementById('show_power');
var bytes = new Uint8Array(analyser.frequencyBinCount);
var UNIT_COUNT = 80;
var averagePower = 0;
var previousPower = 0;
var sendValue = 0;
var draw = function(){
analyser.getByteFrequencyData(bytes);
previousPower = averagePower;
averagePower = 0;
for(var i = 0; i < UNIT_COUNT; i++){
averagePower += bytes[i]
}
averagePower = averagePower/UNIT_COUNT;
if(averagePower >= 255){
averagePower = 254;
}
// 平均パワーを見せる
showPowerElement.innerText = String(averagePower);
sendValue = averagePower;
if (Math.abs(previousPower-averagePower) < 10){ // 普通にやると変化がなさすぎてつまらないので、状態を持たせて変化を10倍する
sendValue = averagePower + (previousPower-averagePower)*10
}
// ajaxでデータをサーバ側に送る
$.ajax(
'/sound/serial_send/'+sendValue
)
};
setInterval(draw, 100); // 繰り返し実行
});
}
</script>
下記のコードで、Railsのサーバ側に音楽の出力の数字を送っている。
// ajaxでデータをサーバ側に送る
$.ajax(
'/sound/serial_send/'+sendValue
)
こんな風にうごく。
あとは、URLの入力欄を作り、そこにSoundcloudのページのURLを入力すると再生開始とともにLEDが光るというようにした。
今日はここまで。
せんでん
忘れてたが、この記事の内容はこのキットだけを使ってやってます。
Arduinoをはじめよう 互換キット UNO R3対応互換ボード 初心者専用実験キット 基本部品セット20 in 1
- 出版社/メーカー: vership
- メディア: おもちゃ&ホビー
- この商品を含むブログを見る
Arduinoとか抵抗とか全部入ってるからめんどくさい人はこれをかおう。
次回はこちら
第6章(予定)
総合もくじ