新・踏切カンカン [Arduino]
「LED チカチカ」からLEDを交互に光らせる「踏切チカチカ」はできても、「踏切カンカン」はちょっと高度で、前回は力業で実現しました。
踏切カンカン
http://hello-world.blog.so-net.ne.jp/2011-10-30
PWMの勉強をして、少しばかり使えるようになったので、改めて作ってみました。
ただし、前回よりもハードを直接触ることになってしまい、そのままではLeonardでは動きません。
タイマーのオーバーフローについて勉強しました。
タイマー/カウンター2割り込みフラグレジスタ(TIFR2) の タイマー/カウンター2 オーバーフロー・フラグ (TOV2) のビットで確認します。TOV2ビットに論理値1を書き込むことで、クリアされるとのこと。
また、8bit高速PWM、分周なしだと、256 CPUサイクルしかありません。
→ 計算式で波形を作るとき短時間で処理を済ませないといけない
→ 割り算はどうやら非常に時間がかかる
→ 割り算はビットシフトで、剰余はAnd演算で対応 (どちらも2のn乗しかできないけど、)
耳で確認しながら、それっぽいところで定数を決めていきました。
というわけで、やってみました。
Arduino Uno や Duemilanove などATmega 328/168 系で、16MHzでの動作です。
デジタル3番(PWM)とGNDにスピーカーをつなぎます。
本当は、スピーカーにコンデンサやら何やらつけないといけないとは思うのですが、とりあえず直接つないで動いています。
踏切カンカン
http://hello-world.blog.so-net.ne.jp/2011-10-30
PWMの勉強をして、少しばかり使えるようになったので、改めて作ってみました。
ただし、前回よりもハードを直接触ることになってしまい、そのままではLeonardでは動きません。
タイマーのオーバーフローについて勉強しました。
タイマー/カウンター2割り込みフラグレジスタ(TIFR2) の タイマー/カウンター2 オーバーフロー・フラグ (TOV2) のビットで確認します。TOV2ビットに論理値1を書き込むことで、クリアされるとのこと。
また、8bit高速PWM、分周なしだと、256 CPUサイクルしかありません。
→ 計算式で波形を作るとき短時間で処理を済ませないといけない
→ 割り算はどうやら非常に時間がかかる
→ 割り算はビットシフトで、剰余はAnd演算で対応 (どちらも2のn乗しかできないけど、)
耳で確認しながら、それっぽいところで定数を決めていきました。
というわけで、やってみました。
// 踏切音くん (Arduino Uno / Duemilanove系, 16MHz)
boolean sigLED = 0; // LEDの状態
void setup() {
pinMode( 3, OUTPUT ); // Arduino pin 3 (ATmega328 PD3, OC2B)をサウンド出力 (固定)
pinMode( 12, OUTPUT );
pinMode( 13, OUTPUT );
TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // 8bit高速PWM
TCCR2B = _BV(CS20); // 分周なし
}
void loop() {
unsigned int pwmVal, t;
digitalWrite( 12, sigLED ); // LEDを交互に光らせる
digitalWrite( 13, sigLED ^= 1 );
for( t = 0; t < 30000; t++ ) {
pwmVal = ( t & B1111111 ) * ( 255 - (t>>7) ) >> 7; // 計算式で音の波形をつくる
while( !(TIFR2 & _BV(TOV2)) ); // タイマーがオーバーフローするのを待つ (この行を消して音に変化なければ計算に時間がかかりすぎ)
TIFR2 |= _BV(TOV2); // タイマー/カウンター2 オーバーフロー・フラグ をクリア
OCR2B = pwmVal; // PWMの値を指定
}
}
Arduino Uno や Duemilanove などATmega 328/168 系で、16MHzでの動作です。
デジタル3番(PWM)とGNDにスピーカーをつなぎます。
本当は、スピーカーにコンデンサやら何やらつけないといけないとは思うのですが、とりあえず直接つないで動いています。