Vol.755 28.Sep.2018

センサーカメラ(電池式) ラズベリーパイ(19)〜GPIOZeroによるAD変換〜

C センサーカメラ(電池式)

by fjk

防犯用などに監視カメラがありますが、電源の確保や高価格の問題があります。既にカメラはあるのですが、さらに死角をなくすために、なるべく安価に設置したいと思い、ネットで探してみると、@乾電池式で配線不要、A屋外・屋内のどこでも付けられる、B赤外線LEDで夜間でも撮影可能、C安価、のセンサーカメラ(SD1000、REVEX製、\3,930)を見つけ、アマゾンで入手した。
 カタログによると、SD1000は新品単3アルカリ電池3本で、15秒の動画を1000回程度撮影することが出来とある(センサーライトOFF時)。センサーの感知距離は10m先の人物も感知する。しかし、センサーの直ぐ前を横切る人は、録画開始が間に合わず、人物の録画が出来ていなかった。
 どんなときにも対応というわけには行かないが、安価で簡単に使えるのは便利で、畑の果物や野菜泥棒の監視への利用例がTVでも紹介されている(ゴミの不法投棄監視にも使えるかな・・)。。

SD1000電池式センサカメラ カメラの裏側(スイッチとカードスロット)
撮影例(昼間) 撮影例(夜間)


R ラズベリーパイ(19) 〜GPIOZeroによるAD変換〜

by fjk

ラズペリーパイにはアルディーノと異なり、アナログ信号の電圧値を測定する端子が無い。そこで、よく使われるのがA/D変換ICが使われる。AD変換器としてSPI接続のMCP3208を用い、光が当たると抵抗値が変化するPDS光センサのアナログ電圧出力値をラズパイに取り込みを行った。

1.ラズパイの設定でSPIを有効にする
2.GPIOZeroの使い方とLED点灯動作確認
 GPIOZeroはラズベリーパイのGPIOデバイスとの簡単なインタフェースとして開発され、ごくわずかなコードでいろいろなことが出来ます。
 ライブラリには、センサー、アナログデジタル変換器、フルカラーLED、ロボットなどへのインターフェースが準備されています。
 GPIOZeroはjessieにデフォルトでインストールされるが、GPIOZeroが使える確認するには
    $ pip list または $ pip show gpiozero
実験回路図 配線状況
【LEDの点灯テスト】(abc-746参照)
GPIOZeroの動作を確認するため、SWを押すとLEDが点灯する例でテストする。
 @gpiozeroをインポートする
 ALEDの接続ピンの指定
 Bプッシュスイッチのピンを指定
 Cwhen_pressedメソッドを使い、ボタンが押されたらledをon(点灯)する
 Dwhen_releasedメソッドを使い、ボタンが離されたらledを消灯する。
 Epause()はプログラムを終了させずにイベントの発生を待つ。
 Fwhen,〜メソッドはイベントを発生させ、指定された処理を行う。
<GPIOZeroによるLED点灯テスト(gpzeroled.py)>

from gpiozero import LED
from gpiozero import Button
from signal import pause

led = LED(17)
button = Button(23)

button.when_pressed = led.on
button.when_released = led.off
pause()

【LEDの点滅】(abc-747参照)
class gpiozero.LED(pin, *, active_high=True, initial_value=False , pin_factory=None)
LEDの点灯にはon()、消灯にはoff()を使う。
LEDの状態を反転するにはtoggle()を使う。
LEDを点滅させるには.blink()を使う。
<GPIOZeroによるLED点滅(gpzeroblink.py)>

from gpiozero import LED
from signal import pause
led = LED(17)
led.blink()
pause()

3.MCP3208によるアナログ電圧の測定
ADCを使う場合、チップ(MCP3001,3002,3004,3008,3201,3202,3204.,3208,3301,3302,3304)に応じたモジュールが準備されている(以下MCP3208の場合)。
class gpiozero.MCP3208(channel=0, differential=False, max_voltage=3.3, **spi_args)
  channel:測定するチャンネル(0−7)
  differential:trueなら差動モード(デフォルトはfales)
測定データを得るにはvalueプロパティを読み出す。
  .value:測定データ(0.0〜1.0)、差動時は-1.0〜+1.0
【ADCの使い方】
@使用するA/Dコンバータを宣言
  (ADチャンネルとして、CDSはch0、VRはch1、使用するデバイスに合わせて選択)
A.valueを読み出す。
<GPIOZeroによるAD変換(gpzeroadc.py)>   <spidevライブラリによるAD変換(spitest.py)>

from gpiozero import MCP3208
Vref = 3.29476

pot = MCP3208(channel = 0)
print(str(pot.value * Vref)+" V")
 

importt spidev
vref = 3.29476

spi = spidev.SpiDev()
spi.open(0,0)                          # spi_bus=0, cs=0
adc = spi.xfer2([0x06,0x00,0x00])      # Singleend, ,ch=0
data = ((adc[1] & 0xff)<< 8) | adc[2]
print ( str(Vref * data / 4095) + "V")
spi.close()
 
CDS電圧測定例(gpiozero)   CDS電圧測定例(spidev)


