日記；回すだけIII ⑩ pythonでSDO、PDOの読み書き＜その5 Profile Position Mode + ディジタル入出力（EPOS4）＞ベータ版


　EPOS4のコントローラには、
- ディジタル入力4ポート、出力2ポート
- アナログ入力2ポート、出力2ポート

が用意されています。オブジェクト・ディレクトリに登録されているので、SDOで読み書きできます。
### ディジタル入出力
　コネクタX7 Digital I/Oのピン番号と機能です。
1 white : Digital input 1       ;  Logic 0 <0.8 V  Logic 1 >2.0 V  、22k pulldown
2 brown : Digital input 2
3 green : Digital input 3
4 yellow : Digital input 4
5 grey : Digital output 1   ; 2.2k pullup to 5.45V MOS FET Drain-GND  、sink 0.5A max 36V
6 pink : Digital output 2   ; Souce  <2mA
7 blue : GND
8 red : VAux Auxiliary output voltage (+5 VDC; IL ≤150 mA)

　デフォルトでは入力は、Lowが0.8V以下、Highは2.0V以上です。コントローラ上のDIPスイッチの設定でPLCモードにすると、Lowが5.5V以下、Highは9V以上です。デフォルトのまま使います。22kΩでプルダウンされ、ヒステリシスのあるバッファの入力されます。購入した純正のケーブル長は約1mありました。

### 機能を定義する
　WizardsのStartupからDigital Inputを選択します。Digital input1～4にFunctionalityとPolarityを画面のように選択します。
　Digital input3はGeneral purouse Aで、CW回転のスイッチに使います。Digital input4はGeneral purouse Bで、CCW回転のスイッチに使います。四つとも負論理にしました。

![2022-03-20 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/575f7edb-1dac-54f5-0659-61b4d6a99a38.png)

　WizardsのStartupからDigital outputを選択します。
　Digital output1、2にFunctionalityとPolarityを画面のように選択します。
　Digital output1はGeneral purouse Aで、CW回転のスイッチの確認のLED点灯に使います。Digital output2はGeneral purouse Bで、CCW回転のスイッチの確認のLED点灯に使います。二つとも正論理にしました。
![2022-03-20 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/2a969b27-77c5-8443-89e8-a7639e5aba63.png)
　Finishで終了します。
　オブジェクト・ディレクトリでも確認できます。
　入力は0x3141で、出力は0x3150が状態を読んだり指定するプロパティになっています。
![2022-03-20 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/6da31fe8-dd4e-bfb1-1356-51e95151d623.png)

