君をのせて(天空の城ラピュタ)を電子音で演奏

 今回もラズパイの記事です。いや~まじ楽しいです。
 楽しいけど、あまりにもソロギターと畑違いなので、Youtubeのチャンネルを分けてみました。
 ラズパイの動画を連続でアップしていたら、チャンネル登録者数が減少しましたので^^;

パッシブブザー

 電子工作としては、たんにPNPトランジスターを使ったスイッチ回路というものなのでしょうか。
 ラズパイで周波数を伴った電気がランジスターに流れると、その周波数を受け取った電気が違う足からも流れるのかな。
 付属CDでは、トランジスターの原理を説明していないので、適当な事を書いていますが・・・ちょっと調べてみますか。

S8550 PNPトランジスターの役割

 う~ん、電子工作素人が読んでも分からない記事ばかりです^^;
 どうもS8550にはNPN型のS8050という兄弟がおり、SとSSはアメリカ製、C8550はインド製、で、お決まりの中国のパチものはS8550と同じ名称ですが、性能は相当低いようです。(このセット品のはたぶん中華でしょうね)
 なぜ沢山種類のあるトランジスターの中で、この品番を使用しているのかですが、「この大きさで、流せれる電流が大きい」「PWM 信号を与えて制御をする場合、コンプリメンタリー特性を利用」だそうです。

 難解ですね。コンプメンタリー特性ってなんやねん。と調べてみたところ、今回のパッシブブザーではトランジスターを1個しか使用していないから、PNPとNPNを使った周波数の増幅?には関係ないようですね。

 ま~多分、「大きめの電流を流しても壊れない」というのが、この品番を使っている理由でしょうか・・・。

 で、肝心のトランジスターの仕組みですが、ベース設置とエミッタ設置で、増幅度が違う・・・、今回のパッシブブザーはどちらになるのやら^^;;
 難しいですな~。Google先生の紹介するサイト記事、少々難しいです。理系の人が説明記事を書くと、やたらと専門用語と、ディープな内容を突き詰めていく内容ですね。もっと、シンプルな説明記事ないかな~。
 今度本屋さんに行って、実際に分かりやすそうな電子工作の本でも買ってこようかな。

とりあえずプログラム

 ま~難しい操作原理は置いておいて、付属CDのプログラムを手打ちしました(前回のLCD1602液晶を使いたいため)。
 動かしてみると、なんともショボい曲?なのか、なんなのか分からない曲が流れます。

 一つだけ、プログラムに不明点がありまして、なぜか配列の0番目を使わない記述でした。。繰り返しの数字が range(1,変数)となっていまして、0スタートでなく、1スタートになっていました。
この部分、自分で「君をのせて」をデーター入力して実際に演奏させたときに???なんか変だなと思い気づいたのですが、・・・どこか見落としがあるかな。

プログラムのアレンジ

 参考プログラムの曲が微妙でしたので、「君をのせて」を楽譜を見ながらデーター打ち。今回の動画の長さ分の打ち込みで1時間以上かかりました。
 ドレミの音階よりも、LCD液晶に表示させるカタカナをコード変換するのが超大変。おそらくア~ンまでの、2次元配列変数を作ったほうが早かったぐらいの作業量でした^^;

 時折試し再生をすると、どうにも音痴な感じでしたので、ネットでドレミ周波数を調べて、小数点3位まで記述しました。整数でないとエラーが出るのかと思いましたが、特にエラーは出ませんでした。実際の楽器では、440Hzと441Hzではかなり音が違いますからね~。

 楽譜上に出てくるF#とG#も加えて、今回の演奏となっています。

LCDのオリジナル顔文字もリニューアル

 前回と比べて、猫っぽくなりました。どちらかと言えば犬っぽいですが。
 余裕がでたら、目、耳とか、髭とかで表情を表せれるようにしたいですね^^

使用プログラム(Python)

import smbus
import RPi.GPIO as GPIO
import time
import threading

I2C = smbus.SMBus(1) #1番のI2Cバスを指定
I2C_add = 0x27 #LCDに付属のインターフェイスのアドレス 
CODE_RS0 = 0b0000000 #LCDのRS (レジスタの選択 0=命令用)
CODE_RS1 = 0b0000001 #LCDのRS (レジスタの選択 1=書き込み用)
CODE_E = 0b0000100 #LCD Enable 1から0になると、LCDの制御ICがデータ処理実行
CODE_LED = 0b00001000 #LCDのバックライト 1点灯 0消灯
mojisuu = 16 #ディスプレイの横文字数 (空白で埋めるために使用)
LINE1 = 0x80 #上段の左端アドレス 0x80 ~ 0x8f までの16文字分
LINE2 = 0xC0 #下段の左端アドレス 0xc0 ~ 0xcf までの16文字分
LIN8C = 0x80 #文字表示任意の場所を指定用 上段の5番目 0x85 下段の12番目 0xcc等 

