■配線状況

 

↓前回記事の際の配線状況

 

↓今回の配線状況

↑配線がつなぎだらけ。

・PICO2台。上の1台がリニアスライド駆動用、

 下の1台が動作検出&mqttへのPUB用。
 それぞれ独立して動作します。

・太い銀色のケーブルは5VUSB電源。

・USB-Cメス端子で受け、PICO−WのVSYSに供給。

・同時にフォトインタラプタの発光側にも5Vから1kΩを介して供給。

・フォトインタラプタのドレインをPICOのGPIOに接続。

・PICO2台の信号系統は分離しています。

 フォトインタラプタ周りはとくにごちゃごちゃしてしまいました。

 

↓リニアスライド

↑可動体にアルミ板のドグを設置

 

↑ドグが溝に適切に入るようにアルミ板を曲げて調整

アルミ板厚0.3mm、AMAZONで手配。

はさみで切り出しができました。

スライド可動体とフォトインタラプタの溝との寸法関係から、

簡単な展開図を先に描いておいて、はさみで切り出し、

ドグになるように曲げ、インタラプタの溝を適切に通過できるように

曲げ角度を調整しました。

一番手前のインタラプタは動作端検出用。

これが遮光されたらスライド動作を停止、反転動作させます。

その向こうのインタラプタは動作状態検出用。

これが遮光されたら動作状態をmqttにて発信します。

 

↓mqttをpubするPICO-W

↑フォトインタラプタ2個からの信号をGPIO18 と19に接続。

赤い4Pディップスイッチはデバイス識別用ですが、今回未使用です。

 

↓リニアスライド制御用PICO-Wの配線状況

ロック付きプッシュボタン2個、左がena、右がdir。

これらは前回記事の接続のままで利用。

両端検知用のフォトインタラプタからの信号線をブレッドボード上で

わたり配線しています。

 

■動作状況

2台のPICO-Wで信号系統がごちゃまぜにすると、

正しく動作しませんでしたので、分離すると良好に動作しました。

1台ずつ動作が良好であることをThonny上で確認したうえで、

USB-CからVSYS電源へつなぎました。

配線が交錯、ブレッドボードへの差し込みが甘く、

配線にふれると無用なオンオフが多発します。

今回はとりあえずの動作確認と割り切っています。

 

↓mqttのsub(pubされた情報の受信)

mqttのpub/subの動作は十分に速く、IoT用途なら十分に適用できます。

 

↓動作中のモータドライバ電源出力状況

9.2W程度、モータ表面は概ね室温レベルのままです。

241224補記

・電圧を上下してみました。

 24V:動作音が明らかに小さくなりました。電力は12Wまで上がり、

    モータがほんのりと暖かくなります。

 12V:音は18V時と変わりませんが、電力が4Wまで下がりました。

 8.7V:これが電圧下限。動作音も若干低下しました。

   電力1.9W、24V時の1/6。負荷が小さいのでこれでも動作します。

241224補記以上

↓無負荷時

 

■リニアスライド制御コード

 

# test_linear_slide.py
#制御プログラム(リニアスライドユニット用)
# Linear Sliding length 100mm
# Stepping moter : 2pahse-bipoler NEMA17
# Stepping moter driver : TB6600
# CPU : RaspberryPi PICO-W
# Edit by kabayon date:20241220
# Coding : utf-8

# ライブラリ:micropythonの標準ライブラリのみ
from time import sleep
import time
from machine import Pin , PWM

# set standerd value of signal
signal_high = 1
signal_low  = 0

# set GPIO Pin-number
GP00 =   0
GP01 =   1
GP02 =   2
GP03 =   3
GP04 =   4
GP05 =   5
GP18 = 18
GP19 = 19
GP20 = 20
GP21 = 21
 
# 動作端検出用フォトインタラプタのオブジェクト設定
sw_ena = Pin(GP18, Pin.IN, Pin.PULL_UP)
sw_direction = Pin(GP19, Pin.IN, Pin.PULL_UP)
ls01 = machine.Pin(GP20, Pin.IN, Pin.PULL_UP)
ls02 = machine.Pin(GP21, Pin.IN, Pin.PULL_UP)

# Stepping motor driverへ信号出力するピンのオブジェクト設定
pin_pulse      = Pin(GP02, Pin.OUT)
pin_direction = Pin(GP03, Pin.OUT)
pin_ena         = Pin(GP04, Pin.OUT)

# ■TB6600ドライバ信号初期値
# DIR = HIGHで正転、DIR = LOWで逆転。
# status_direction = signal_high
# ENA = HIGHでトルク発生、ENA = LOWでトルクフリー
# status_ena = signal_high

# ■基本動作パラメータ設定
# ボールねじピッチ長さ(mm単位)
length_lead = 4
# 減速比を設定。モータ単体ならば1
ratio_gear = 1
# 1mm移動時のモータ主軸の総回転数設定
length_drive_1mm = 1
num_rotate_1mm = ratio_gear * length_drive_1mm / length_lead
# 1mm移動時のパルス数
num_pulse_1rotation = 1600
num_pulse_1mm = int( num_rotate_1mm * num_pulse_1rotation )
 
# パルス幅を秒単位で指定。値を小さくする程高速で回転する。
width_pulse = 0.0005

# ■動作繰り返し

time_stop_ls01=2
time_stop_ls02=2
dir_up=1
dir_down=0
status_dir = dir_up

