ESP32-S3 吊坠设备固件,集成火山引擎 RTC 语音助手、蓝牙配网、 VEML7700 环境光传感器驱动及石头同频匹配交友功能。 VEML7700 驱动: - 基于 ESP-IDF i2c_master API 实现,复用项目 I2cDevice 基类 - 支持 ALS + White 双通道、自动量程、Vishay 非线性校正 - 3 次采样取中位数过滤偶发异常 石头同频匹配算法(双维度): - 维度1:光谱比值 ALS/White(石头固有光学特征,不随光照强度变化) - 维度2:亮度等级(5级对数划分,排除极端环境差异) - 比值阈值 15%,实测同石头姿势变化波动 1.6%~9.6%,安全余量充足 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9.6 KiB
9.6 KiB
石头同频匹配方案说明
1. 业务背景
用户将自己的"本命石"放到设备的 VEML7700 环境光传感器上,录入光源信息。社交场景下,将其他用户的石头放到传感器上检测,如果两块石头"同频"则匹配交友成功。
核心挑战:录入和匹配可能发生在完全不同的光照环境下(室内/室外/阴天/晴天),算法需要在不同环境下仍能正确识别"同一类"石头。
2. 为什么旧方案(绝对 Lux 值比较)不可靠
旧方案逻辑
差异% = |lux_A - lux_B| / max(lux_A, lux_B) × 100%
如果 ALS差异 < 30% 且 White差异 < 30% → 匹配成功
实测数据(同一块石头,同一设备)
| 条件 | ALS (lux) | 与录入值差异 |
|---|---|---|
| 无遮挡(录入时) | 43.97 | 基准 |
| 无遮挡(匹配时) | 42.29 ~ 47.17 | 2% ~ 7% |
| 手掌遮挡10cm | 22.79 ~ 34.74 | 21% ~ 48% |
问题:同一块石头仅因为手掌遮挡(模拟不同光照环境),Lux 绝对值就变化了近 50%。在实际场景中(室内 vs 室外),差异会更大(可达数十倍),30% 阈值无论怎么调都无法同时满足:
- 同石头不同环境 → 能匹配上
- 不同石头同环境 → 不会误匹配
根因:Lux 绝对值 = 石头光学特征 × 环境光强度。环境变了,绝对值就完全不同。
3. 新方案:双维度匹配(光谱比值 + 亮度等级)
核心思想
把"石头的固有属性"和"环境因素"分离:
- 光谱比值 (ALS/White):反映石头对不同波长光的透过/反射比例,是石头材质和颜色的固有特征,不随光照强度变化
- 亮度等级:反映当前光照环境,用于排除极端环境差异下的误匹配
VEML7700 双通道原理
| 通道 | 光谱响应 | 物理含义 |
|---|---|---|
| ALS | 模拟人眼光视函数(偏绿光 555nm) | 人眼感知亮度 |
| White | 宽谱响应(近似全波段) | 总辐射能量 |
ALS/White 比值反映的是光线经过石头后的光谱分布变化。不同材质/颜色的石头对光谱的改变不同,因此比值不同。而同一块石头无论光多强多弱,比值基本不变。
实测数据验证
用上一轮测试数据反向计算比值:
| 条件 | ALS | White | ALS/White 比值 | 比值波动 |
|---|---|---|---|---|
| 无遮挡(录入) | 43.97 | 50.25 | 0.875 | 基准 |
| 无遮挡 #1 | 42.29 | 48.95 | 0.864 | -1.3% |
| 无遮挡 #4 | 44.90 | 51.89 | 0.865 | -1.1% |
| 无遮挡 #5 | 46.82 | 54.07 | 0.866 | -1.0% |
| 手掌轻遮挡 | 33.46 | 41.82 | 0.800 | -8.6% |
| 手掌重遮挡 | 24.01 | 34.45 | 0.697 | -20.3% |
关键发现:
- 无遮挡条件下比值波动仅 ±1.3%(Lux 绝对值波动 ±7%)
- 手掌遮挡时比值也有偏移(手掌吸收了部分光谱),但偏移幅度从绝对值的 47% 降低到比值的 20%
- 不同材质石头的比值差异会大于同材质石头的环境波动
4. 匹配算法详细设计
判定条件
同时满足以下两个维度才算匹配成功:
维度1:光谱比值匹配(判断石头是否为同类)
ratio_A = ALS_A / White_A (本命石)
ratio_B = ALS_B / White_B (对方石)
差异% = |ratio_A - ratio_B| / max(ratio_A, ratio_B) × 100%
如果 差异% ≤ 15% → PASS
维度2:亮度等级匹配(排除极端环境差异)
亮度等级划分:
0 = 极暗 (<5 lux)
1 = 暗 (5 ~ 50 lux)
2 = 中 (50 ~ 500 lux)
3 = 亮 (500 ~ 5000 lux)
4 = 极亮 (>5000 lux)
如果 |等级_A - 等级_B| ≤ 1 → PASS(允许相差1个等级)
为什么这样设计
| 设计决策 | 理由 |
|---|---|
| 比值阈值 15% | 无遮挡同石头波动约 1 |
| 亮度等级用对数划分 | 人眼对亮度的感知是对数的;室内/室外的亮度差异是数量级的(10 lux vs 10000 lux) |
| 允许相差 1 个等级 | 同一环境内亮度波动可能跨越等级边界(如 48 lux vs 52 lux 分属"暗"和"中") |
| 3 次采样取中位数 | 过滤传感器偶发异常读数(实测中观察到单次异常偏低 50% 的情况) |
匹配场景预测
| 场景 | 比值匹配 | 亮度等级 | 结果 | 说明 |
|---|---|---|---|---|
| 同石头 + 同光照 | ✅ (~1-2%) | ✅ 同级 | 匹配 | 理想场景 |
| 同石头 + 略有遮挡 | ✅ (~8%) | ✅ 同级 | 匹配 | 手遮一下不影响 |
| 同石头 + 室内→遮挡严重 | ⚠️ (~15-20%) | ✅ 可能同级 | 概率匹配 | 趣味性 |
| 同石头 + 室内→室外 | ✅ (~1-5%) | ❌ 差2+级 | 不匹配 | 环境差异过大 |
| 不同石头 + 同光照 | ❌ (>20%) | ✅ 同级 | 不匹配 | 不同材质 |
| 不同石头 + 不同光照 | ❌ | ❌ | 不匹配 | 双重不匹配 |
| 相似材质石头 + 同光照 | ✅ (<15%) | ✅ | 匹配 | 有缘! |
5. NVS 存储结构
| NVS Key | 类型 | 说明 |
|---|---|---|
ratio |
int32 | 光谱比值 × 10000(如 0.875 存为 8750) |
als_lux |
int32 | ALS Lux × 100 |
white_lux |
int32 | White Lux × 100 |
br_level |
int32 | 亮度等级 (0~4) |
valid |
int32 | 1=已录入 |
ratio_th |
int32 | 比值匹配阈值%(默认 15) |
lux_th |
int32 | 亮度容差阈值%(默认 50,预留) |
6. 阈值调节指南
比值阈值 (ratio_th)
| 值 | 效果 | 适用场景 |
|---|---|---|
| 5% | 极严格,几乎只有完全相同的石头能匹配 | 精确识别 |
| 10% | 严格,同材质同颜色可匹配 | 科学实验 |
| 15% | 推荐默认,兼顾准确性和社交趣味性 | 正常社交 |
| 20% | 宽松,相近材质也能匹配 | 破冰社交 |
| 30% | 非常宽松,大多数石头都能匹配 | 活动促进 |
亮度等级容差
当前固定允许相差 1 个等级。如果后续需要更灵活,可以通过 lux_th 字段扩展。
7. 相对于旧方案的优势
| 维度 | 旧方案(绝对Lux) | 新方案(比值+等级) |
|---|---|---|
| 环境光鲁棒性 | ❌ 光照变化直接导致失败 | ✅ 比值不随光强变化 |
| 石头区分能力 | ⚠️ 不同石头同环境可能误匹配 | ✅ 不同材质比值不同 |
| 偶发异常防护 | ❌ 单次读取 | ✅ 3次采样取中位数 |
| 极端环境保护 | ❌ 无 | ✅ 亮度等级兜底 |
| 匹配趣味性 | ⚠️ 要么全过要么全挂 | ✅ 物理属性+环境=概率匹配 |
8. 用户使用指南与注意事项
操作方式
本设备为吊坠产品,检测石头时用食指和大拇指捏住石头,贴紧设备传感器区域进行检测。
- 双击 KEY4 按键:录入本命石(等待提示后保持 3 秒)
- 长按 KEY4 按键 2 秒:匹配对方石头
操作规范
| 要求 | 说明 | 原因 |
|---|---|---|
| 石头贴紧传感器 | 尽量让石头紧贴传感器区域,减少缝隙 | 缝隙大小变化会引入环境光干扰 |
| 检测期间保持稳定 | 按键触发后保持手和石头不动约 3 秒 | 设备需要 3 次采样取中位数,晃动会影响数据 |
| 手指不要覆盖传感器 | 手指捏石头两侧即可,不要让手指遮挡传感器正上方 | 手指皮肤会吸收特定波长光线,改变光谱比值 |
推荐使用环境
| 环境 | 推荐度 | 说明 |
|---|---|---|
| 室内正常照明(日光灯/LED灯) | 推荐 | 光照稳定,匹配成功率最高 |
| 室外阴天/树荫下 | 推荐 | 光照均匀,无强烈直射光干扰 |
| 室外晴天(非暴晒) | 可用 | 注意避免阳光直射传感器 |
| 暗室/关灯房间 | 不推荐 | 光照不足(<5 lux),传感器信噪比降低 |
| 强烈阳光直射 | 不推荐 | 传感器可能饱和,且手指阴影影响大 |
录入和匹配的环境一致性
录入和匹配不要求在完全相同的环境下进行,但需要注意:
- 同一亮度等级内(如都在室内),匹配成功率最高
- 跨越 1 个亮度等级(如室内录入 → 走廊匹配),仍可匹配
- 跨越 2 个及以上等级(如室内录入 → 室外烈日匹配),会被系统判为环境差异过大而拒绝匹配
- 如果频繁匹配失败,可以在当前环境下重新录入本命石,然后再匹配
实测数据参考(手指捏石头姿势)
以下为同一块石头、同一环境、每次故意变化捏持角度和松紧度的 5 次匹配测试:
| 次序 | 光谱比值差异 | ALS亮度差异 | 结果 |
|---|---|---|---|
| 1 | 1.6% | 7.3% | 匹配成功 |
| 2 | 2.3% | 1.3% | 匹配成功 |
| 3(角度变化) | 6.6% | 5.9% | 匹配成功 |
| 4(角度变化大) | 9.6% | 3.1% | 匹配成功 |
| 5(松紧变化) | 5.4% | 9.7% | 匹配成功 |
结论:手指捏持姿势变化对比值的影响在 1.6%~9.6%,远低于 15% 匹配阈值,具有充足的安全余量(5.4%),正常操作下不会因姿势差异导致匹配失败。
常见问题
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 同一块石头反复匹配失败 | 录入和匹配时光照环境差异过大 | 在当前环境重新双击录入,再匹配 |
| 不同石头总是能匹配上 | 两块石头材质/颜色极其相近 | 这属于"有缘",是正常现象 |
| 录入提示传感器未初始化 | VEML7700 传感器硬件连接异常 | 重启设备,检查硬件 |
| 匹配结果显示"光照环境差异过大" | 录入(室内)和匹配(室外)跨度过大 | 在相近光照环境下操作 |