読者です 読者をやめる 読者になる 読者になる

Raspberry Pi 備忘録 / Mbedもあるよ!

Raspberry Pi であれこれやった事の記録

電圧計を使ってみる & ピンプラグ給電を試す

テスターではなく、電圧計を使ってみます。

電圧計その1

まず、1つ250円のこちら。

超小型2線式LEDデジタル電圧計(パネルメータ)3桁表示 DC3〜15V(赤色)オートレンジ: 測定器・計測器関連 秋月電子通商 電子部品 ネット通販

まず、安定化電源で 3.4v をだして、電圧計をチェック。

f:id:pongsuke:20170120151616j:plain

Raspberry pi 5v を計測しました。

f:id:pongsuke:20170120154017j:plain

結構低いです。

電圧計その2

USBタイプです。

多機能USB簡易電圧・電流チェッカー(積算電流・電力・時間表示対応) RT−USBVAC3QC: 測定器・計測器関連 秋月電子通商 電子部品 ネット通販

WEBカメラを刺してみました。
これは、刺しているだけで、動作はさせていない状態です。

f:id:pongsuke:20170120154008j:plain

次に、MjewpStreamer でストリーミングしてみた。

f:id:pongsuke:20170120154020j:plain

ピンプラグ給電を試します

GPIOの 5v と GND に5vを供給して起動します。
3.3vに繋いだら、多分壊れる。

ACアダプター

5v 4A を買った。

とりあえず電圧を測定してみる。

f:id:pongsuke:20170120155631j:plain

5.2v出てます。
大丈夫かな・・・。

カメラ接続だけ。 f:id:pongsuke:20170120155636j:plain

カメラ起動中 f:id:pongsuke:20170120155639j:plain

高く与えた電圧の分、高くなっている。

Raspberry pi でロボットアームを動かす その4 接続と動作テスト

MG996R も、DS3218 も、可動域が違いますがほぼ一緒です。

PCA9685 で、60hzで全部動かしちゃいます。

150 で最小値、 600 で最大値 を取ってくれる、、、みたいです。

可動域

MG996R 120度
DS3218 180度

ちなみに、可動域を超えて動かそうとすると、すごい発熱します!

ハンドの部分は、モーターの可動域そのままは使用しません。
ハンドの可動域を超えて動こうとして壊れないように、範囲を限定して動かします。

私の場合は

min     = 250
max     = 395

です。

コーディング

ハンド以外も、パーセント指定で動かせたほうが楽かと思い、書き直しました。

#!/usr/bin/python
# coding: utf-8 

from __future__ import division
import time
import Adafruit_PCA9685

# Uncomment to enable debug output.
#import logging
#logging.basicConfig(level=logging.DEBUG)

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(60)

def MG996R_BASE( percent ):
        channel = 0
        min     = 150
        max     = 600
        a_percent       = (max-min)/100
        pwm.set_pwm(channel, 0, int(a_percent*percent)+min)

def DS3218_LEAN_UNDER( percent ):
        percent = 100 - percent
        channel = 1
        min     = 250
        max     = 500
        a_percent       = (max-min)/100
        pwm.set_pwm(channel, 0, int(a_percent*percent)+min)

def MG996R_LEAN_UPPER( percent ):
        channel = 2
        min     = 150
        max     = 500
        a_percent       = (max-min)/100
        pwm.set_pwm(channel, 0, int(a_percent*percent)+min)

def MG996R_WRIST( percent ):
        channel = 3
        min     = 150
        max     = 600
        a_percent       = (max-min)/100
        pwm.set_pwm(channel, 0, int(a_percent*percent)+min)

def MG996R_HAND( percent ):
        channel = 4
        min     = 250
        max     = 395
        a_percent       = (max-min)/100
        pwm.set_pwm(channel, 0, int(a_percent*percent)+min)

def calibration():
        MG996R_BASE(0)
        time.sleep(1)
        MG996R_BASE(50)
        time.sleep(1)
        MG996R_BASE(100)
        time.sleep(1)
        MG996R_BASE(50)
        time.sleep(1)

        DS3218_LEAN_UNDER(0)
        time.sleep(1)
        DS3218_LEAN_UNDER(50)
        time.sleep(1)
        DS3218_LEAN_UNDER(100)
        time.sleep(1)
        DS3218_LEAN_UNDER(50)
        time.sleep(1)

        MG996R_LEAN_UPPER(0)
        time.sleep(1)
        MG996R_LEAN_UPPER(50)
        time.sleep(1)
        MG996R_LEAN_UPPER(100)
        time.sleep(1)
        MG996R_LEAN_UPPER(10)
        time.sleep(1)

        MG996R_WRIST(0)
        time.sleep(1)
        MG996R_WRIST(50)
        time.sleep(1)
        MG996R_WRIST(100)
        time.sleep(1)
        MG996R_WRIST(50)
        time.sleep(1)

        MG996R_HAND( 5 )
        time.sleep(1)
        MG996R_HAND( 95 )
        time.sleep(1)

