【问题标题】:Equation seems to be outputting wrong value in embedded C (stm32)方程似乎在嵌入式 C (stm32) 中输出错误值
【发布时间】:2022-06-13 22:34:21
【问题描述】:

希望你今天过得愉快。

我遇到了一个奇怪的问题。我正在使用定制 BMS PCB 上的 STM32 F103 C8T6 微控制器上的嵌入式 C 代码,但我在使用热敏电阻 ADC 值计算实际温度的代码时遇到了一些问题。

通过 excel,我们确定了我们需要使用的公式来根据 ADC 值计算以摄氏度为单位的温度:y = -0.5022x^5 + 6.665x^4 - 35.123x^3 + 92.559x^2 - 144.22x + 166.76

所以,在我的代码中,我有以下几行,其中 temp[i] 是原始 ADC 值,realTemp[i] 是转换后的值:

realTemp[i] = (double)(temp[i] / 10000);
realTemp[i] = -0.5022 * realTemp[i]*realTemp[i]*realTemp[i]*realTemp[i]*realTemp[i] + 6.665 * realTemp[i]*realTemp[i]*realTemp[i]*realTemp[i] - 35.123 * realTemp[i]*realTemp[i]*realTemp[i] + 92.559 * realTemp[i]*realTemp[i] - 144.22 * realTemp[i] + 166.76;

我没有使用 math.h 中的 pow 函数,因为它过去给我们带来了问题。

我们在 temp[i] 变量中得到的值如下:35480、35496、35393、35480。当我们在 excel 中使用这些值和函数时,我们得到了正确的输出,介于 25.3 和 25.5 摄氏度之间,但是上面列出的 C 代码在 realTemp 数组中输出 36。我不确定十进制值,但我不关心它们,因为该值在几行之后被类型转换为 uint16,以便通过 CAN 总线传输。

【问题讨论】:

  • 可能是因为temp 是一个整数数组。所以(temp[i] / 10000) 对于您显示的所有输入来说只有 3 个。 realTemp[i] = (double)(temp[i] / 10000); 应该是 realTemp[i] = temp[i] / 10000.0;
  • 请注意:看到“realTemp[i]*realTemp[i]”重复了这么多次,让我感到刺痛。使用临时变量,节省输入并提高可读性。
  • 这真的需要一个五阶多项式来模拟特征吗?如果您从“趋势线”中获取这些系数,请谨慎行事,Excel 默认会隐藏可能影响曲线形状的有效数字。给定一个 12 位 ADC,您真的需要那么多阶数或那么多有效数字吗?就您而言(没有 FPU),使用浮点的需要会增加代码大小并且速度会有些慢。定点实现可能更可取,但我当然会首先考虑简化曲线拟合,并且在某种程度上更合理。可用精度。
  • 只使用带有一些曲线点和一些线性插值的表格可能会更好/更快。

标签: c embedded stm32


【解决方案1】:

使用浮点除法,而不是整数除法。

// Integer division ------v-------------v       
// realTemp[i] = (double)(temp[i] / 10000);
realTemp[i] = temp[i] / 10000.0;

【讨论】:

    【解决方案2】:

    正如其他人所说,您正在进行整数除法,然后将结果转换为双精度 - 您需要将除法本身作为双精度。

    您的代码在相关微控制器上会很大且速度很慢。这可能不是问题 - 温度通常不会经常变化,因此慢速代码可能适合您。

    您还需要小心处理此类高次多项式 - 它们很容易不稳定,尤其是当您尝试将它们外推到非常高或非常低的温度时。如果您决定通过切换到“float”来加快代码速度,这会带来特别大的风险。

    这种事情的更好方法通常是查找表,或者大而简单,或者使用线性样条。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-26
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 2017-09-21
      • 2017-02-09
      相关资源
      最近更新 更多