ここではべゼリーにアナログセンサーの値を入力する例として、べゼリーの頭に光センサーをつけてみます。
・べゼリーの頭頂の穴は、アナログの光センサーをとりつけることを想定しています。光センサーをつけることで、部屋が明るくなったり暗くなったりしたときにべゼリーを反応させることができますが、明るい場所でべゼリーの頭を撫ぜたときにも反応させることができます。
・今回は「CdSセル」とも呼ばれる光センサーを使います。CdSとは硫化カドミウムのことで、明るい場所ほど抵抗値が小さくなる性質があります。1個100円以下で買えます。(共立エレショップ)
・本当かどうか、テスターをもっている人は、CdSセルの抵抗値を測ってみましょう。てのひらで覆うなどして明るさを変えると、抵抗値が変化することがわかります。
・残念ながらラズベリーパイのGPIO(汎用入出力ピン)に接続できるセンサーは基本的に、結果をデジタル値で返すデジタルセンサーだけです。なのでCdSセルのようなアナログセンサーをラズパイにつなぐ際には、アナログ値をデジタル値に変換する、ADC(アナログ・デジタル・コンバーター)が必要になります。
・今回は4チャンネル12ビットのADC「MCP3204」を使います。秋月電子通商で360円で買いました。これには7対の足が生えており、4つのアナログセンサーから値を入力することができます。ちなみにMCP3208は8対の足が生えており、8つまでのアナログ値を入力できます。
・取扱説明書にピン配置が書いてあります。ラズパイとの接続は電源2本とシリアル(SPI=Serial Peripheral Interface)4本。合計6本のケーブルで接続します。
・MCP3204をブレッドボードに差し込みます。写真だとわかりにくいですが、きりかきが左に向いています。配線をコンパクトにするため硬いジャンパー線を3本使ってますが、もちろん柔らかいジャンパー線でも構いません。プルアップ抵抗として抵抗値の大きな抵抗をCdSの回路に入れます。ここでは10kΩを使っています。
・写真を参考にしながら、ブレッドボードとラズパイをジャンパーケーブル(オス・メス)でつないでください。
・Vdd=Vref=ラズパイの3.3v電源に接続。
・DGND=AGND=ラズパイのGNDに接続
・CLK=ラズパイのSPI SCLKに接続
・Dout=ラズパイのSPI MISOに接続
・Din=ラズパイのSPI MOSIに接続
・CS/SHDN=ラズパイのSPI CE0に接続
・CH0=CdSセルに接続
・こんな感じになったでしょうか?
・べゼリーの頭部パーツにCdSセルを固定します。ゼリー状の瞬間接着剤やパテでも良いかもしれませんが、筆者の場合は裏側からグルーガン(ホットボンド)で固定しました。
・べゼリーの後頭部の切れ目は、ケーブルを固定するためのものです。
・台座の中にすべてを収めてフタをしめたら完成です。
サンプルプログラム1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
#!/usr/bin/python # -*- coding: utf-8 -*- # Bezelie Sample Code for Raspberry Pi : アナログ入力のサンプル # ラズパイにADコンバータとアナログセンサーを接続しておいてください。 # ライブラリの読み込み import RPi.GPIO as GPIO from time import sleep # MCP3204からSPI通信で12ビットのデジタル値を取得。4チャンネル使用可 def readadc(adcnum, clockpin, mosipin, misopin, cspin): if adcnum > 7 or adcnum < 0: return -1 GPIO.output(cspin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) GPIO.output(cspin, GPIO.LOW) commandout = adcnum commandout |= 0x18 # スタートビット+シングルエンドビット commandout <<= 3 # LSBから8ビット目を送信するようにする for i in range(5): # LSBから数えて8ビット目から4ビット目までを送信 if commandout & 0x80: GPIO.output(mosipin, GPIO.HIGH) else: GPIO.output(mosipin, GPIO.LOW) commandout <<= 1 GPIO.output(clockpin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) adcout = 0 # 13ビット読む(ヌルビット+12ビットデータ) for i in range(13): GPIO.output(clockpin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) adcout <<= 1 if i>0 and GPIO.input(misopin)==GPIO.HIGH: adcout |= 0x1 GPIO.output(cspin, GPIO.HIGH) return adcout # 初期設定 GPIO.setmode(GPIO.BCM) # 変数 SPICLK = 11 SPIMOSI = 10 SPIMISO = 9 SPICS = 8 # SPI通信用の入出力を定義 GPIO.setup(SPICLK, GPIO.OUT) GPIO.setup(SPIMOSI, GPIO.OUT) GPIO.setup(SPIMISO, GPIO.IN) GPIO.setup(SPICS, GPIO.OUT) # 関数 def main(): try: print "開始します" while True: inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) print(inputVal0) sleep(0.2) except KeyboardInterrupt: print "終了しました" GPIO.cleanup() # ポートをクリア # 直接実行された場合の処理 if __name__ == "__main__": main() |
・アナログセンサから取得した数値を0.2秒おきに表示するプログラムです。
・アナログセンサー(今回はCdSセンサー)の値をいろいろ変えてみて、べゼリーを動かすきっかけとしてちょうどよい数字を探しましょう。
・筆者の場合は室内でCdSセンサーの上に手をかざすと、だいたい1000よりも小さな値になることがわかりましたので、「しきい値」は1000にしました。
サンプルプログラム2
・sample_aInput1.pyとほとんど同じですが、CdSセンサーの値が1000よりも小さかったらべゼリーが体を動かし、声を発するように処理が追記されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
#!/usr/bin/python # -*- coding: utf-8 -*- # Bezelie Sample Code for Raspberry Pi : アナログ入力のサンプル # 事前にsample_aInput1.pyを実行し、しきい値を決めておいてください。 # ライブラリの読み込み import RPi.GPIO as GPIO import subprocess # 外部プロセスを実行するモジュール import bezelie from time import sleep # 準備 bez = bezelie.Control() # べゼリー操作インスタンスの生成 bez.moveCenter() # サーボをセンタリング sleep(0.5) # MCP3204からSPI通信で12ビットのデジタル値を取得。4チャンネル使用可 def readadc(adcnum, clockpin, mosipin, misopin, cspin): if adcnum > 7 or adcnum < 0: return -1 GPIO.output(cspin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) GPIO.output(cspin, GPIO.LOW) commandout = adcnum commandout |= 0x18 # スタートビット+シングルエンドビット commandout <<= 3 # LSBから8ビット目を送信するようにする for i in range(5): # LSBから数えて8ビット目から4ビット目までを送信 if commandout & 0x80: GPIO.output(mosipin, GPIO.HIGH) else: GPIO.output(mosipin, GPIO.LOW) commandout <<= 1 GPIO.output(clockpin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) adcout = 0 # 13ビット読む(ヌルビット+12ビットデータ) for i in range(13): GPIO.output(clockpin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) adcout <<= 1 if i>0 and GPIO.input(misopin)==GPIO.HIGH: adcout |= 0x1 GPIO.output(cspin, GPIO.HIGH) return adcout # 初期設定 GPIO.setmode(GPIO.BCM) # 変数 ttsFile = "/home/pi/bezelie/edgar/exec_openJTalk.sh" # 発話シェルスクリプトのファイル名 SPICLK = 11 SPIMOSI = 10 SPIMISO = 9 SPICS = 8 # SPI通信用の入出力を定義 GPIO.setup(SPICLK, GPIO.OUT) GPIO.setup(SPIMOSI, GPIO.OUT) GPIO.setup(SPIMISO, GPIO.IN) # 関数 def main(): try: print "開始します" while True: inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) print(inputVal0) if inputVal0 < 1000: # しきい値は条件によって変えてください。 bez.moveAct("happy") # しあわせアクション subprocess.call("sh "+ttsFile+" "+"にゃ", shell=True) bez.stop() # サーボ停止命令 sleep(1) except KeyboardInterrupt: print "終了しました" GPIO.cleanup() # ポートをクリア # 直接実行された場合の処理 if __name__ == "__main__": main() |
・以下が実行結果です。頭が暗くなったら体を動かして声を出しているだけなのですが、まるで撫でられたから反応したように見えますよね。
応用
べゼリーに接続できるアナログセンサーとしては、ジョイスティックやボリュームもあります。
・これはジョイスティックの上下左右でべゼリーの頭部を動かし、ボリュームでべゼリーの体を回転できるようにした例です。さらに肩に乗せるウェアラブルロボットとして作ってみました。
・ショルダーバッグ(虫かご)についているジョイスティックとボリュームで、肩の上のべゼリーをコントロールすることができます。
・2018年3月、ラズベリーパイの誕生日イベントで展示した際の映像です。黄色とオレンジのボタンを押すと、発話するようにしました。
・2018年3月、アメリカのテキサス州オースチンで行われた音楽と映画とテクノロジーの祭典「サウス・バイ・サウスウエスト」では、多くのかたに肩乗せべゼリーを体験していただきました。写真を見ればお分かりの通り、国籍を問わず、みんな笑顔です。