def move01():
        MG996R_HAND(80)
        time.sleep(1)
        MG996R_HAND(0)
        time.sleep(1)
        DS3218_LEAN_UNDER(20)
        time.sleep(1)
        MG996R_BASE(40)
        time.sleep(1)
        MG996R_BASE(48)
        time.sleep(1)
        MG996R_LEAN_UPPER(10)
        time.sleep(1)
        MG996R_LEAN_UPPER(18)
        time.sleep(1)

        time.sleep(2)

        for var in range(0, 4):
                MG996R_HAND(10)
                time.sleep(0.5)
                MG996R_HAND(90)
                time.sleep(0.5)

if __name__ == '__main__':
        try:
                while True:
                        #calibration()
                        move01()
                        break

        except KeyboardInterrupt:
                pass

MG996R_BASE(50)                 # 旋回
time.sleep(0.5)
DS3218_LEAN_UNDER(80)   # 傾斜・下
time.sleep(0.5)
MG996R_LEAN_UPPER(10)   # 傾斜・上
time.sleep(0.5)
MG996R_WRIST(50)                #ハンド回転
time.sleep(0.5)
MG996R_HAND( 50 )               # ハンド開閉
time.sleep(0.5)
print("END.\n")

電源の交換

それぞれ独立して動かす分には、6V 2A で足りることがわかったので、別途用意した ACアダプター(6V 2.8A)を使用することにしました。

動作も問題無さそうです。

以下の2つを使用しました。

スイッチングACアダプター6V2.8A 100V〜240V GF18−US0628−T: 電源一般 秋月電子通商 電子部品 ネット通販

2.1mm標準DCジャック⇔小型ねじ端子台(着脱可能): パーツ一般 秋月電子通商 電子部品 ネット通販

f:id:pongsuke:20170117124453j:plain

Raspberry pi でロボットアームを動かす その3 PCA9685

I2C接続16チャンネル サーボ&PWM駆動キット PCA9685 を試す

はんだ付け

先にPINを付けてから、電源のターミナルをつける。
そうしないと、裏返した際に傾いて、はんだ付けしにくい。

配線

SCL - RPI GPIO3
SDA - RPI GPIO2
GND - RPI GND
Vcc - RPI 5v

I2C を有効にする

raspi-config から行う。

動作確認

$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: 70 -- -- -- -- -- -- -- 

Adafruitのライブラリとサンプルを使う。

$ git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
$ cd Adafruit_Python_PCA9685
$ sudo python setup.py install

サンプルスクリプトを書き換える。

0と1に繋いであります。

$ cat PCA9685.py 
#!/usr/bin/python
# coding: utf-8 

from __future__ import division
import time
import Adafruit_PCA9685

# Uncomment to enable debug output.
#import logging
#logging.basicConfig(level=logging.DEBUG)

pwm = Adafruit_PCA9685.PCA9685()

def set_servo_pulse(channel, pulse):
        pulse_length = 1000000    # 1,000,000 us per second
        pulse_length //= 50       # Hz
        print('{0}us per period'.format(pulse_length))
        pulse_length //= 4096     # 12 bits of resolution
        print('{0}us per bit'.format(pulse_length))
        pulse /= pulse_length
        print "%d pulse" % pulse
        pwm.set_pwm(channel, 0, int(pulse))

pwm_set = [800, 1200]

if __name__ == '__main__':
        try:
                while True:
                        channel = 0
                        set_servo_pulse(channel, pwm_set[0])
                        time.sleep(1)
                        set_servo_pulse(channel, pwm_set[1])
                        time.sleep(1)

                        channel = 1
                        set_servo_pulse(channel, pwm_set[0])
                        time.sleep(1)
                        set_servo_pulse(channel, pwm_set[1])
                        time.sleep(1)

        except KeyboardInterrupt:
                pass

スクリプトその2