counter = 0
timer1 = 0
time_sleep = 1
hennsuu = 0

#GPIO setup
def GPIO_setup():
    GPIO.setwarnings(False) #セットアップ前のエラー非表示
    GPIO.setmode(GPIO.BCM) #GDIOピンの指定方法
    GPIO.setup(26,GPIO.OUT) #GPIO.LOW=0=False   initial=GPIO.LOW 7seguLED
    GPIO.output(26,GPIO.HIGH)
    global Buzz
    Buzz = GPIO.PWM(26,440)
    Buzz.start(50)
    
    global timer1
    global time_sleep
    timer1 = threading.Timer(time_sleep,timer)
    timer1.start()

def timer():
    global counter
    global timer1
    global time_sleep
    timer1 = threading.Timer(time_sleep,timer)
    timer1.start()
    counter += 1
    #LIN8C = 0x85
    #LCD_print=(str(counter)+'s')
    #LCD_moji(LCD_print,LIN8C)
    #LIN8C = 0xc5
    #kanacode = [0xb6,0x0c4,0xde,0xb3,0xc1,0xad,0xb3]
    #LCD_katakana(kanacode,LIN8C)

def I2C_write(bits,mode):
    data = (bits & 0xF0) | mode | CODE_LED
    I2C.write_byte_data(I2C_add,(data | CODE_E),(data))
    time.sleep(0.0002)
    data = ((bits << 4) & 0xF0) | mode | CODE_LED
    I2C.write_byte_data(I2C_add,(data | CODE_E),(data))
    time.sleep(0.0002)

def LCD_set():#初期設定 4ビットへの設定
    data = (0x33 & 0xF0) | 0x00 | CODE_LED
    I2C.write_byte_data(I2C_add,(data | CODE_E),(data))
    time.sleep(0.005)#0.004以上あける。    
    I2C.write_byte_data(I2C_add,(data | CODE_E),(data))
    time.sleep(0.0002)#0.00001以上あける
    startcom = [0x32,0x28,0x0c,0x01,0x02]
    for command in startcom:
        I2C_write(command,CODE_RS0)
    I2C_write(0x06,CODE_RS0)
    
def LCD_clear():#画面クリア
    clearcom = [0x0c,0x01,0x02,0x06]
    for command in clearcom:
        I2C_write(command,CODE_RS0)
        time.sleep(0.0008)
        
def LCD_text(message,line):#指定した行にまとめてmessage書き込み
    message =message.center(mojisuu," ") #左,右寄せ、中央 ほかを空白で埋める  rjust, ljust, center
    I2C_write(line,CODE_RS0)#行を指定 上0x80 か 下0xc0 で左端から
    for i in range(mojisuu):
        I2C_write(ord(message[i]),CODE_RS1)#LCDのRSを1、文字コード指定 。これを行う前に行(列81=8fも可能)の指定が必要

def LCD_moji(message,line):#指定した場所にmessage書き込み(上書き)
    I2C_write(line,CODE_RS0)#位置を指定 上0x80 か 下0xc0 で左端から
    for i in range (len (message)):
        I2C_write(ord(message[i]),CODE_RS1)

def LCD_katakana(message,line):#指定した場所にmessage書き込み(上書き)
    I2C_write(line,CODE_RS0)#位置を指定 上0x80 か 下0xc0 で左端から
    for i in range (len (message)):
        I2C_write(message[i],CODE_RS1)
        
def LCD_tuiki(message):#LED_mojiのあとの追記用
    for i in range (len (message)):
        I2C_write(ord(message[i]),CODE_RS1)

def LCD_l_move(kazu,hayasa):#文字を左へスクロール 変数kazu分 早は変数hayasa
    I2C_write(0x0c,CODE_RS0)#カーソル表示OFF
    I2C_write(0x07,CODE_RS0)#シフト機能ON
    for i in range (kazu):
        I2C_write(0x18,CODE_RS0)
        time.sleep(hayasa)
    I2C_write(0x06,CODE_RS0)#シフト機能OFF
    I2C_write(0x02,CODE_RS0)#カーソル戻す
    