【GPIOZeroの応用例】( https://gpiozero.readthedocs.io/を参考にした)
今までのラズパイ応用例をGPIOZeroで記述し直すと・・

5.RGBLED (フルカラーLEDの場合、abc748を参照)
class gpiozero.RGBLED(red, green, blue, *, active_high=True, initial_value=(0, 0, 0), pwm=True, pin_factory=None)
PWMがTrue(default)なら、0.0〜1.0をcolorプロパティに指定することで明るさを可変できる。
(他の使用方法として前述のLEDの例も参照)
<GPIOZeroによるカラーLED制御(gpzerocled.py)>

from gpiozero import RGBLED
led = RGBLED(17, 27, 22 , pwm=True)
led.color = (1.0, 0.0, 1.0)

6.モーター (ドライバーにTA7291Pを使う場合、配線はabc752を参照)
class gpiozero.Motor(forward, backward, *, pwm=True, pin_factory=None)
  forwardは順方向への接続ピン番号
  backwardは逆方向への接続ピン番号
  pwmをTrueにするとスピード制御が可能
・順方向へモータを回すにはforward()を使う
  forward(speed=1) speedは0.0〜1.0(最大)
・逆方法へモータを回すにはbackward()を使う
  backward(speed=1) speedは0.0〜1.0(最大)
・方向を変えるにはreverse()を使う(速度は同じ)
・モータを止めるにはstop()を使う
<GPIOZeroによるDCモータ制御(gpzerodcm.py)>

from gpiozero import Motor
from time import sleep
motor = Motor(forward=23, backward=24)
print("start")
motor.forward()
sleep(2)
motor.backward()
sleep(2)
motor.stop()
print("end")

7.サーボモーター制御(abc754を参照)
class gpiozero.Servo(pin, *, initial_value=0, min_pulse_width=1/1000,max_pulse_width=2/1000, frame_width=20/1000, pin_factory=None)
 ・pinはGPIOピン番号
 ・最小パルス幅はmin_pulse_widthで指定(秒)
 ・最大パルス幅はmax_pulse_widthで指定(秒)
 ・パルス間隔はframe_widthで指定(秒)、デファオルトは20mS
 ・初期位置はinitial_valueで指定(-1.0〜1.0)、デフォルトの0にするとmaxとminの中間点となる
 ・位置の指定は-1.0(min位置)から1.0(max位置)をvalueプロパティで指定する
<GPIOZeroによるサーボモータ制御(gpzeroservo.py)>

from gpiozero import Servo
from time import sleep
servo = Servo(17)
while True:
  servo.min()
  sleep(1)
  servo.max()
  sleep(1)
  servo.mId()
  sleep(1)


 ≪角度で回転位置を指定するAngulerServo≫
class gpiozero.AngularServo(pin, *, initial_angle=0, min_angle=-90, max_angle=90 , min_pulse_width=1/1000 , max_pulse_width=2/1000 , frame_width=20/1000, pin_factory=None)
AngulerServoモジュールを使うと、パルス幅では無く、角度でモータを制御できる。例では、-90〜+90の範囲で角度を指定する。
<GPIOZeroによるサーボモータ角度制御(gpzeroangservo.py)>

from gpiozero import AngularServo
s = AngularServo(17, min_angle=-42, max_angle=44)
s.angle = 0.0


8.ロボット
2個のモーターを制御して前進、更新、右左折を制御する場合は,robotモジュールが使える
class gpiozero.Robot(left=None, right=None, pin_factory=None)
  leftは左モータの2つの配線ピン番号をタブルで指定。
  rightは右モータの2つの配線ピン番号をタブルで指定。
  forward(speed=1, **kwargs)   ・・前進を指定(0.0〜1.0)
  curve_left (float343)      ・・前進しながら左モータを減速(減速率を指定)
  curve_right (float344)     ・・前進しながら右モータを減速(減速率を指定)
  backward(speed=1, **kwargs)   ・・後退を指定
  curve_left (float343)      ・・後退しながら左モーターを減速(減速率を指定)
  curve_right (float344)     ・・後退しながら右モーターを減速(減速率を指定)
  left(speed=1)          ・・超信地旋回(スピンターン)による左回転
  right(speed=1)         ・・超信地旋回(スピンターン)による右回転
  reverse()            ・・モータ回転方向を逆にする(速度はそのまま)

 ≪ロボット動作テスト≫
前進、右旋回、左旋回、後退、停止
<GPIOZeroによるロボット制御(gpzerorobo.py)>

from gpiozero import Robot
from time import  sleep
robot = Robot(left=(4, 14), right=(17, 18))

for i in range(4):
    robot.forward()
    sleep(10)
    robot.right()
    sleep(1)
    robot.left()
    sleep(1)
    robot.backward()
    sleep(1)
    robot.stop()

 ≪4つのボタンでロボットの走行を制御≫
<GPIOZeroによるロボット制御(gpzerorobo4b.py)>

from gpiozero import Button, Robot
from time import sleep
from signal import pause
robot = Robot((17, 18), (22, 23))

left = Button(2)
right = Button(3)
forward = Button(4)
backward = Button(5)
go = Button(6)
instructions = []

def add_instruction(btn):
  instructions.append({
    left: (-1, 1),
    right: (1, -1),
    forward: (1, 1),
    backward: (-1, -1),
  }[btn])

def do_instructions():
  instructions.append((0, 0))
  robot.source_delay = 0.5
  robot.source = instructions
  sleep(robot.source_delay * len(instructions))
  del instructions[:]

go.when_pressed = do_instructions
for button in (left, right, forward, backward):
  button.when_pressed = add_instruction

pause()


 ≪2つの可変抵抗タイプステックで制御≫
ADCのMCP3208と可変抵抗タイプステック を使って走行ロボットを制御。
zip関数を使うのでpython3で実行すること。
<GPIOZeroによるロボット制御(gpzerorobo2s.py)>

from gpiozero import Robot, MCP3208
from signal import pause

robot = Robot(left=(4, 14), right=(17, 18))
left  = MCP3208(0) 
right = MCP3208(1)
robot.source = zip( scaled(left.values,,-1,1) , scaled(right.values),-1,1) )
pause()


センサーカメラ(電池式) ラズベリーパイ(19)〜GPIOZeroによるAD変換〜