モーターの仕様に合わせて、50hzにしたり、DUty比を計算して値を当ててみたりしたんですが、どうも、PCA9685 と、Adafruitさんのドライバにおいては、サンプルに有るように、 60hz, 150最小, 600最大 で組んでしまったほうが良さそうです。

ドライバの詳細を読み込めば、分かるのかもしれませんが、現在の結論は、そうなってしまった。

$ cat PCA9685.py 
#!/usr/bin/python
# coding: utf-8 

from __future__ import division
import time
import Adafruit_PCA9685

# Uncomment to enable debug output.
#import logging
#logging.basicConfig(level=logging.DEBUG)

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(60)

if __name__ == '__main__':
        try:
                while True:
                        channel = 0
                        pwm.set_pwm(channel, 0, 150)
                        time.sleep(1)
                        pwm.set_pwm(channel, 0, 375)
                        time.sleep(1)
                        pwm.set_pwm(channel, 0, 600)
                        time.sleep(1)
                        pwm.set_pwm(channel, 0, 375)
                        time.sleep(1)

                        channel = 1
                        pwm.set_pwm(channel, 0, 150)
                        time.sleep(1)
                        pwm.set_pwm(channel, 0, 375)
                        time.sleep(1)
                        pwm.set_pwm(channel, 0, 600)
                        time.sleep(1)
                        pwm.set_pwm(channel, 0, 375)
                        time.sleep(1)


        except KeyboardInterrupt:
                pass

pwm.set_pwm(0, 0, 375)
time.sleep(1)
pwm.set_pwm(1, 0, 375)
time.sleep(1)
print("END.\n")

モーターをゼロポジションにする

上記のスクリプトで、とにかく 375 で終了にさせておく。

ただし、下から3つ目のサーボモーターは、設計図のままだと、可動域の中央ではない。
上を向かせて組まないといけない。

アームを組み上げる

これの、1:19 あたりから5軸の組み立て方が出ます。
最初は3軸用なので注意。

www.youtube.com

注意点!

1.ネジとホーンの種類

サーボモーターと一緒に入っているネジとホーン(5袋)は使用しません。

別の袋に入っている、金属のホーンと、その復路に貼っているネジで組み上げます。

2. ネジの長さが長すぎる とくに、ハンドの部分。
ホーンの厚みよりもネジが長いので、当たっちゃいます。
ペンチでカットしました。

3. ハンドの可動域 120度全て動かせません。(開きすぎちゃう)
渡しの場合は、DUry比で50%で組合上げて、色々ずれて? 結局、

min = 250
max = 395

と成りました。

min で閉じて、 max で開き切ります。

なので、それ以上、それ以下にならないようにコーディングします。

f:id:pongsuke:20170116161417j:plain

f:id:pongsuke:20170116161437j:plain

f:id:pongsuke:20170116161443j:plain

Raspberry pi でロボットアームを動かす その2

モーターの動作確認

MG996R の動作確認

6v 1A に設定した安定化電源から給電しました。

f:id:pongsuke:20170106111203p:plain

配線は、上記の通り。
周波数も、上記の通り 50hz です。

$ cat MG996R.py 
#!/usr/bin/python
# coding: utf-8 

import RPi.GPIO as GPIO
import time
import sys 

# GPIO 21番を使用
PIN = 21

GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN, GPIO.OUT)
servo = GPIO.PWM(PIN, 50)       # GPIO.PWM(PIN, [周波数(Hz)])

val = [2.5,3.6875,4.875,6.0625,7.25,8.4375,9.625,10.8125,12]

if __name__ == '__main__':
        try:
                servo.start(0.0)

                servo.ChangeDutyCycle(val[0])
                time.sleep(0.5)
                servo.ChangeDutyCycle(val[8])
                time.sleep(0.5)
                servo.ChangeDutyCycle(val[0])
                time.sleep(0.5)

                while True:
                        for i, dc in enumerate(val):
                                servo.ChangeDutyCycle(dc)
                                print("Angle:" + str(i*22.5)+"  dc = %.4f" % dc) 
                                time.sleep(0.5)
                        for i, dc in enumerate( reversed(val) ):
                                servo.ChangeDutyCycle(dc)
                                print("Angle:" + str(180 - i*22.5)+"  dc = %.4f" % dc) 
                                time.sleep(0.5)

        except KeyboardInterrupt:
                pass

servo.ChangeDutyCycle(val[4])
time.sleep(1.5)
servo.stop()
GPIO.cleanup()

DS3218

安定化電源(6v, 1A設定)につないで、RPIからPWMを送るのですが、どうもピクピクしてしまう。

