0

我希望能够在我的 LCD 模块上以英尺为单位显示从 0 英尺到 20000 英尺的高度。这些数字是从我可以旋转以更改值的电位计读取的。目前电位计显示的范围是 0 到 1023,但我需要适当地缩放这些,以便它们从 0 到 20000 英尺读取。除此之外,我希望下面的行显示一个“条形图”来表示高度增加。LCD 每行有 20 个块,因此条形图的范围可以从 1 个块到 20 个块。

   sprintf(buf, "Altitude: %d    ", DELVAL2);    // display altitude level
   lcd_putxy(1,0,buf);
   for (delay = 0; delay < 50000; delay++);      // introduce a delay

   sprintf(buf, "*", DELVAL2 );                  // display bar graph
   lcd_putxy(2,0,buf);
   for (delay = 0; delay < 50000; delay++);      // introduce a delay

到目前为止,这是我的代码。它从电位计读取值DELVAL2并将其显示在 LCD 上。有人可以解释一下我如何适当地缩放数据以生成高度和条形图的方法。

4

3 回答 3

1

如果您的 DELVAL2 在 0-1023 范围内,您可以将其缩放到 0-20000,但您无法获得比 (1/1024) * 20000 更大的分辨率。为什么?您可以读取的最小值(一位)是 1/1024。您的最大值是 20000,因此 DELVAL2 上的一位更改将导致 20000/1024 = 19,53 的缩放值更改。

您可以计算如何缩放它,它已经在stackoverflow上进行了描述: How to scale down a range of numbers with a known min and max value

您必须记住,您可能会陷入浮点运算,这是您可能想要避免的事情。例如,你可以做这样的事情

scaled = (DELVAL2 * 1953) / 1000;

代替

scaled = DELVAL2 * 19.53;

请记住,您可以在此计算中获得的最大值为 1024*1953 = 1999872,因此您需要 32 位变量。可能需要额外的演员表,具体取决于您的架构和编译器,例如

scaled = (DELVAL2 * (uint32_t)1953) / 1000;

关于第二个问题 - 条形图 - 你做得很好。计算您需要多少符号并绘制它们。它是缩小而不是放大。简单的划分就足够了。当您知道需要多少符号时,在简单循环中生成它们

for(int i = 0; i < num; i++)
    buf[i] = '*';
buf[i] = 0; //last symbol is 0 to stop drawing
lcd_putxy(2,0,buf);
于 2016-12-14T17:18:52.973 回答
0

缩放[0...1023][0...20000]乘以 20,000,然后除以 1023。

int altitude = (int) ((potentiometer*20000L + 1023/2)/1023);

代码使用long乘法,因为int在微控制器上可能只有 16 位。如果 没有必要INT_MAX == 0x7FFFFFFF

+ 1023/2是为了提供一个四舍五入的转换。

于 2016-12-14T17:16:12.683 回答
0

大概buf是一个 16 位整数,并且包含底池值。大概您可以将其限制为值 [0, 1023]。

如果你这样做

    int scaledbuf;
    scaledbuf = buf >> 5;

您将获得scaledbuf[0, 32736] 范围内的值。然后你可以做

    if (scaledbuf > 20000) scaledbuf = 20000;

以牺牲你的底池的一些范围为代价,这将给你一个范围 [0,20000] 的值,而无需进行任何乘法运算,只需左移。

但是,无论如何,您都在延迟循环中烧毁循环,因此您可能可以管理乘法 20 的成本。

     int scaledbuf;
     scaledbuf = buf * 20;
     if (scaledbuf > 20000) scaledbuf = 20000;

这保留了相当多的底池范围,同时使您处于 16 位算术领域。

于 2016-12-14T17:16:35.890 回答