while True:
    status_sw_ena = sw_ena.value()
    #time.sleep(0.5)
    # 移動長さ
    length_drive = 95
    # 移動パルス数
    count_pulse = length_drive * num_pulse_1mm
    print("num_pulse_1mm ",num_pulse_1mm,"count pulse ",count_pulse)
    #time.sleep(1)
    print("start driving")
    status_ls01 = ls01.value()
    status_ls02 = ls02.value()
    print("ls01:",status_ls01,"ls02:",status_ls02)
    if status_ls01==1:
        status_dir = dir_up
    elif status_ls02==1:
        status_dir = dir_down
    pin_direction.value(status_dir)        
    for j in range( 0 , count_pulse ):
        pin_ena.value( sw_ena.value() )
        status_ls01 = ls01.value()
        status_ls02 = ls02.value()
        if status_ls01==1 and status_dir==dir_down:
            pin_ena.value(0)
            j=count_pulse
            time.sleep( time_stop_ls01 )
            status_dir = dir_up
            pin_direction.value(status_dir)
        if status_ls02==1 and status_dir==dir_up:
            pin_ena.value(0)
            j=count_pulse
            time.sleep( time_stop_ls02 )
            status_dir = dir_down
            pin_direction.value(status_dir)
        else:
            pin_pulse.value( signal_low )
            time.sleep( width_pulse )
            pin_pulse.value( signal_high )
            time.sleep( width_pulse )

 

■mqtt制御プログラム(機械動作IoT用)

 

# test_mqttwithPI.py
#制御プログラム(機械動作IoT用)
# photo intrupter
# CPU : RaspberryPi PICO-W
# Edit by kabayon date:20241221
# Coding : utf-8

# ライブラリ:標準ライブラリ
import time
from machine import Pin
import machine
import sys
# ライブラリ:networkライブラリ
import network
from umqtt.simple import MQTTClient

# set GPIO Pin-number
GP18 = 18
GP19 = 19

# Wi-Fi接続function
def connect():
    # 自分の固定IPアドレス設定
    IPaddress_mine = '192.168.10.81'
    # Wifi起動
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    # Wifi接続       
    wlan.connect(ssid, password)
    while wlan.isconnected() == False:
        print('Waiting for connection...')
        time.sleep(1)
    wlan_status = wlan.ifconfig()
    wlan.ifconfig((IPaddress_mine, wlan_status[1], wlan_status[2], wlan_status[3]))
    ip = wlan.ifconfig()[0]
    print(f'Connected on {ip}')
    return ip

# Subメッセージ表示function
def printMessage(topic, message):    
    # 受信データをytes型からUTF-8文字列へ変換、標準出力表示
    print("topic:" + topic.decode("utf-8") )
    print("message:" + message.decode("utf-8") )

# メインルーチンーーーーーーーーーーーーーーーーーーーーーー

# LED制御値設定
on_led = 1
off_led = 0
time_on_led = 0.5

# Wi-Fi接続SSID、パスワード設定
ssid = 'kabanet24'
password = 'kabanet24'
# MQTTブローカーサーバーIP設定
address_kaban5105 = '192.168.10.32'
mqttBroker = address_kaban5105

# ConnectID(ユニーク)設定
myId = 'rpp01'
# トピック(構造化)設定
topic= b"test_mqtt/rpp01"
# メッセージヘッダー設定
msg_header = "rpp01 send "
# 接続維持時間設定
time_keepalive_MQTTClient = 3600

# LEDオブジェクト定義
led_rpp = machine.Pin("LED",machine.Pin.OUT)
# 初動LED点滅&オフ
led_rpp.value(on_led)
time.sleep(time_on_led)
led_rpp.value(off_led)

# 初期設定
# MQTTオブジェクト定義
client = MQTTClient(myId, mqttBroker, keepalive=time_keepalive_MQTTClient)
# 受信(Subscribe)時に呼ぶ関数の設定
client.set_callback(printMessage)
# Wi-Fi接続
connect()

# ブローカーに接続
try:
    # ブローカー接続処理
    client.connect()
    # Subトピック登録
    client.subscribe(topic)
except:
    # ブローカー接続失敗時、プログラム終了
    print("Could not connect to mqtt server.")
    sys.exit()
print("mqqtt connect done ")

# 動作検出用フォトインタラプタのオブジェクト設定
sw_head = Pin(GP18, Pin.IN, Pin.PULL_UP)
sw_bottom = Pin(GP19, Pin.IN, Pin.PULL_UP)
# get intial status of sw
status_old_sw_head = sw_head.value()
status_old_sw_bottom = sw_bottom.value()

# ■動作繰り返し
while True:
    flag_head = 0
    flag_bottom = 0
    status_sw_head = sw_head.value()
    status_sw_bottom = sw_bottom.value()
    if status_sw_head !=status_old_sw_head:
        flag_head = 1
    if status_sw_bottom !=status_old_sw_bottom:
        flag_bottom = 1
    if flag_head==1 or flag_bottom==1:
        # LED on
        led_rpp.value(on_led)
        #print(status_sw_head,status_sw_bottom)
        msg_status = "H"+str(status_sw_head)+"/B"+str(status_sw_bottom)
        #print(msg_status)
        # Pubメッセージ生成
        msg = msg_header+msg_status
        # Pub実行
        client.publish(topic, msg)
        # LED点滅
        led_rpp.value(on_led)
        time.sleep(time_on_led)
        led_rpp.value(off_led)
        # ブローカーPubメッセージ確認チェック
        client.check_msg()
        # LED off
        led_rpp.value(off_led)
    status_old_sw_head = status_sw_head
    status_old_sw_bottom = status_sw_bottom

 

以上