### ハードウェア
　スイッチとLEDを並べた基板を用意しました。
　スイッチと直列に1kを入れる予定でしたが、配線を間違え、プルアップしてしまいました。プルダウンに22kが入っていますが、1kが小さいので、4.7VのHighになっています。
![2022-03-20 (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/6073cb38-0d17-e466-7889-9cfdf62dd408.png)

　コネクタの信号です。
- 1 Digital input1
- 2 Digital input2
- 3 Digital input3
- 4 Digital input4
- 5 Digital output1
- 6 Digital output2
- 7 Vdd(5V)
- 8 GND

![IMGP1030.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/82c168ed-9261-34ab-ad12-46bd627a08d6.png)


### プログラム
　入力はDigital input3、4だけの対応です。
　Digital inputs logic stateでは、bit2がDigital input3、bit3がDigital input4です。負論理なので、7と11になります。
　whileループ内で、Digital input3が押されてLowになると、positionを500、速度500でCW方向に回転し、Digital outputs polarityを'1'にします。Digital outputs1（5番）のLEDが点灯します。Digital input4が押されてLowになると、positionを500、速度500でCCW方向に回転し、Digital outputs polarityを'2'にします。Digital outputs2（6番）のLEDが点灯します。
　ループの最後で0.1秒待ち、LEDを消します。

```python
import canopen
import time

# Start with creating a network representing one CAN bus
network = canopen.Network()

# Add some nodes with corresponding Object Dictionaries
node = canopen.BaseNode402(5,'maxon_motor_EPOS4_0170h_6050h_0000h_0000h.eds')
network.add_node(node)

# Connect to the CAN bus
network.connect(bustype='ixxat', channel=0, bitrate=1000000)

print("\n===start  ID=5 EPOS4\n")

node.nmt.send_command(0x81)  # NMT reset
time.sleep(0.5)
node.nmt.send_command(0x82)  # NMT Reset Communication
#node.nmt.wait_for_bootup(15)
time.sleep(0.5)
node.nmt.send_command(0x80)  # NMT Pre-ope
time.sleep(0.5)
node.nmt.send_command(0x1)   # NMT start
network.check()
print('NMT:node state  = {0}\n'.format(node.nmt.state))
#--------------------

network.sync.start(0.1)

print("---Switch CiA402") 
node.setup_402_state_machine()

#node.sdo[0x6040].raw = 0x0010  # Fault Reset
node.sdo[0x1003].raw = 0x0000
time.sleep(0.1)
node.sdo[0x1003].raw = 0x0000
time.sleep(0.1)
node.sdo[0x1003].raw = 0x0000
time.sleep(0.1)
#node.state = 'NOT READY TO SWITCH ON'

#node.state = 'SWITCH ON DISABLED'

Statusword = node.sdo[0x6041].raw
print('Statusword  {:0>16b}'.format(Statusword))


#node.state = 'READY TO SWITCH ON'
node.sdo[0x6040].raw = 0x0006
time.sleep(0.1)
node.sdo[0x6040].raw = 0x0006
time.sleep(0.1)
node.sdo[0x6040].raw = 0x0006
time.sleep(0.1)
 
#node.state = 'SWITCHED ON'
node.sdo[0x6040].raw = 0x0007
time.sleep(0.1)
node.sdo[0x6040].raw = 0x0007
time.sleep(0.1)
node.sdo[0x6040].raw = 0x0007
time.sleep(0.1)

#node.state = 'OPERATION ENABLED'
node.sdo[0x6040].raw = 0x000f
time.sleep(0.1)
node.sdo[0x6040].raw = 0x000f
time.sleep(0.1)
node.sdo[0x6040].raw = 0x000f
time.sleep(0.1)

print("\nSWITCH ready\n") 
print('Statusword  {:0>16b}\n'.format(node.sdo[0x6041].raw))

#----main----------------

def move(position, velocity):
    node.sdo[0x6040].raw = 0x0006
    node.sdo[0x6040].raw = 0x000f
    node.rpdo[3]['Controlword'].phys  = 0x007f
    node.rpdo[3]['Target position'].phys  = position
    node.rpdo[3].transmit()
    node.rpdo[4]['Controlword'].phys  = 0x007f
    node.rpdo[4]['Profile velocity'].phys  = velocity
    node.rpdo[4].transmit()

def readPosition():
    print('Target position {:5d}'.format(node.tpdo[3]['Position actual value'].raw))

readPosition()

node.sdo[0x6060].raw = 0x0001  #  Modes of operation <- Profile Position Mode
node.sdo[0x6083].raw = 5000    # Prfile acceleration
    
node.nmt.state = 'OPERATIONAL'
print('\n>>> move\n')
while 1:
    #print(node.sdo[0x3141]['Digital inputs logic state'].phys)
    #print(node.sdo[0x3141]['Digital inputs polarity'].phys)
    #print("")
    if node.sdo[0x3141]['Digital inputs logic state'].phys == 11:
        move(500,500)
        node.sdo[0x3150]['Digital outputs polarity'].phys =1
        print(node.sdo[0x3141]['Digital inputs logic state'].phys)
        print('\n>>> move +\n')
        readPosition()
    if node.sdo[0x3141]['Digital inputs logic state'].phys == 7:
        move(-500,500)
        node.sdo[0x3150]['Digital outputs polarity'].phys =2
        print(node.sdo[0x3141]['Digital inputs logic state'].phys)
        print('\n>>> move -\n')
        readPosition()

    time.sleep(0.1)
    node.sdo[0x3150]['Digital outputs polarity'].phys =0


#-------------------
print("\n-----")
node.sdo[0x6040].raw = 0x0010  # Fault Reset
print("") 
node.nmt.send_command(0x02)  # NMT remote stop
network.check()
print('node state end) = {0}'.format(node.nmt.state))
node.nmt.send_command(0x81)  # NMT reset
time.sleep(0.5)
node.nmt.send_command(0x82)  # NMT Reset Communication
network.sync.stop()
network.disconnect()
```

　中断はCTRL-Cです。正常終了していません。