今回もラズパイの記事です。いや~まじ楽しいです。
楽しいけど、あまりにもソロギターと畑違いなので、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()

コメント
コン太郎さん、新年おめでとうございます。
ラズパイとはまた奇妙なもののはまっていますね。私は名前すら知りませんでした。
正直今回の動画も、演奏内容よりも猫たちが気になってしょうがないです(笑)。
2匹とも元気そうですね。
こっちも元気ですが、そろそろ避妊手術の時期なのに、かわいそうなんで引き伸ばしてばかりいます・・・。
J minorさん、こんばんわ、今年もよろしくお願いします。
ラズパイ知ったのは私も最近ですが、おもちゃの一種だと思って楽しんでいます。
猫たち、病院行くのすごい嫌がるんですよね~。そして病院の匂いを漂わせるユパさんに、3日ほどテトは威嚇していまし^^
避妊うんぬんは難しいですよね~、うちは雄二匹なので避妊というよりも、部屋にマーキングされるのが困るという1番の理由ですかね。泌尿系の病気にもなってもらいたくないし。
環境とお金がゆるすなら、どんどん増えてもらいたい!?です^^