---
# System prepended metadata

title: 答quick stop active 觸發條件為何
tags: [sandal]

---

[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的原因