試しに RPI 5v から給電した所、正常に動いた。

ただし、電圧低下のシグナルが出るので、このままでは良くない。

しばらく原因がわからなかったのですが、どうも、ただのアンペア不足だったようです。2A出すようにしたら、正常に動き始めました。

流す電流も大きくなってきたので、PCA9685 を入れることにしました。

Raspberry pi でロボットアームを動かす その1

ロボットアームを動かしてみたい。

色々とロボットアームを検討したのですが、最終的に、これを日本のAmazonで買った。

f:id:pongsuke:20170106105927j:plain

5軸だ。

www.sainsmart.com

使用するモーター

4 x 9kg servo = Tower Pro, MG996R 55g metal gear servo * 4
1 x 20kg servo = DS3218

だ。

MG996R

データシート曰く、

Specifications
 Weight: 55 g
 Dimension: 40.7 x 19.7 x 42.9 mm approx.
 Stall torque: 9.4 kgf・cm (4.8 V ), 11 kgf・cm (6 V)
 Operating speed: 0.17 s/60o (4.8 V), 0.14 s/60o (6 V)
 Operating voltage: 4.8 V a 7.2 V
 Running Current 500 mA - 900 mA (6V)
 Stall Current 2.5 A (6V)
 Dead band width: 5 μs
 Stable and shock proof double ball bearing design
 Temperature range: 0 oC - 55 oC

1.0Aは見ておいたほうが良いのだろう。
同時に複数箇所動かすのは、電流が足りなくなりそう。

f:id:pongsuke:20170106111203p:plain

DS3218

データシートが見つからないが、下記のサイトが詳しい。
消える前に引用しておく。

LD-1501MG 17KGロボット用180度高トルクデジタルサーボ セール - バングッド

Specifications:
- Weight: 60g
- Size: 40*20*40.5mm
- Speed: 0.16sec/60 7.4V
- Nm: 15kg/cm 6V ; 17kg/cm 7.4V
- Work voltage: 6-7.4V
- Cable length: 30cm
- Accessories includes plastic servo horm and servo arm, screws, rubber sleeve, etc
Rotation Angle: maximum 180 degree

Instruction:
PWM pulse width adjustment angle, the period is 20ms, duty cycle 0.5ms~2.5ms of the pulse width level corresponding to 0 degree -180 degree, that is a linear relationship. Usually the servo actuator controller uses 500-2500 value corresponding to the servo control of the output angle of the duty ratio of 0.5ms~2.5ms, so that the control accuracy of the LD-1501MG servo is 3us, the minimum control accuracy can reach 0.3 degrees within the 2000 pulse width!

20ms周期 = 50hz

  0度 = 0,5ms = 0.5/20 = 2.5%
180度 = 2.0ms =  2/20 = 10.0%

電流に関して

MG996R 6v, DS3218 6v で良さそうだ。

USB 5v で完結すると理想的だ。

USB 5v を 6b に昇圧させれば良いんだろうとは思うが、そもそも、USBには 5v 2.5A 程度が最大だ。
どのみち1つのUSBでは動かせないだろう・・・。

DC-DCコンバーター も視野に入れつつ、とりあえずは、手元にある 2.5A までの安定化電源でテストしようと思う。

Raspberry pi Zero で オフィス環境の可視化 その4

ロギングしたので、グラフにしました。

f:id:pongsuke:20161227120331p:plain

f:id:pongsuke:20161227120336p:plain

f:id:pongsuke:20161227120343p:plain

f:id:pongsuke:20161227120349p:plain

Raspberry pi Zero で オフィス環境の可視化 その3

ロギングしましょう。

IOTデバイスは、各所にばらまかれるので、クラアイント&サーバー方式が良いのではと思い、
MySqlにデータを集積させる。

C から MySql

sudo apt-get install libmysqlclient-dev

コンパル

gcc -lmysqlclient -o mysqltest mysqltest.c

MySqlにデータを投げる

C での MySql への接続と、PythonでのMySqlへの接続。

メモだけ

#include <mysql/mysql.h>
...
        sprintf(query, "INSERT INTO log (log_type,value) VALUES('PRESS', %4.4f)", press);
        mysql_query(conn, query);
        res = mysql_use_result(conn);

        while ((row = mysql_fetch_row(res)) != NULL) {
                new_serial = atoi(row[0]);
        }
        mysql_free_result(res);

        // 切断
        mysql_close(conn);
        return new_serial;

など。