日記；回すだけIII ⑪ pythonでSDO、PDOの読み書き＜その6 Profile Position Mode + アナログ入力（EPOS4）＞ベータ版

　EPOS4のコントローラには、

- ディジタル入力4ポート、出力2ポート
- アナログ入力2ポート、出力2ポート

が用意されています。オブジェクト・ディクショナリに登録されているので、SDOで読み書きできます。前回ディジタル入出力を利用しました。今回はアナログ入力です。

### アナログ入力
　Analog I/O (X8)コネクタのピン番号と機能です。

1 white　Analog input 1, positive signal
2 brown　Analog input 1, negative signal
3 green　Analog input 2, positive signal
4 yellow　Analog input 2, negative signal
5 grey　Analog output 1
6 pink　Analog output 2
7 blue　Ground
　1-2のアナログ入力1、3-4のアナログ入力2を利用します。ともに12ビット、±10Vの差動入力です。

### 機能を定義する
　WizardsのStartupからAnalog Inputを選択します。Analog input1にFunctionalityを画面のようにSet value velocity選択します。
　電圧Voltageを速度Velocityに換算することができます。あとでわかったことですが、これはCSVモードで生きるようで、今回のようなProfile Position Modeでは有効なVelocity値が得られませんでした。
　Analog input2はNoneのままです。

![2022-03-22 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e782f486-c43f-b6cd-f84b-87fc88710269.png)

　Finishで終了します。
　オブジェクト・ディレクトリでも確認できます。
　0x3160にアナログ電圧が入っています。
![2022-03-22 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/22d605a5-ca6f-9ef6-57d8-510bb6de3984.png)

　0x60ffに換算された速度値が入っています。見ていると、値は更新されます。しかし、プログラムでは初期の値しか代入できず、更新された値は反映できませんでした。

![2022-03-22 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/113242a6-61e2-f3bf-bb95-c8fe52bd8e24.png)

### ハードウェア
　10kΩのボリュームを二つ並べた基板を用意しました。
　コネクタX7 Digital I/Oの7番 Vdd(5V)から5Vをもらってきました。ディジタルとアナログ・コネクタのGNDは共通のようです。


1　Analog input 1, positive signal
2　Analog input 1, negative signal
3　Analog input 2, positive signal
4　Analog input 2, negative signal
5　＋5V
6　GND

![2022-03-22 (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/50c16686-686e-aa9a-7a7c-ba86c0a94ebd.png)

![IMGP1033.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/3144e9ae-f692-5e9c-b87c-c0688bf991bc.png)


### プログラム

　入力はAnalog input1だけの対応です。
　``node.sdo[0x3160]['Analog input 1 voltage'].phys``は電圧を読み取っています。実際の電圧の千倍の整数値が入っているので、速度の値にそのまま使います。差動入力のため、ボリュームを最小にするとマイナス値をとってくることがあります。対策をしていないので、エラーで止まります。

```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")

def NMT_start():
    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

def CiA402_start():
    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)

#----int----------------

NMT_start()
network.check()
print('NMT:node state  = {0}\n'.format(node.nmt.state))

network.sync.start(0.1)

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

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

def move(velocity):
    node.sdo[0x6040].raw = 0x0006
    node.sdo[0x6040].raw = 0x000f
    node.rpdo[3]['Controlword'].phys  = 0x007f
    node.rpdo[3]['Target position'].phys  = 5000
    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[0x607a].raw = 0       # Target position
node.sdo[0x6081].raw = 30     # Profile velocity
    
node.nmt.state = 'OPERATIONAL'
print('\n>>> move\n')


while 1:
    newVerocity = int(node.sdo[0x3160]['Analog input 1 voltage'].phys)+30
    print(newVerocity)

    move(newVerocity)
    readPosition()
    time.sleep(3)
    
#-------------------
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()
```

　最初は変な速度で回ります。``node.sdo[0x6081].raw = 30``がないと、速度が変化しません。``def move(velocity):``の関数にしないと、速度が変化しません。
　まだ何か、初期設定などで、設定すべき事柄などがフォローしきれていないようです。