[TOC]
## 資訊
> 您早
>麻煩您幫查 驅動器狀態字 Quick Stop active觸發條件有哪些嗎?
>
>控制字是下0x1F
正常觸發時狀態字為0x9237
偶爾機台運作中時控制器會收到驅動器狀態字為0x8317(Quick Stop active)
>在位置模式(CSP mode)
> 控制器判斷此狀態會做斷始能動作,並發警報。
現況不知為何驅動器會觸發Quick Stop active,而且情況是不容易重現。
> 沒有任何(警報)代碼
## 比對bit field
### request
In CSP, control word 下`0x1F`-->`0b11111` (spec table 27),(Figure 75)是要求 Switch on + enable operation,CSP下 bit4無作用。
就目前所知,下這個命令的目的是slave 為了確認master 仍連線。stop bit (bit2) 沒有設0,表示沒有要急停。
### response
`0x9237`--> `0b1001001000110111`, `0x8317` --> `0b1000001100010111`
```python
#python
exp=0b1001001000110111
true=0b1000001100010111
bin(exp^true) #-->0b1000100100000
```
兩者差別在 bit 5(1-->0), bit 8(0-->1), bit 12(1-->0)
status word的定義可參照cia402 or 在 code裡,`objdef.c`的line 427
```clike=427
union{
WORD all;
struct
{
WORD Readytoswitchon :1; //bit0
WORD Switchedon :1;
WORD Operationenabled :1;
WORD Fault :1;
WORD Voltageenabled :1;
WORD Quickstop :1; //bit5
WORD Switchondisabled :1;
WORD Warning :1;
WORD Manufacturerspecific1 :1; //bit8:stop flag
WORD Remote :1;
WORD Targetreached :1;
WORD Internallimitactive :1;
WORD Operationmodespecific :2; //bit12:
WORD HomeFinish :1;
WORD Manufacturerspecific2 :1; // z-index flag
}bit;
}Statusword = {0};
```
從 `objdef.c` 的 line1753
```clike=1753
Statusword.bit.Manufacturerspecific1 = GetStopRespStatus();
```
可以知道橋弘確實將bit8(manufacture specific bit)定義為,如果stop完成,set bit。同[appear2](#appear2)
最後的 `Operationmodespecific` ,我假設在csp mode,則根據cia402 spec p.142, Table 278
| Bit | Value | Definition |
| --- | ----- | ---------- |
| 12 | 0 | Drive does not follow the command value – Target position ignored |
| 12 | 1 | Drive follows the command value – Target position used as input to position control loop |
也就是,因為某種原因,驅動器忽略命令。
### paragraph summary
所以`0x8317`看起來是某種error 發生導致bit 12(unfollow),並啟動急停(bit5, set to 0)。bit 8則是有點奇怪,沒有和bit 5 sync
總體來說,就是要查所有 CSP error 發生的case。
## 查code 處
假設 drive code 沒有繞過正規method直接access bit 了話,應該是定義在 `objdef.c` line 1339 的 `CANopenState_QuickStopActive`
```clike=1339
void CANopenState_QuickStopActive()
{
Statusword.bit.Readytoswitchon = 1;
Statusword.bit.Switchedon = 1;
Statusword.bit.Operationenabled = 1;
Statusword.bit.Fault = 0;
Statusword.bit.Quickstop = 0;
Statusword.bit.Switchondisabled = 0;
}
```
透過searching 功能,直接使用此method的有兩處。
### appear1
分別是 1. `objdef.c` line 1416 的`void ControlWordRun()`裡的line 1493
```clike=1486
...
if(!Statusword.bit.Operationenabled) // not already Opeation enabled
CANopenState_SwitchOnDisabled();
// State Transition 11: => QUICK STOP
// Event: Quick stop command recerived from host
else if(Statusword.bit.Operationenabled)
{ // already Opeation enabled
CANopenState_QuickStopActive(); // CANopenState_SwitchOnDisabled();
u_bQuickStopFlag = TRUE;
}
...
```
也就是cia402 state machine in operation enable state時,quick stop
這裡算是正常開關機。
### appear2
或是2. `objdef.c` line 1606 的`void StatusWordDeal()`裡的line 1709
```clike=1699
...
else if (GetDriveStatus())
{
if (GetBrakeIng())
{
CANopenState_OperationEnable();
Statusword.bit.Internallimitactive = 1;
}
else if (GetStopRespStatus())
{
CANopenState_QuickStopActive();
u_bStopExist = TRUE;
}
else
```
`GetStopRespStatus()` 是直接讀取flag。假設沒有直接設定flag,這個function 在 `control.c`,對應setter 是 `SetStopRespFlag`,就是要找`SetStopRespFlag(TRUE);`。
只有 line 7975 `void ExecuteFaultResponse(WORD wResponse)`
和 line 14411 `BrakeEnable()` 這裡有。
`BrakeEnable()`幾乎沒有使用,反而是`ExecuteFaultResponse`,在`objdef.c`, `taskctrl.c`, `control.c`, `Error.c`都有。而且很 spaghetti
```clike=1519
//..., objdef.c ,ControlWordRun()
else if (ControlWord.bit.EnableOperation == 0)
{
if (u_bDisableVolt)
ExecuteFaultResponse(OFF2);
else if (u_bQuickStopFlag)
u_wCANEnable = NULL_CTRLWORD;
else if (u_bShutDown)
u_wCANEnable = NULL_CTRLWORD;
else if (u_bDisableOper)
u_wCANEnable = NULL_CTRLWORD;
else if (GetDriveStatus())
u_wCANEnable = DISABLE_CTRLWORD;
else
u_wCANEnable = NULL_CTRLWORD;
}
if (GetControlSource() != PC_COMMAND)
{
if (u_bQuickStopFlag)
{
if (u_wQuickStopCode == SLOWBYQUICKRAMP || u_wQuickStopCode == SLOWBYCURRENTLMT || u_wQuickStopCode == SLOWBYVOLTLMT)
ExecuteFaultResponse(OFF1);
else if (u_wQuickStopCode == DISABLE)
ExecuteFaultResponse(OFF2);
else if (u_wQuickStopCode == SLOWBYSLOWRAMP)
ExecuteFaultResponse(OFF3);
else if (u_wQuickStopCode == SLOWBYQUICKRAMP_INSTOP || u_wQuickStopCode == SLOWBYCURRENTLMT_INSTOP || u_wQuickStopCode == SLOWBYVOLTLMT_INSTOP)
ExecuteFaultResponse(STOP1);
else if (u_wQuickStopCode == SLOWBYSLOWRAMP_INSTOP)
ExecuteFaultResponse(STOP2);
else
ExecuteFaultResponse(OFF2);
}
if (u_bShutDown)
{
if (u_wShutDownCode == DISABLE_DRIVE)
ExecuteFaultResponse(OFF2);
else if (u_wShutDownCode == SLOWDOWN_SLOWRAMP)
ExecuteFaultResponse(OFF3);
else
ExecuteFaultResponse(OFF2);
}
if (u_bDisableOper)
{
if (u_wDisableCode == DISABLE_DRIVE)
ExecuteFaultResponse(OFF2);
else if (u_wDisableCode == SLOWDOWN_SLOWRAMP)
ExecuteFaultResponse(OFF3);
else
ExecuteFaultResponse(OFF2);
}
```
太四散了,所以要用error code縮小,error code定義在`Error.h`
```clike=169
//error response
#define NONE 0x0001
#define OFF1 0x0002
#define OFF2 0x0004
#define OFF3 0x0008
#define STOP1 0x0010
#define STOP2 0x0020
#define IASC 0x0040
#define MOTION 0x0080
#define OFF4 0x0100
```
### no err flag
然而讀不到任何error code,這有兩種可能 1.error flag(bit field)很快被某種機制by pass or reset掉了 2.不是用正規的方法(`ExecuteFaultResponse`)set flag,而是某一層直接set flag。但目前找不到有直接setting的地方。所以比較傾向1,被清掉了,e.g. `ClearResponseStatus`。
`ClearResponseStatus` 主要都在
```clike=7640
//control.c
void CheckFaultResponse()
{
switch(u_wFaultResponse)
{
case NONE:
ClearResponseStatus();
break;
case OFF1:
StopMotion();
break;
case OFF2:
Disable();
ClearResponseStatus();
```
可是這個function 也沒有被call。所以也不知道是不是真的被清掉。也有可能是PC下command去清的。
但是又很難reproduce error
### paragraph summary
目前還不知道沒有error code的原因。但是又要有error code 才能往下找。
## summary
1. 有某種內部error 產生
2. status word bit5 有點bug,但pc端沒有依賴它判斷,可暫時忽略
3. 驅動器急停,符合預期
4. 目前還不知道沒有error code的原因