モータ電流を使った壁 (endstop) 検出
追加センサなしでエンドストップ / 原点 homing を実現する方法。指令モードの選び方と誤検出防御
要点
モータの実電流を「壁に当たった」信号として使う ことで、リミットスイッチや ADC しきい値センサを増やさずに原点 homing / エンドストップ検出ができる。
条件:
- モータへの指令が VELOCITY (速度) モードであること。トルク / duty モードでは原理的に検出しにくい (後述)
- 壁到達時に電流が 持続的に上がる (瞬時ピークではなくステップ) こと。ゴム緩衝材が挟まっているとこの前提が崩れる
- モータの電流フィードバックが host 側に届いていること (feedback msg / ADC ADC etc.)
なぜ VELOCITY が必要か
指令モードで壁到達時に電流がどう振る舞うかは firmware の regulate 対象で決まる。
| 指令モード | firmware が何を維持する | 壁到達時の電流 |
|---|---|---|
| VELOCITY (速度) | 速度 | 速度 0 になっても指令速度を維持しようとして電流を吐き上げる → スパイク発火 |
| TORQUE / CURRENT (トルク・電流) | 電流 | 指令電流に regulate されるだけで、実電流は指令値のまま → スパイク発火せず |
| DUTY (RoboMaster MD の場合) | 電流 (実質) | RoboMaster C610/C620 の DUTY は「±10000 = ±10A の正規化電流指令」なので TORQUE と同じ挙動 → スパイク発火せず |
| PWM DUTY (純粋 PWM 出力) | PWM duty 比 | 端子電圧一定 → 逆起電力ゼロで電流最大 → スパイク発火するがピークが飽和しやすい (電源電流上限で頭打ち) |
MD の「DUTY」が PWM duty ではなく実質電流指令なのは firmware 仕様の話で、他の MD (ODrive / RobStride 等) は名前が同じでも中身が違うことがある。「壁検出の可否は指令モードの名前ではなく、firmware が何を regulate しているか」 で決まる。
2 条件 OR で停止判定
電流スパイクの検出は 1 条件だと環境依存になりやすい。実運用では 2 条件 OR が頑丈:
[A] I > I_move + k * σ_move (統計ベース、cap を知らなくてよい)
[B] |I| ≥ ratio * I_cap (飽和検出、cap を知っている時に速い)- [A] sigma ベース: 走行中 (CRUISE) に電流の平均
I_moveと標準偏差σ_moveを数百 ms 蓄積し、I > I_move + k * σ_move(k=3 くらい) で「異常に高い」を判定 - [B] cap 飽和: 電流制限値
I_cap(config or firmware から取得) を知っているなら、|I| ≥ 0.9 * I_capで「限界まで吐き上げてる」を検出
どちらか成立で over-current 扱い。両方使うことで:
- 静音下 (σ 退化) にも強い ([B] が拾う)
- cap 不明の機構にも使える ([A] が使える)
引っかかりと壁の区別
一度でも over-current 条件が成立したら即停止、だと途中で引っかかったときに「壁到達」と誤認する。持続時間 stall_hold_ms (例 100 ms) を挟むと、瞬時ピーク (引っかかり) を除外できる。
raw over-current: [==pulse==] . . [======step======]
(30 ms) (200 ms 継続)
判定: チャタリング 壁確定条件が落ちたらタイマー reset。連続で成立し続けた場合のみ壁確定。
完了までのシーケンス例 (6 状態)
S0 BASELINE (100-150 ms) motor OFF、offset / sigma_off / v_min を測る
S1 SOFT_START (200 ms) velocity 0 -> velocity_home へ ramp、current 無視
S2 MOVE_GATE (~100 ms) ramp 完了後、|v| > v_min が hold_ms 継続 → S3
超過 → LIMIT_AT_START (最初から壁の可能性)
S3 CRUISE (100 ms) I_move / sigma_move をサンプリング
S4 WATCH (timeout まで) 2 条件 OR で over-current 判定、stall_hold_ms 継続で LIMIT_HIT
S5 BACKOFF (~backoff) 逆方向 velocity で backoff 距離動かして停止
DONE reset_encoder で「壁 = 0」を確定S0 の baseline 測定と S2 の gate は「最初から壁に押し付けられている状態で reset_encoder しない」ための安全弁。gate が失敗しても encoder を reset しない選択肢 (reset_on_limit_at_start) を残すと運用上安全。
3 パターン比較 (電流 / 収束 / 外部センサ)
同じ「壁到達を検出したい」でも、観測量が違う 3 パターンがある。全部 VELOCITY 指令で走らせる (指令モードは共通)。
| 電流ベース | 収束ベース | 外部センサ (limit sw / ADC) | |
|---|---|---|---|
| 観測量 | 電流 I | 速度 v と 位置 Δp | センサの topic (true/false) |
| 検出条件 | I > threshold を hold_ms 継続 | ` | v |
| ハード追加 | 不要 | 不要 | センサ + 配線 |
| 電流 feedback | 要 | 不要 | 不要 |
| 壁 vs 引っかかり の区別 | できる (瞬時ピーク vs 持続ステップ) | ❌ できない (引っかかりでも v ≈ 0) | ❌ できない (センサ側の位置でしか判定できない) |
| 時間コスト | stall_hold_ms (~150ms) | stability_interval_ms (~200ms) × 判定成立まで | エッジ検出は瞬時 |
| 検出精度 | 数 ms×v 分の overshoot (backoff で戻す) | 同上 | エッジ跨ぎ 1 パルス |
| 調整コスト | baseline / margin の tune | v_th と p_th の tune | true/false 判定、調整レス |
| 誤検出耐性 | 摩擦・引っかかり対策のロジック必要 | 引っかかりが誤検出になる | センサ正常前提、強い |
選び方:
- 精度 1 パルス欲しい / 機構が固定 / センサ配線 OK: 外部センサ
- 配線を増やしたくない / 電流 feedback がある / 引っかかりを判別したい: 電流ベース
- 配線 なし / 電流 feedback なし (encoder だけ) / 単純さ優先: 収束ベース
両者混在も可能 (electrical endstop で粗く止めた後に電流で押し付けて微調整、等)。
関連
- [[robomaster-normalization]] — RoboMaster MD の DUTY 単位系
- [[rc27-mech-calibration-history]] — rc26 (BT + 外部センサ) → rc27 (電流ベース C++ node) への移行