Vol.754 14.Sep.2018

マンガン・アルカリ電池の使い分け方 Pythonのおさらい(2)〜内包表現〜 ラズパイ(18)〜WiringPiでサーボモーター制御

B マンガン・アルカリ電池の使い分け方

by fjk

アルカリ電池とマンガン電池との価格差が少なくなって、長寿命でパワーのあるアルカリ電池を使う機会が多くなってきましたが、アルカリ電池を機器にセットしたまま長時間放置しておくと液漏れを起こし、機器本体が使え無くなってしまうことがよくあります。そこで、どんな機器にマンガン電池もしくはアルカリ電池が向いているのか、再確認しました。
 マンガン電池アルカリ電池
特 徴 ○アルカリ電池に比べて液漏れがしにくい
○休み休み使うと電力が回復する
●大電力を必要とする機器には使えない
○マンガン電池よりパワーがある
○使用期限が長い(10年)
●腐食性が高い電解液で液漏れし易い
推奨用途 リモコン、キッチンタイマー、時計、
懐中電灯、ペンライト、・・・
(小電力で、使わない時間が多い)
ヘッドホン、ラジカセ、デジタルカメラ、
電動歯ブラシ、ラジコン、・・・
(パワーが必要、長時間連続使用)
液漏れ対策 液漏れしにくいので、電池消耗チェックが
忘れやすい長期間放置しておく機器に向く
電池の消耗が直ぐ判るように、確認間隔が
短いよく使う機器に向く


P Pythonのおさらい(2) 〜内包表現〜

by fjk

内包表現(comprehension expression、逆は外延extension)とは、リストや辞書などのオブジェクトのループ処理を簡単・シンプルに記述できる記法で、内包表記の種類として次の4つがある。

1.リスト内包
  comp_list = [<式> for <変数> in <反復可能オブジェクト>]
リスト内包は [ ](ブラケット)で定義。戻り値はリスト
  表記例:  [x + 2 for x in range(5)]
2.ジェネレータ式
  comp_gen = (<式> for <変数> in <反復可能オブジェクト>)
ジェネレータ式は ( )(パーレン)で定義。戻り値はイテレータ
  表記例:  (x + 2 for x in range(5)) 
3.セット内包 (セットはリストと異なり重複要素は取り除かれる)
  comp_set = {<式> for <変数> in <反復可能オブジェクト>}
セット内包は { }(ブレース)で定義。
  表記例: {x + 2 for x in range(5)}
4.辞書内包
  comp_dict = {<式(key: value)> for <変数> in <反復可能オブジェクト>}
辞書内包も { } (ブレース)で定義。戻り値は辞書。セット内包と異なり各要素の値の部分が key : value
  表記例:  li = [("C", 1972), ("Java", 1995), ("JavaScript", 1995)]
      {k: v for k, v in li}
●for文のネスト ・・・for文のネストは可能だが変数の順に注意
 表記例:  comp_list = [i * j for i in range(1, 10) for j in range(1, 10)]
●if文 ・・・・ifを使うと条件を同時に記述できる(if文はfor文の後に後述)
 表記例:  [x ** 2 for x in range(10) if x % 2 == 0]
●if〜else文 ・・・・if文のみと異なりif〜eles文は3項演算子的に使用(forの前に前述)
 表記例:  [x if x % 3 == 0 else 'fizz' for x in range(10)]
※Pythonの三項演算子は以下の書式なので、
   `真の値` if `条件式` else `偽の値`
三項演算子をリスト内包表現で使うには、以下の様に記述する。
  [`真の値` if `条件式` else `偽の値` for `任意の変数名` in `イテラブルオブジェクト`]
【シーケンスデータを扱う組み込み関数の例】
@ filter関数(リストの要素を抽出してくれる関数
python3ではイテレータを返す(python2ではリスト)
<書式> (使用例は右図)
  filter(func,iterable,・・)
<同じ処理をラムダ式で記述>
  list(filter(lambda x : x % 2 == 1 , range(1, 10)))
<結果>どちらも
  >>> 1,3,5,7,9

<奇数を取り出すfilter使用例>
def is_mod(x):
    return x % 2 == 1

list(filter(is_mod, range(1 ,10)))
  
A map関数(リストの要素に演算を適用してくれる関数)
python3ではイテレータを返す(python2ではリスト)
<書式> (使用例は右図)
  map(func,iterable,・・)
<同じ処理をラムダ式で記述>
  map(lambda x : x * x , range(1, 10))
<結果>どちらも
  >>> 1,4,9,16,25

<mapによる要素毎の演算例>
def square(x):
    return x * x

list(map(square , range(1 ,5)))
  
B zip関数(2つ以上のリストを同時に扱う場合の関数)
各イテラブルから要素を集めたイテレータを作る。
要素の最短の長さのイテレータを返す
<書式>
  zip(iterable1, iterable2, ...)
<使用例1>(リストの要素同士を掛ける)
  >>> 4,10,18
<使用例2>(行・列変換)
  >>> 1 4 7
  >>> 2 5 8
  >>> 3 6 9

<zip使用例1>
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [x * y for x, y in zip(list1, list2)]
print(list3)

<zip使用例2>
list={[1,2,3],[4,5,6],[7,8,9]}
for (a,b,c)in zip(*list):
  print a,b,c


R ラズベリーパイ(18) 〜WiringPiでサーボモータ制御〜

by fjk

abc752で作成したPWMパルスはソフトウェアで作成したため精度が悪く、モーターがふらつくことがある。そこで、ハードウェアで高精度のパルス幅を得るため(ALT5モード)WiringPiを利用し、安価なサーボモーター(SG-90、\400)をラズパイで制御した。
 サーボモータ制御を行う前に、LED点灯でWiringPiの使い方や動作をテストする。

【WiringPiのインストールとテスト】

1.WiringPiが既にインストールされているか確認
$ pip list または $ pip show wiringpi
2.python-devとpython-pipをインストール
$ sudo apt-get install python-dev python-pip
3.WiringPiのインストール
$ sudo pip install wiringpi2
wiringpiとwiringpi2両方がインストールされる(wiringpiの方が新しい)
 
4.WirintPiの実行はrootでなければならないので
$ sudo idle & または $ sudo python で起動
5.LEDの点滅スケッチでWiringPiの動作を確認
import wiringpi as wp  ・・ライブラリーの読込
wp.wiringPiSetup()   ・・・初期設定
wp.pinMode(LED, GPIO.OUT)
wp.digitalWrite(LED, GPIO.HIGH)
6.PWMで制御する場合
ピンモードはwp.GPIO.PWM_OUTPUT
wp.pwmSetMode(wp.PWM_MODE_MS)
wp.pwmSetRange(1920)
wp.pwmSetClock(200)
wp.pwmWrite(LED,duty)

<SG-90の主な仕様>
  パルス幅:  0.5〜2.4mS
  周波数:   50Hz(20mS)
  静止トルク: 1.8kgf
  動作電圧:  4.8〜5V
  レンジ:   1920
wp_LED.py
# use for python2
import wiringpi as wp
from time import sleep
LED = 23

wp.wiringPiSetupGpio()
wp.pinMode(LED, wp.GPIO.OUTPUT)

while True:
    wp.digitalWrite(LED, 1)
    sleep(5)
    wp.digitalWrite(LED, 0)
    sleep(5)
 wp_LEDb.py

LED_PWM波形
(Balanceモード、50%、5mS/Div)
# use for python2
import wiringpi as wp
LED = 18

wp.wiringPiSetupGpio()
wp.pinMode(LED,wp.GPIO.PWM_OUTPUT)
wp.pwmSetRange(1920)
wp.pwmSetClock(200)

try:
  while True:
    duty = input("duty? : ")
    if duty< 1 or duty > 100:
      break
    wp.pwmWrite(LED,duty)

finally:
    print "End"

【Wiringpiを使ってサーボモーター制御】
 WiringPiのPWM波形のデフォルトはBalanceモード(周波数が変わる)でパルスが下図のように平均化され、期待するパルス幅が得られないので、Mark-Spaceモード(周波数一定)を指定する必要がある。
  

1.サーボモータの制御にはMark-Spaceモードを指定する
pwmSetMode(GPIO.PWM_MODE_MS)
2.パルス幅 角度 指定数(= パルス幅÷サイクル×レンジ)
-90:  48(= 0.5/20*1920)
0:  139(= 1.45/20*1920)
90:  230(= 2.4/20*1920)
3.ソフトモードとハードモード
@ソフトモード:softPwmWrite(pin,value)  ・・全GPIOピン利用可
     softPwmCreate(ピン,初期値,レンジ) で条件設定、通常(pin,0,100)。
Aハードモード:pwmWrite(pin,value)   ・・GPIO 18,19,12,.13ピンのみ利用可
     pwmSetRange(レンジ)pwmSetClock(クロック)  で条件設定
     50Hz = 19200000Hz(RaspPi_clock)÷1920(Range)÷200(Clock) で計算

※ソフトモードではサイクルタイムが10mS固定なのでSG-90サーボ制御(要20mS)には不適。

<ハードモードservo-h.py   <ソフトモードservo-s.py

# use for python2

from wiringpi import *
PWM0 = 18
#PWM1 = 19

def setupMotor(id):
  wiringPiSetupGpio()
  pinMode(id, GPIO.PWM_OUTPUT)
  pwmSetMode(GPIO.PWM_MODE_MS)
  pwmSetRange(1920)
  pwmSetClock(200) 

if __name__ == '__main__' :
  try:
    setupMotor(PWM0)
    print "setup GPIO:" ,PWM0
    while True:
      angle = input("count? : ")
      if angle == 0:
        pwmWrite(PWM0, 139)
        print "Move -> 0"
        break
      elif angle < 48 or angle > 230:
        print "ERROR: range(48-230)"
      else:
        pwmWrite(PWM0, angle)
        print "Move -> ",angle

  finally:
    print "End"
 

# use for python2

import wiringpi as wp
PWM_PIN = 23


def setupMotor(id):
  wp.wiringPiSetupGpio()
  wp.pinMode(id,wp.PWM_OUTPUT)

  wp.softPwmCreate(id,0,100)


if __name__ == '__main__' :
  try:
    setupMotor(PWM_PIN)
    print "setup GPIO:" ,PWM_PIN
    while True:
      duty = input("duty(%)? : ")
      if duty == 0:
        wp.softPwmWrite(PWM_PIN, 0)
        print "duty -> 0"
        break
      elif duty < 0 or duty > 99:
        print "ERROR: range (0-99)"
      else:
       wp.softPwmWrite(PWM_PIN,duty)
       print "duty -> ",duty

  finally:
    print "End"

サーボモーター配線図 サーボモーター制御中
ハードモード波形例(Mark-Spaceモード、1mS)
(ソフトを止めても出力は継続、5mS/Div)
ソフトモード波形例(10%)
(サイクル間隔は10mS、5mS/Div)
ハードモード
(GPIO18がALT5になっている)
ソフトモード
(GPIO23がOUTになっている)


マンガン・アルカリ電池の使い分け方 Pythonのおさらい(2)〜内包表現〜 ラズパイ(18)〜WiringPiでサーボモーター制御