・bezelie.pyはべゼリー専用のプログラムです。
・pythonプログラムにモジュールとしてimportすることで、サーボドライバーを通じて3つのサーボを簡単に制御することができます。
各種モジュールのインポート
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
クラス初期化時の処理
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
・data_chat.jsonからサーボのセンタリング位置を読み取り、変数に代入しています。
各サーボを動かす関数
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
・べゼリーの3つのサーボには名前がついています。首を上下に振るサーボがHead、首の横振りがBack、体の回転がStageです。
サーボドライバーPCA9685の初期化処理
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
moveServo:サーボを目的の角度まで回転させる関数
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
複数のサーボを簡単に動かしたいときのための関数
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
・moveRnd()はランダムで感情アクションを実行します。
・moveAct()は指定された感情アクションを実行します。
感情アクション関数
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
・6種類の感情アクションが設定されています。
直接実行された場合の処理
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Bezelie Python Module for Raspberry Pi
# べゼリー専用モジュール
from random import randint # 乱数の発生
from time import sleep # ウェイト処理
import RPi.GPIO as GPIO # GPIO
import smbus # I2C
import math # 計算用
import threading # マルチスレッド処理
import json # jsonファイルを扱うモジュール
bus = smbus.SMBus(1)
# 変数
jsonFile = "/home/pi/bezelie/edgar/data_chat.json" # 設定ファイル
class Control(object): # クラスの定義
# 初期化メソッド。インスタンス生成時に自動実行される。
def __init__(self, address_pca9685=0x40, dutyMax=490, dutyMin=110, dutyCenter=300, steps=1):
f = open (jsonFile,'r')
jDict = json.load(f)
self.headTrim = int(jDict['data2'][0]['head']) # トリム値の読み込み
self.backTrim = int(jDict['data2'][0]['back'])
self.stageTrim = int(jDict['data2'][0]['stage'])
# インスタンス変数に値を代入。selfは自分自身のインスタンス名。
self.address_pca9685 = address_pca9685
self.dutyMax = dutyMax
self.dutyMin = dutyMin
self.dutyCenter = dutyCenter
self.steps = steps
self.headNow = dutyCenter
self.backNow = dutyCenter
self.stageNow = dutyCenter
self.initPCA9685()
# 第1引数はselfにするのが義務。
def moveHead(self, degree, speed=1):
max = 320 # 下方向の限界
min = 230 # 上方向の限界
self.headNow = self.moveServo(2, degree, self.headTrim, max, min, speed, self.headNow)
def moveBack(self, degree, speed=1):
max = 380 # 反時計回りの限界
min = 220 # 時計回りの限界
self.backNow = self.moveServo(1, degree, self.backTrim, max, min, speed, self.backNow)
def moveStage(self, degree, speed=1):
max = 390 # 反時計回りの限界
min = 210 # 時計回りの限界
self.stageNow = self.moveServo(0, degree, self.stageTrim, max, min, speed, self.stageNow)
def moveCenter(self): # 3つのサーボの回転位置をトリム値に合わせる
self.moveHead(self.headTrim)
self.moveBack(self.backTrim)
self.moveStage(self.stageTrim)
def initPCA9685(self):
try:
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
freq = 0.9 * 50
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
prescale = int(math.floor(prescaleval + 0.5))
oldmode = bus.read_byte_data(self.address_pca9685, 0x00)
newmode = (oldmode & 0x7F) | 0x10
bus.write_byte_data(self.address_pca9685, 0x00, newmode)
bus.write_byte_data(self.address_pca9685, 0xFE, prescale)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode)
sleep(0.005)
bus.write_byte_data(self.address_pca9685, 0x00, oldmode | 0xa1)
except:
print "サーボドライバーボードを接続してください"
# pass
def resetPCA9685(self):
bus.write_byte_data(self.address_pca9685, 0x00, 0x00)
def setPCA9685Duty(self, channel, on, off):
channelpos = 0x6 + 4*channel
try:
bus.write_i2c_block_data(self.address_pca9685, channelpos, [on&0xFF, on>>8, off&0xFF, off>>8])
except IOError:
pass
def moveServo(self, id, degree, trim, max, min, speed, now):
dst = (self.dutyMin - self.dutyMax) * (degree + trim + 90) / 180 + self.dutyMax
if speed == 0:
self.setPCA9685Duty_(id, 0, dst)
sleep(0.001 * math.fabs(dst - now))
now = dst
if dst > max:
dst = max
if dst < min:
dst = min
while (now != dst):
if now < dst:
now += self.steps
if now > dst:
now = dst
else:
now -= self.steps
if now < dst:
now = dst
self.setPCA9685Duty(id, 0, now)
sleep(0.004 * self.steps *(speed))
return (now)
def moveRnd(self):
self.stop_event = threading.Event()
r = randint(1,7)
if r == 1:
self.thread = threading.Thread(target = self.actHappy)
elif r == 2:
self.thread = threading.Thread(target = self.actNod)
elif r == 3:
self.thread = threading.Thread(target = self.actWhy)
elif r == 4:
self.thread = threading.Thread(target = self.actAround)
elif r == 5:
self.thread = threading.Thread(target = self.actUp)
elif r == 6:
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def moveAct(self, act):
self.stop_event = threading.Event()
if act == 'happy':
self.thread = threading.Thread(target = self.actHappy)
elif act == 'nod':
self.thread = threading.Thread(target = self.actNod)
elif act == 'why':
self.thread = threading.Thread(target = self.actWhy)
elif act == 'around':
self.thread = threading.Thread(target = self.actAround)
elif act == 'up':
self.thread = threading.Thread(target = self.actUp)
elif act == 'wave':
self.thread = threading.Thread(target = self.actWave)
else:
self.thread = threading.Thread(target = self.actEtc)
self.thread.start()
def actHappy(self, time=0.2): # しあわせ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(5)
self.moveBack(-5)
self.moveBack(0)
sleep (time)
self.moveHead(0)
def actNod(self, time=0.2): # うなづき
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def actWhy(self, time=0.2): # 首かしげ
while not self.stop_event.is_set():
self.moveHead(10)
self.moveBack(20)
sleep (time)
self.moveBack(0)
self.moveHead(0)
def actAround(self, time=0.2): # 見回し
while not self.stop_event.is_set():
self.moveStage(20)
self.moveStage(-20)
self.moveStage(0)
def actUp(self, time=0.2): # 見上げ
while not self.stop_event.is_set():
self.moveHead(30)
sleep (time)
self.moveHead(0)
def actWave(self, time=0.2): # くねくね
while not self.stop_event.is_set():
self.moveBack(20)
self.moveStage(10)
self.moveStage(-10)
self.moveStage(0)
self.moveBack(0)
def actEtc(self, time=0.5): # ETC
while not self.stop_event.is_set():
self.moveHead(-10)
sleep (time)
self.moveHead(0)
def stop(self):
self.stop_event.set()
self.thread.join()
# スクリプトとして実行された場合はセンタリングを行う
if __name__ == "__main__":
bez = Control() # べゼリー操作インスタンスの生成
f = open (jsonFile,'r')
jDict = json.load(f)
bez.headTrim = int(jDict['data2'][0]['head'])
bez.backTrim = int(jDict['data2'][0]['back'])
bez.stageTrim = int(jDict['data2'][0]['stage'])
bez.moveCenter()
・コマンドラインから直接実行された場合は、サーボのセンタリングを行います。