Skip to content

Si12T: default to original firmware sensitivity + add config get/set API#6

Open
GOB52 wants to merge 4 commits into
m5stack:mainfrom
GOB52:feature/si12t-sensitivity
Open

Si12T: default to original firmware sensitivity + add config get/set API#6
GOB52 wants to merge 4 commits into
m5stack:mainfrom
GOB52:feature/si12t-sensitivity

Conversation

@GOB52

@GOB52 GOB52 commented Jun 20, 2026

Copy link
Copy Markdown

Summary

Two related changes for the Si12T head-touch sensor:

  1. Default the sensor to the same sensitivity the original StackChan firmware
    uses (SI12T_Type_Low / SI12T_Sensitivity_Level_3, register 0x33)
    instead of the current SI12T_Type_High / SI12T_Sensitivity_Level_4
    (0xCC).
  2. Expose a small runtime configuration API on TouchSensor_Class
    (sensitivity, response/debounce, sleep, reference recalibration), with
    matching getters that read the value back from the chip.

Motivation

This change set was created to help improve / mitigate a false-trigger problem
on the Si12T head-touch sensor: it sometimes reports a touch / swipe gesture
while nothing is touching it.

This is not tied to a particular sensitivity setting. It occurs both with
the sensitivity the original StackChan firmware ships (Type_Low / Level_3)
and with StackChan-BSP's current default — it has been observed on my own device
and reported by other users.

Concrete example: on a StackChan the avatar spontaneously plays its "head-pet"
reaction — the facial expression changes and the neck servo moves — even though
no one touched the head, because the gesture recognizer saw a spurious non-zero
getIntensities() reading cross the swipe threshold.

This PR does not by itself claim to eliminate the issue; it adds the building
blocks to investigate and mitigate it:

  • setResponseCycles() — RTC debounce; a touch must persist for cycles + 2
    scan cycles before it counts, rejecting single-sample spikes.
  • recalibrate() — re-establish the idle baseline after an external disturbance
    (e.g. power-rail / I2C activity) that can skew it.
  • setSensitivity() and the getters — tune and read back the configuration at
    runtime.

It also aligns the default sensitivity with the original firmware
(Type_Low / Level_3). Note that this alignment is for parity with the
firmware, not a fix for the false trigger, which occurs at that setting too.

Default sensitivity

The original StackChan firmware initialises the Si12T at Type_Low /
Level_3 (firmware/main/hal/hal_head_touch.cpp):

si12t_setup(si12t, SI12T_TYPE_LOW, SI12T_SENSITIVITY_LEVEL_3);

StackChan-BSP currently defaults to the more sensitive Type_High / Level_4.
This PR aligns the BSP default with the firmware so out-of-the-box behaviour
matches the reference implementation.

New configuration API

TouchSensor_Class gains setters and getters. Getters read the value back from
the chip registers and fall back to the last-set value only if the I2C read
fails.

void setSensitivity(SI12T_Type type, SI12T_Sensitivity_Level level);
void setResponseCycles(uint8_t cycles);   // RTC[2:0]; response cycle = cycles + 2 (debounce)
void setSleep(bool enable);               // low-power sleep scan mode
void recalibrate();                       // force a reference (baseline) update

SI12T_Type              getSensitivityType();
SI12T_Sensitivity_Level getSensitivityLevel();
uint8_t                 getResponseCycles();
bool                    getSleep();

Underlying Si12T helpers were added to back these:

  • SI12T_Set_Config(ms, ftc, ilc, rtc) composes the CFIG register
    (0x08 = MS | FTC[1:0] | ILC[1:0] | RTC[2:0]); set_Ctrl1() now routes
    through it so the previously hard-coded 0x22 is the explicit default.
  • SI12T_Reset_Reference() pulses the Ref_rst registers (0x0A/0x0B) to
    force a baseline update (datasheet 12.2.4).
  • SI12T_Read_Sensitivity() / SI12T_Read_Config() / SI12T_Read_Ctrl()
    return the raw register byte (or -1 on read failure) for the getters.
  • SI12T_Set_Sensitivity() now caches the configured type/level (used as the
    getter fallback).

Register fields and bit layouts follow the Si12T datasheet (section 12).

Notes

  • getSleep() reflects the actual chip state. Because set_Ctrl2() enables the
    low-power sleep scan mode during normal operation, getSleep() returns true
    after begin(); setSleep(false) switches to the active (fast) mode. This is
    the chip's own semantics.
  • No change to the touch read/gesture path; this PR only touches configuration.

Testing

  • With the new Type_Low / Level_3 default: idle intensities stay clean
    ([0,0,0]) and intentional head touches/swipes are still detected.
  • Setters/getters compile and link; getters decode the expected register fields.

ciniml added a commit to ciniml/stackchan-idf that referenced this pull request Jun 21, 2026
Type_Low はヒステリシス幅が広く、idle ↔ touched 遷移がより安定する
(Si12T datasheet 12.2.2)。実機で head touch の誤発火頻度が低減した
ことを確認。元 StackChan firmware (hal_head_touch.cpp) と同じ値で、
m5stack/StackChan-BSP#6 で提案された新デフォルトでもある。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ciniml added a commit to ciniml/stackchan-idf that referenced this pull request Jun 21, 2026
m5stack/StackChan-BSP#6 で提案された残り 2 つの対策を導入。

1. CTRL1 の RTC[2:0] を 2 → 5 に拡大。応答サイクルが 4 → 7 になり、
   software 側の firmly_touched() フィルタに加えて HW debounce が
   1 段乗る。radio coex バースト 1 発で抜けてくる単発スパイクを
   弾く目的。なで検出のレイテンシは ~30 ms 程度しか増えない。
2. Si12tTouch::recalibrate() を追加し、サーボ VM 電源 ON + 1.5 s
   settle 後に呼び出して baseline を再取得。サーボ電源が立ち上がる
   と内部電源環境が変わって以前の baseline が外れたまま FTC=10 s の
   slow auto-cal を待つことになり、その間 ghost touch が出る原因。

実機で「感度を Type_Low/L3 に下げても誤爆がまだ起きる」状態だったので
合わせ技で対策。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant