SSブログ

dsDecR2、モーター和音 [ds-DCCデコーダ]

 和音を作ろうと考えていたが、先週は風邪引いて寝たら週末が終わっていた・・・。
 で、今週いろいろと試行錯誤した。
(1)TimerOneライブラリのsetPeriod(音の高さ)、setPwmDuty(モーターのスピード)を10msecごとぐらいに切り替えて(つまり、最初はドの音を10msec出して、次にソの音を10msec出すと言うのを繰り返すイメージ)やってみた。
 setPwmDutyも一緒に出している理由は、セットで使わないと、Dutyが狂うので(音を高くしたつもりなのに、モーターが暴走するなど)。
 結果は失敗で、音はド、ソ、ド、ソときれいにタイムインターバルで聞こえるし(和音じゃない!)、電車もギクシャクして動きが悪かった。
 次に、
(2)CTCモードを使用して、自分で波形を作って制御しようとした。
 CTCモードでカウンタが上がって行き、OCR1A値まで行くごとに出力が反転するモードを使用したのだが、今回はモーターのスピードも制御する関係で出力のHigh/Low(つまりDuty)も一緒に制御したかったのだが、全然使い勝手が悪かった。Dutyが意味不明に反転することがあり、低速で走っている電車が突然最高速!。と言うわけで、これもボツ。
 で、もうちょっと使えそうなモードが無いかAvrの日本語データシートページを見たら、高速PWMや位相基準PWMがそのまま使えることがわかった。これは、カウンタの上限=周波数(音の高さ)とDuty(モーターの速さ)を別々に制御でき、周期ごとに割り込みを入れられるので、複数の周波数(音の高さ)の切替が可能っぽい。
 て、これって、TimerOneライブラリそのまんまじゃないか?と思ったのでライブラリの中身を見てみたら、やっぱり、そのまんまだった。TimerOneライブラリは「位相基準PWM」を使用しており、このモードは「PWM動作の対称特性からモーターの制御の応用に好まれる」そうである。まあ、深いことは考えずに
(3)TimerOneを流用することにした。出来たものはこちら
 TimerOneをそのまま使用し、今回はattachInterrupt命令を使って、周期ごとの割り込みを起こして、自分の関数int1を呼び出す。
  //setup内の宣言
  Timer1.attachInterrupt(int1,current_period1);//interruptの設定

  //割り込みルーチン
  void int1()
{
  //和音生成用interrupt
  switch(pwm_state)
  {
    case 0:
    {
      Timer1.setPeriod(current_period1);
      break;
    }
    default:
    {
      Timer1.setPeriod(current_period2);
      break;
    }
  }
  //pwm_stateのトグル
  if(pwm_state == state_num)
  {
    pwm_state = 0;
  }
  else
  {
    pwm_state ++;
  }
  
  //Duty
  Timer1.setPwmDuty(MOTOR_PWM_A,current_duty_a);
  Timer1.setPwmDuty(MOTOR_PWM_B,current_duty_b);
}

 この関数内で、周波数の切替を行う、つまり、ドとソを周期的に交互に出るようにする。
 サンプルソースではstate_numは1で、周波数1、周波数2を交互に繰り返す。たとえばstate_numを3にすると、周波数1を1回、周波数2を3回繰り返すため、周波数2が強調された音になる。
 ここで気をつけなければいけないのが、位相基準PWMの対称特性である。
 図を書くと一目瞭然だが、例えば、二つの音を交互に出すとする。例えば750Hzと1500Hzの音を出すとする。
 すると、750[Hz]の音の周期は1333[us]、1500[Hz]の周期は667[us]で、この二つの周期が交互にくるので、合成の周期は1000[us](=(1333[us]+667[us])/2))となる。なお、周期1000[us]のとき周波数は1000[Hz]である。
 ただし、Dutyは異なるため、750Hzと1500[Hz]の音のパルス幅は異なり、周波数変換してやればたぶんわかるが(面倒なので計算してない)1000Hz以外のところにいくつかピークが出て、和音っぽく聞こえるはずである。
 また、なんかVVVF制御の波形にもちょっと近そうな気がする。(私は業界に人じゃないので気がするだけかもだが)
 で、実験してみたら、ちょっと和音ぽく聞こえる。単音ではないので、音が少々小さくなった。耳を澄まさないといけない。
 今回は113系用に単純にスピードとともに周波数があがるだけのものを作った。デバッグは毎度のごとくDCC/MM2シールド→dsDec→線路→アナログモーター車という、PWMコントローラ状態で行った。
 途中でこの音ってモーターの純粋な音ではないのかと言う疑心暗鬼で何回もアナログコントローラでも音を確認した。
 出来た波形は以下の感じ。
113系用.png
 表はこちら
 配列は以下で、周波数を追加している。
//速度領域始め、終わり、周波数始め、終わり、周波数2始め、2終わり、Duty始め、終わり
const int kasoku[5][8] =
{
   {  0,512,345,685,691,1500,0,512},
   { 513, 700,685,685,1500,1500,513, 700},
   { 701,1019,685,685,1500,1500,701,1019},
   { 1020,1021,685,685,1500,1500,1020,1021},
   { 1022,1023,685,685,1500,1500,1022,1023}
};

動画は以下のとおり。
私は満足だった。


コメント(0)  トラックバック(0) 

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0