電子オルゴール

  1. 実験の目的
     PICのソフトウエアによる発振機能を用いて、ドレミ.. の音を合成し、簡単な音楽演奏を試みます。

  2. 音の合成

    1. 音の生成
       音は物体の機械的振動が空気を媒介して耳で聴取される信号です。音色はその強さを縦軸とし、横軸を時間とした波形で決まります。



      音は複数の周波数の音の重ねた音として聞こえます。音の周波数の比がきれい(簡単な)値のとき、きれいな音と聞こえます。音の高さは主となる音の周波数で定まります。音色は波形で定まります。

    2. 音階
      音階はドレミで表現しますが、低いドから次のドになると周波数は倍になります。平均率の音階は、この1オクターブを周波数の比を一定に12等分します。従って、前の音の周波数を1にすると、次の音の周波数は、前の音の約 2^(1/12) = 1.06倍になります。ミとファおよび、シとド以外には半音が入ります。これはピアノ鍵盤の黒鍵に相当します。ド#はドの半音上の音で、これはレ♭の音と同じです。

       五線譜のラの音の周波数はちょうど440ヘルツになりますから、次1オクターブ低いラの音までの周波数は次の表のようになります。 A,B,C..はドイツ語の音階表記です。A(ラ)の音はきれいな整数値なので、よく楽器の音あわせに利用されます。

      ドイツ音階 A A# B C C# D D# E F F# G G# A
      ラ# ド# レ# ファ ファ# ソ#
      周波数 220.0 233.1 246.9 261.6 277.2 293.7 311.1 329.6 349.2 369.9 391.9 415.3 440.0
      周波数比 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1
      周期(mS) 4.5 4.3 4.1 3.8 3.6 3.4 3.2 3.0 2.9 2.7 2.6 2.4 2.3
      周期(16uS) 284.1 268.1 253.1 238.9 225.5 212.8 200.9 189.6 179.0 169.0 159.5 150.5 142.0

    3. 音階の合成
      音符に従った長さと高さ(周波数)で音を生成すれば曲として聞こえます。特定の周波数 f の音は出すには、1秒間に f 個のパルスを生成し、その信号でスピーカを鳴らします。ただし、音の波形は単純ですから、「良い」音にはなりません。
      きれいな楽器の音を出すには、予め楽器の音をディジタル録音し、その音を指定時間再生する方法が一般的です。
       場合によっては、その楽器の振動をシミュレーションして音を出す場合もあります。

    4. 音の合成実験
       この実習では、超小型プロセッサを利用して音階を出します。曲のデータは予め4分音符単位の長さで、数字の羅列で音符を表現しておきます。超小型プロセッサはこの数字の列にしたがい、数字の音階に対応する音を生成します。1昔前の携帯電話の「着メロ」に近い音になります。

  3. 回路制作

    1. 必要な部品
      回路配線用パッチボード
      PIC:16F628
      音声用アンプ(スピーカ用の電力増幅回路) TW-143D
      小型スピーカ 
      電源:5V
      パッチ用線材

    2. アンプとスピーカ
       スピーカは磁力を利用して、円筒部にあるコイルを駆動し、コイルに接続した 薄い「幕」を振動し、音波を生成します。アンプはスピーカを駆動するための電力増幅を行うアナログ回路です。ここでは、簡単なキットによるアンプと小型スピーカを利用します。

    3. 回路の組み立て
       PICのICの文字 16F628 を読める向きにし、パッチボードに写真のように差し込みます。すべてのピンがパッチボードの穴に入るよう、注意して差し込みます。文字が見えない場合、円形の「くぼみ」が左下に来るよう向きを設定してください。
       picの下側で左から5番目のピンとボードの下のー電源バーを接続します(写真青色)。次に、上側の左から5ピンを上の+電源バーに差し込みます。これは、PICに電源を供給します。
       アンプ回路の入力用ピン(写真黄色)を下側一番右のピンに差し込みます。これはPICからの音声信号です。次に、アンプの赤黒コードの赤を、ボード上側の+電源バーに、黒コードをボード下側の電源バーに接続します。


      最後に、電源部(アダプタ)の赤い線を、ボードの+電源バーに、黒い線をボード下のー電源バーに接続します。これで、配線が終了です。

    4. 回路の動作
       PICに電源が入ると、自動的にプログラムを実行開始します。音階に対応する音声信号は、RB3(下側一番右)ピンから出力されます。この信号を アンプ 回路に入れ、電力増幅(パワーアップ)をします。増幅された信号をスピーカに接続します。

  4. プログラム

    1. プログラム
       プログラムは、MAINから始まり、入出力ピンの設定、PWMの設定などを行います。54行のMAINLPから繰返し演奏を行います。音符の位置をSNDCNTとしてこれを増しながら、音符を順に演奏します。音符データが 0xed (16進でed)になると、71行のRESTARTに分岐し、曲の頭からリピートします。
       各音符は、76行のSETSNDで演奏します。音符の演奏間隔は103行のTIM2で定めています。先頭の MOVLW 命令のデータ 0x40 が音符の長さを定めています。これを小さくすると、演奏が早くなり、大きくすると遅くなります。

       演奏データは フラッシュROMに記録されています。プログラム最後のEEPROMからは演奏データが記録されています。134行のORG 02100H はROMの番地です。先頭のデータは音符の周波数で、これを変更すると音符の高さが変化してしまいます。149行のORG 02120H 以後が曲のデータで、8分音符単位の音符の高さを指定します。最後の 0xed で音符データの終了を指定します。
       
    2. 演奏データの変更
      1. 演奏速度
        103行の TIM2の MOVLW 0x40 の数値0X40を変更すると、演奏速度が変ります。数字を大きくすると、演奏が遅くなり、小さくすると演奏が早くなります。

      2. 曲データ
         ソースの最後の方で、150行以後 ORG 02120H の次の DE が音符データを定義しています。
         0x14はソですから、この行は ソソミファソソミファ.. となります。休符は 0X15 です。曲の最後には 0xed を付けて下さい。
         1行にいくつデータを書いてもかまいませんが、データ間には ,(コンマ) が必要です。行の最後は不要です。viewメニューの EEROM で、この部分のデータを確認できます。
         134-137 行のデータは音階に対する周波数データです。変更すると、音符の音の高さが変化してしまいます。

    3. ソース

      ;*********************************************
      ;   PIC16F628
      ;   SOUND PLAYER v0.1
      ;   yokoie        2003.11.26作製
      ;                       2004.03.11更新
      ;クロックは4MHz
      ;PWMを利用、出力はRB3/CCP1(9ピン)
      ;*********************************************
      LIST P=16F628, ST=OFF, R=DEC, F=INHX8M
      INCLUDE P16F628.INC
      
      ;Fuse(Config)のデータ
      ;__CONFIG       _INTRC_OSC_NOCLKOUT   & _MCLRE_ON & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_OFF & _CP_OFF
      
      
      ;  変数レジスタの定義
      CNT1    EQU     0x70             ;タイマ用変数
      CNT2    EQU     0x71             ;タイマ用変数
      CNT3    EQU     0x72             ;タイマ用変数
      CNT4    EQU     0x73            ;
      SNDCNT  EQU     0x74            ;音符カウンタ
      
      ;  メインルーチン
              ORG         0           ;Reset Start
      MAIN        
              BSF     STATUS,RP0      ;バンク1へ切替
              MOVLW   0x03            ;Set PortA to Read Mode
              MOVWF   TRISA
              MOVLW   0xB0            ;Set PortB to Read Mode
              MOVWF   TRISB
              
      ;**** PWM モードの設定 ****     
              MOVLW   0x6f            ;PWMのパルス幅を188に
              MOVWF   PR2             ;プリスケーラー設定
              BCF     STATUS,RP0      ;バンク0に戻す
              MOVLW   0CH             ;
              MOVWF   CCP1CON         ;CCP1CONをPWMモードに設定
      
              MOVLW   0x40
              MOVWF   CCPR1L          ;PWMのデューティー設定
      
              ;**** TIMER2 設定  ****
              MOVLW   0x06            ;TIMER2=ON プリスケーラー=1:1
              MOVWF   T2CON           ;TIMER2をセット
      
              ;**** 音符カウンタリセット ****
              MOVLW   0x20
              MOVWF   SNDCNT
      
      ;演奏開始
      MAINLP  BCF     STATUS, Z       ;ゼロフラグクリア
              MOVF    SNDCNT,W        ;楽譜の位置
              CALL    BANK1
              MOVWF   EEADR           ;アドレスをEEADRへセット 
              BSF     EECON1,RD       ;楽譜読み出し開始
              MOVF    EEDATA,W        ;Wレジスタにデータ取り出し 
              CALL    BANK0
              XORLW   0xed            ;0xedなら曲が終了
              BTFSC   STATUS, Z       ;
              CALL    RESTRT          ;先頭に戻る
              CALL    BANK1
              MOVF    EEDATA,W        ;Wレジスタにデータ取り出し 
              CALL    BANK0
              CALL    SETSND          ;音を出す
              INCF    SNDCNT
              GOTO    MAINLP
      
      RESTRT  MOVLW   0x20            ;音符データの先頭に戻す
              MOVWF   SNDCNT
              GOTO    MAINLP          ;再開
                      
              ;PWM周期設定
      SETSND  ;MOVF   E_ADRS,W        ;周波数データのアドレス指定
              CALL    BANK1
              MOVWF   EEADR           ;アドレスをEEADRへセット 
              BSF     EECON1,RD       ;読み出し設定
              MOVF    EEDATA,W        ;Wレジスタにデータ取り出し 
              CALL    BANK1           
              MOVWF   PR2             ;PWMの周期を設定
              CALL    BANK0           
              CALL    TIM2            ;音符の長さだけ持続
              RETURN
      
      STPSND  
              BCF     T2CON, 2        ;0出力
              CALL    TIM2            ;タイマー2
              BSF     T2CON, 2        ;1出力
              RETURN
      
      ;  タイマサブルーチン
      
      TIM1    MOVLW   0xff             ;255
              MOVWF   CNT1              ;
      TIMLP1  CALL    TIM2
              DECFSZ  CNT1,F             ;
              GOTO    TIMLP1             ;
              RETURN                   ;
              
      ;音符の時間待つ
      TIM2    MOVLW   0x40            ;音符の長さを設定
              MOVWF   CNT2            ;CNT2<=0x40
      TIMLP2  CALL    TIM3            ;
              DECFSZ  CNT2,F          ;
              GOTO    TIMLP2          ;
              RETURN                  ;
      
      TIM3    MOVLW   0xff            ;255
              MOVWF   CNT3            ;
      TIMLP3  CALL    TIM4
              DECFSZ  CNT3,F          ;
              GOTO    TIMLP3          ;
              RETURN                  ;
      
      TIM4    MOVLW   0x01            ;
              MOVWF   CNT4            ;
      TIMLP4  DECFSZ  CNT4,F          ;
              GOTO    TIMLP4          ;
              RETURN                  ;
      
      
      ;バンク切り替え関数
      BANK0   BCF     STATUS, RP0     ;バンク0へ
              BCF     STATUS, RP1
              RETURN
      
      BANK1   BSF     STATUS, RP0     ;バンク1へ
              BCF     STATUS, RP1
              RETURN
      
      ;EEPROM DATA
              ORG     02100H          ;周波数データ
              DE      0, 0xeC, 0xDF, 0xd2, 0xc6, 0xbb, 0xb0, 0xa6, 0x9d, 0x94, 0x8c, 
              DE      0x84, 0x7c, 0x73, 0x6e, 0x68
              DE      0x62, 0x5c, 0x57, 0x52, 0x4d, 0
      
      ;ここから楽譜を入力
      ;データ番地と音階対応表
      ;       0x01:ド         0x02:ド#       0x03:レ         0x04:レ#       0x05:ミ
      ;       0x06:ファ       0x07:ファ#     0x08:ソ         0x09:ソ#       0x0a:ラ
      ;       0x0b:ラ#       0x0c:シ         0x0d:ド↑       0x0e:ド#↑     0x0f:レ↑
      ;       0x10:レ#↑     0x11:ミ↑       0x12:ファ↑     0x13:ファ#↑   0x14:ソ↑
      ;       0x15:休符
      
      ;曲の最後に0xedを入力してください。
      
              ORG             02120H
              DE              0x14, 0x14, 0x11, 0x12, 0x14, 0x14, 0x11, 0x12 
              DE              0x14, 0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x11, 0x12
              DE              0x11, 0x11, 0x0d, 0x0f, 0x11, 0x15, 0x05, 0x06
              DE              0x08, 0x0a, 0x08, 0x06, 0x08, 0x05, 0x06, 0x08
              DE              0x06, 0x06, 0x0a, 0x08, 0x06, 0x06, 0x05, 0x03
              DE              0x05, 0x03, 0x01, 0x03, 0x05, 0x06, 0x08, 0x0a
              DE              0x06, 0x06, 0x0a, 0x08, 0x0a, 0x0a, 0x0c, 0x0d
              DE              0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x11, 0x12, 0x14
              DE              0xed      
              END