def LCD_r_move(kazu,hayasa):#文字を右へスクロール 変数kazu分 早は変数hayasa
    I2C_write(0x0c,CODE_RS0)#カーソル表示OFF
    I2C_write(0x07,CODE_RS0)#シフト機能ON
    for i in range (kazu):
        I2C_write(0x1C,CODE_RS0)
        time.sleep(hayasa)
    I2C_write(0x06,CODE_RS0)#シフト機能OFF
    I2C_write(0x02,CODE_RS0)#カーソル戻す

def LCD_back(kazu):
    for i in range (0,kazu):
        I2C_write(0x10,CODE_RS0)#左にカーソル戻す
        
def LCD_insert(message,hayasa):#入力した際に、文字を左へスクロール カーソルの位置固定
    I2C_write(0x07,CODE_RS0)#シフト機能ON
    for i in range (len (message)):
        I2C_write(ord(message[i]),CODE_RS1)#LCDのRSに1、文字指定
        time.sleep(hayasa)
    I2C_write(0x06,CODE_RS0)#シフト機能OFF
    I2C_write(0x02,CODE_RS0)#カーソル戻す        

def LCD_original():
    I2C_write(0x40,CODE_RS0) #オリジナル文字 1文字目のアドレス指定
    #2文字目は0b01001000 0x48  #3文字目は0b01010000 0x50、以降0x58 0x60 0x68 0x70 0x78 の計8文字
    #      0bxxx00000  左3ビット使わない 5*7ドット
    I2C_write(0b00100,CODE_RS1)
    I2C_write(0b01010,CODE_RS1)
    I2C_write(0b10001,CODE_RS1)
    I2C_write(0b10000,CODE_RS1)
    I2C_write(0b01000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b00001,CODE_RS1)
    I2C_write(0b01000,CODE_RS1)
    I2C_write(0b10000,CODE_RS1)
    I2C_write(0b01100,CODE_RS1)
    I2C_write(0b10010,CODE_RS1)
    I2C_write(0b10010,CODE_RS1)
    I2C_write(0b011100,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b11000,CODE_RS1)
    I2C_write(0b00001,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b01100,CODE_RS1)
    I2C_write(0b10010,CODE_RS1)
    I2C_write(0b10010,CODE_RS1)
    I2C_write(0b11100,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b00100,CODE_RS1)
    I2C_write(0b01010,CODE_RS1)
    I2C_write(0b10010,CODE_RS1)
    I2C_write(0b00010,CODE_RS1)
    I2C_write(0b00100,CODE_RS1)
    I2C_write(0b01000,CODE_RS1)
    I2C_write(0b10000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b00110,CODE_RS1)
    I2C_write(0b01000,CODE_RS1)
    I2C_write(0b00011,CODE_RS1)
    I2C_write(0b00100,CODE_RS1)
    I2C_write(0b01001,CODE_RS1)
    I2C_write(0b00010,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b01000,CODE_RS1)
    I2C_write(0b10000,CODE_RS1)
    I2C_write(0b10001,CODE_RS1)
    I2C_write(0b01110,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b00001,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b00010,CODE_RS1)
    I2C_write(0b00001,CODE_RS1)
    I2C_write(0b10010,CODE_RS1)
    I2C_write(0b01100,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b10000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み
    I2C_write(0b01100,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b11000,CODE_RS1)
    I2C_write(0b00100,CODE_RS1)
    I2C_write(0b10000,CODE_RS1)
    I2C_write(0b01000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)
    I2C_write(0b00000,CODE_RS1)#カーソル用の空白使えない。続けて文字を作成するためには、0で書き込み

def LCD_led():#LEDライトの消灯
    CODE_LED = 0
    data = (0 & 0xF0) | CODE_RS0 | CODE_LED
    I2C.write_byte_data(I2C_add,(data | CODE_E),(data))
    time.sleep(0.0002)
    #命令を2回流さないと、4ビットのずれが出てバグる
    data = (0 & 0xF0) | CODE_RS0 | CODE_LED
    I2C.write_byte_data(I2C_add,(data | CODE_E),(data))
    time.sleep(0.0002)
      
 
def LCD_neko():
    LCD_text('Carrying You',LINE1)
    LCD_text('Castle in Sky',LINE2)
    time.sleep(3)
    LCD_clear()
    
    LIN8C = 0x80
    kanacode = [0x00,0x01,0x02,0x03]
    LCD_katakana(kanacode,LIN8C)
    LIN8C = 0xc0
    kanacode = [0x04,0x05,0x06,0x07]
    LCD_katakana(kanacode,LIN8C)

def destroy():
    timer1.cancel()
    Buzz.stop()
    GPIO.output(26,GPIO.HIGH)
    time.sleep(0.4)
    LCD_print=('--end--')
    LCD_moji(LCD_print,0x85)
    time.sleep(2)
    LCD_r_move(16,0.4)
    LCD_clear()
    LCD_led()
    GPIO.cleanup()
    print ('end')
    

def main():
    for j in range(0,len(kasi_1)):
        LIN8C = 0xc4
        kanacode = kasi_1[j]
        LCD_katakana(kanacode,LIN8C)
        for i in range(0, len(song_1[j])):
            Buzz.ChangeFrequency(song_1[j][i])
            time.sleep(beat_1[j][i] * 0.3) # delay a note for beat
    
    
CL = [1, 131, 147, 165, 175, 196, 211, 248] # Frequency of Bass tone in C major
CM = [1, 261.626, 293.665, 329.628, 349.228, 369.994, 391.995, 415.305,  440, 493.883] # Frequency of Midrange tone in C major
CH = [1, 523.251, 587.330, 659.255, 698.456, 783.991, 880, 987.767] # Frequency of Treble tone in C major

song_1 = [[CM[8],CM[9],CH[1],CM[9],CH[1],CH[3],CM[9],CM[0]],
          [CM[3],CM[8],CM[6],CM[8],CH[1],CM[6],CM[0]],
          [CM[3],CM[3],CM[4],CM[3],CM[4],CH[1],CM[3]],
          [CH[1],CH[1],CH[1],CM[9],CM[5],CM[5],CM[9],CM[9],CM[0]],
          [CM[0],CM[8],CM[9],CH[1],CM[9],CH[1],CH[3],CM[9],CM[0]],
          [CM[3],CM[3],CM[8],CM[6],CM[8],CH[1],CM[6],CM[0]],
          [CM[3],CM[4],CH[1],CM[9],CH[1],CH[2],CH[2],CH[3],CH[1]],
          [CH[1],CM[9],CM[8],CM[8],CM[9],CM[7],CM[8]],
          [CH[1],CH[2],CH[3],CH[2],CH[3],CH[5],CH[2],CH[0]],
          [CM[6],CM[6],CH[1],CM[9],CH[1],CH[3],CH[3],CH[0]],
          [CM[8],CM[9],CH[1],CM[9],CH[1],CH[2],CH[2],CH[1],CM[6],CM[6]],
          [CH[4],CH[3],CH[2],CH[1],CH[3],CH[0]],
          [CH[3],CH[6],CH[5],CH[5],CH[3],CH[2],CH[1]],
          [CH[1],CH[2],CH[1],CH[2],CH[5],CH[3],CH[0]],
          [CH[3],CH[6],CH[5],CH[3],CH[2],CH[1]],
          [CH[1],CH[2],CH[1],CH[2],CM[9],CM[8],CH[0]],
          [CM[8],CM[9],CH[1],CM[9],CH[1],CH[3],CM[9],CM[0]],
          [CM[3],CM[8],CM[6],CM[8],CH[1],CM[6],CM[0]],
          [CM[3],CM[3],CM[4],CM[3],CM[4],CH[1],CM[3]],
          [CH[1],CH[1],CH[1],CM[9],CM[5],CM[5],CM[9],CM[9],CM[0]],
          [CM[0],CM[8],CM[9],CH[1],CM[9],CH[1],CH[3],CM[9],CM[0]],
          [CM[3],CM[3],CM[8],CM[6],CM[8],CH[1],CM[6],CM[0]],
          [CM[3],CM[4],CH[1],CM[9],CH[1],CH[2],CH[2],CH[3],CH[1]],
          [CH[1],CM[9],CM[8],CM[8],CM[9],CM[7],CM[8]]]

beat_1 = [[1,1,3,1,2,2,5,2],
          [2,3,1,2,2,4,1],
          [3,1,3,1,1,3,6],
          [1,1,1,3,1,2,2,3,1],
          [2,1,1,3,1,2,2,3,1],
          [2,1,3,1,2,2,2,3],
          [3,2,1,3,2,1.5,2.5,1,3],
          [2,1,1,1,2,2,6],
          [1,1,3,1,2,2,3,3],
          [1,1,3,1,2,2,7,1],
          [1,1,2,1,1,1,1,3,1,4],
          [2,2,2,2,10,3],
          [3,4,3,1,1,1,5],
          [1,2,1,2,3,5,1],
          [2,4,4,1,1,5],
          [1,2,1,3,2,5,1],
          [1,1,3,1,2,2,5,2],
          [2,3,1,2,2,4,1],
          [3,1,3,1,1,3,6],
          [1,1,1,3,1,2,2,3,1],
          [2,1,1,3,1,2,2,3,1],
          [2,1,3,1,2,2,2,3],
          [3,2,1,3,2,1.5,2.5,1,3],
          [2,1,1,1,2,2,6]]

kasi_1 = [[0xb1,0xc9,0xc1,0xcd,0xb2,0xbe,0xdd],
          [0xb6,0xb6,0xde,0xd4,0xb8,0xc9,0xca],
          [0xc4,0xde,0xba,0xb6,0xc6,0xb7,0xd0,0xa6],
          [0xb6,0xb8,0xbc,0xc3,0xb2,0xd9,0xb6,0xd7],
          [0xc0,0xb8,0xbb,0xdd,0xc9,0xcb,0xb6,0xde],
          [0xc5,0xc2,0xb6,0xbc,0xb2,0xc9,0xca,0x20],
          [0xb1,0xc9,0xc4,0xde,0xda,0xb6,0xcb,0xc4,0xc2,0xc6],
          [0xb7,0xd0,0xb6,0xde,0xb2,0xd9,0xb6,0xd7,0x20,0x20],
          [0xbb,0xb1,0xc3,0xde,0xb6,0xb9,0xd6,0xb3],
          [0xcb,0xc4,0xb7,0xda,0xc9,0xca,0xdf,0xdd],
          [0xc5,0xb2,0xcc,0xd7,0xdd,0xcc,0xdf,0xb6,0xca,0xde,0xdd,0xc6],
          [0xc2,0xd2,0xba,0xdd,0xc3,0xde,0x20,0x20,0x20,0x20,0x20,0x20],
          [0xc4,0xb3,0xbb,0xdd,0xb6,0xde,0xc9,0xba,0xbc,0xc0],
          [0xb1,0xc2,0xb2,0xb5,0xd3,0xb2,0x20,0x20,0x20,0x20],
          [0xb6,0xb1,0xbb,0xdd,0xb6,0xde,0xb8,0xda,0xc0],
          [0xb1,0xc9,0xcf,0xc5,0xbb,0xde,0xbc,0x20,0x20],
          [0xc2,0xb7,0xad,0xb3,0xca,0xcf,0xdc,0xd9],
          [0xb7,0xd0,0xa6,0xb6,0xb8,0xbc,0xc3,0x20],
          [0xb6,0xb6,0xde,0xd4,0xb8,0xcb,0xc4,0xd0],
          [0xb7,0xd7,0xd2,0xb8,0xc4,0xd3,0xbc,0xcb,0xde],
          [0xc2,0xb7,0xad,0xb3,0xca,0xcf,0xdc,0xd9,0x20],
          [0xb7,0xd0,0xa6,0xc9,0xbe,0xc3,0x20,0x20],
          [0xb2,0xc2,0xb6,0xb7,0xaf,0xc4,0xc3,0xde,0xb1,0xb3],
          [0xce,0xde,0xb8,0xd7,0xa6,0xc9,0xbe,0xc3,0x20,0x20]
           ]
 
LCD_set()
LCD_original()
LCD_neko()
GPIO_setup()

main()

destroy()

コメント

  1. J minor より:

    コン太郎さん、新年おめでとうございます。

    ラズパイとはまた奇妙なもののはまっていますね。私は名前すら知りませんでした。

    正直今回の動画も、演奏内容よりも猫たちが気になってしょうがないです(笑)。
    2匹とも元気そうですね。

    こっちも元気ですが、そろそろ避妊手術の時期なのに、かわいそうなんで引き伸ばしてばかりいます・・・。

  2. コン太郎 より:

    J minorさん、こんばんわ、今年もよろしくお願いします。

    ラズパイ知ったのは私も最近ですが、おもちゃの一種だと思って楽しんでいます。

    猫たち、病院行くのすごい嫌がるんですよね~。そして病院の匂いを漂わせるユパさんに、3日ほどテトは威嚇していまし^^

    避妊うんぬんは難しいですよね~、うちは雄二匹なので避妊というよりも、部屋にマーキングされるのが困るという1番の理由ですかね。泌尿系の病気にもなってもらいたくないし。

    環境とお金がゆるすなら、どんどん増えてもらいたい!?です^^

タイトルとURLをコピーしました