notifyDccSpeed の内容

## KATOのDCS50Kを使用してstepを変えた時のパケットを観測

### はじめに
コマンドステーションのstep数の違いによるDCCパケットを確認する必要があり、
以前作った Arduino Nano DCC Shiled に、DCCスニファスケッチを書き込み確認しました。
DCS50Kのスピードリミットは[99]の最高速度に設定しました。
![スクリーンショット 2024-02-05 17.58.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/e5a95d12-ea25-854b-18c8-264f4e147839.png)

DCC速度信号を受信した時の処理のスケッチ抜粋
```c
//---------------------------------------------------------------------
//DCC速度信号の受信によるイベント
//extern void notifyDccSpeed( uint16_t Addr, uint8_t Speed, uint8_t ForwardDir, uint8_t MaxSpeed )
//---------------------------------------------------------------------
extern void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps )
{
    uint16_t aSpeedRef = 0;
    //速度値の正規化(255を100%とする処理)
    if( Speed >= 1){
        aSpeedRef = ((Speed - 1) * 255) / SpeedSteps;
    } else {
        //緊急停止信号受信時の処理 //Nagoden comment 2016/06/11
#ifdef DEBUG
        Serial.println("***** Emagency STOP **** ");
#endif
        aSpeedRef = 0;
    }
#ifdef DEBUG
    // デバッグメッセージ
    Serial.print("Speed - ADR: ");
    Serial.print(Addr);
    Serial.print(", AddrType: ");
    Serial.print(AddrType);
    Serial.print(", SPD: ");
    Serial.print(Speed);
    Serial.print(", DIR: ");
    Serial.print(Dir);
    Serial.print(", SpeedSteps: ");
    Serial.print(SpeedSteps);
    Serial.print(", aSpeedRef: ");
    Serial.println(aSpeedRef);
#endif
}
```
## DCS50Kの設定
14stepに設定
DCS50Kの操作 [LOCO] → [STEPS] → [S 14] → [LOCO]
DCCのパケットとしてはスロットル最大で29
28stepと認識していますが速度のパケットは1/2に間引かれて送信されます。
FORWARD時、スロットルを最小にすると0が送られてくるので、Emagency STOPになりますね。DCS50Kのバグでしょうかね。
```
[S 14] 14step
FORWARD
Speed - ADR: 1, AddrType: 0, SPD: 0, DIR: 1, SpeedSteps: 29, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 29, DIR: 1, SpeedSteps: 29, aSpeedRef: 246

REVERSE
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 0, SpeedSteps: 29, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 29, DIR: 0, SpeedSteps: 29, aSpeedRef: 246
```
28stepに設定
DCS50Kの操作 [LOCO] → [STEPS] → [S 28] → [LOCO]
DCCのパケットとしてはスロットル最大で29
```
[S 28] 28step
FORWARD
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 1, SpeedSteps: 29, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 29, DIR: 1, SpeedSteps: 29, aSpeedRef: 246

REVERSE
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 0, SpeedSteps: 29, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 29, DIR: 0, SpeedSteps: 29, aSpeedRef: 246
```
127stepに設定
DCS50Kの操作 [LOCO] → [STEPS] → [S127] → [LOCO]
DCCのパケットとしてはスロットル最大で126
```
[S127] 127step
FORWARD
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 1, SpeedSteps: 127, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 126, DIR: 1, SpeedSteps: 127, aSpeedRef: 250

REVERSE
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 0, SpeedSteps: 127, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 126, DIR: 0, SpeedSteps: 127, aSpeedRef: 250
```


## 比較のためにDSair2
スロットルを最大にすると127がセットされます。
```
127step
FORWARD
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 1, SpeedSteps: 127, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 127, DIR: 1, SpeedSteps: 127, aSpeedRef: 252

REVERSE
Speed - ADR: 1, AddrType: 0, SPD: 1, DIR: 0, SpeedSteps: 127, aSpeedRef: 0
Speed - ADR: 1, AddrType: 0, SPD: 127, DIR: 0, SpeedSteps: 127, aSpeedRef: 252
```


### 正規化部分を改良
正規化の式にて、Speed-1を入れると最大値がずれてしまうので以下のようなスケッチが良いかな。
```c
    if( Speed == 1　){
        aSpeedRef = 0
    }else if( Speed >= 2){
        aSpeedRef = (Speed * 255) / SpeedSteps;
    } else {
    //緊急停止信号受信時の処理 //Nagoden comment 2016/06/11
#ifdef DEBUG
        Serial.println("***** Emagency STOP **** ");
#endif
        aSpeedRef = 0;
    }

```