SSブログ

新・踏切カンカン [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乗しかできないけど、)

耳で確認しながら、それっぽいところで定数を決めていきました。

pr_fumikiri.jpg

というわけで、やってみました。

// 踏切音くん (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にスピーカーをつなぎます。
本当は、スピーカーにコンデンサやら何やらつけないといけないとは思うのですが、とりあえず直接つないで動いています。

タグ: 踏切

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。