【问题标题】:reduce nonlinear analog value to digital outputs将非线性模拟值减少到数字输出
【发布时间】:2019-05-30 13:25:37
【问题描述】:

我制作了一个键盘,可以给我一个模拟值。现在我想根据阻力检测按下哪个键。然而,这些值是非线性的。

我用很多“if/else-es”来做到这一点。有没有更好的方法来做到这一点?

if(analogValue < 159){
  keyPress(KEY_A_ACUTE);
}else if(analogValue < 400){
  keyPress(KEY_I_ACUTE);
}else if(analogValue < 537){
  keyPress(KEY_O_ACUTE);
}else if(analogValue < 624){
  keyPress(KEY_U_ACUTE);
}else if(analogValue < 685){
  keyPress(KEY_N_TILDE);
}else if(analogValue < 800){
  keyPress(KEY_E_ACUTE);
}

【问题讨论】:

  • 视情况而定,如果只有这6种情况就可以了。如果它 > 100 并且性能是一个问题,我会使用二进制搜索匹配间隔
  • 这只是这 6 种情况,但我正在尝试学习,所以我正在寻找一个函数来将值映射到正确的整数
  • 建议使用“跳转表”并在模拟值上进行一些计算以确定要使用跳转表中的哪个条目
  • 温度。湿度、电源电压、电路电阻(甚至可能是情绪的相位)都会导致模拟读数发生变化。没有按下按钮时的读数是多少?代码是否允许'keybounce'
  • @user3629249 我知道我得到的值有点不可预测,但它们属于这些范围。我的代码确实允许按键反弹等等,但这不是问题。该代码有效,但我不喜欢它。所以我要求一种更好的方法。

标签: c adc digital


【解决方案1】:

您可以创建结构类型的数组并使用循环:

struct KeyValue
{
    int    key_name;
    int    max_value;  // Strictly less than threshold
};

static const struct KeyValue keys[] =
{
    { KEY_A_ACUTE, 159 },
    { KEY_I_ACUTE, 400 },
    { KEY_O_ACUTE, 537 },
    { KEY_U_ACUTE, 624 },
    { KEY_N_TILDE, 685 },
    { KEY_E_ACUTE, 800 },
};
enum { NUM_KEYS = sizeof(keys) / sizeof(key[0]) };

int analague_to_key_name(int analogue_value)
{
    for (int i = 0; i < NUM_KEYS; i++)
    {
         if (analogue_value < keys[i].max_value)
             return keys[i].key_name;
    }
    return KEY_UNKNOWN;
}

唯一的问题是处理超出范围的值——我选择返回一个特殊的 KEY_UNKNOWN 值,但您可以使用任何适当的替代策略。当然,数据必须按照max_value的升序排序。

这种技术的一个优点是它不受表中添加的影响,并且可以处理阈值之间的任意差异。如果表足够大(可能有几十个条目),您可以切换到对值进行专门的二进制搜索,这样可以减少比较。二进制搜索是专门的,因为您需要接受一个范围;您可能需要使用min_valuemax_value 创建结构。

【讨论】:

    猜你喜欢
    • 2013-06-11
    • 2021-11-11
    • 2017-11-23
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 2021-05-27
    相关资源
    最近更新 更多