0

LCD モジュールで 0 フィートから 20000 フィートの範囲の高度をフィートで表示できるようにしたいと考えています。数値は、回転させて値を変更できるポテンショメータから読み取られます。現時点では、ポテンショメーターは 0 から 1023 まで表示していますが、0 から 20000 フィートまで読み取れるように、これらを適切にスケーリングする必要があります。これに加えて、下の行に「棒グラフ」を表示して、高度の増加を表します。LCD には 1 行あたり 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

これはこれまでの私のコードです。ポテンショメータから値を読み取り、DELVAL2LCD に表示します。高度と棒グラフを作成するためにデータを適切にスケーリングする方法を誰かが説明してくれませんか。

4

3 に答える 3

1

DELVAL2 が 0 ~ 1023 の範囲にある場合、0 ~ 20000 にスケーリングできますが、(1/1024) * 20000 より大きな解像度を取得することはできません。なぜですか? 読み取ることができる最小値 (1 ビット) は 1/1024 です。最大値は 20000 であるため、DELVAL2 で 1 ビット変更すると、スケーリングされた値で 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;

2 番目の質問について - 棒グラフ - 順調に進んでいます。必要なシンボルの数を計算して描画します。拡大ではなく縮小です。単純な分割で十分です。必要なシンボルの数がわかったら、単純なループで生成します

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);

マイクロコントローラでは 16 ビットのみの場合があるため、コードはlong乗算を使用します。intの場合は必要ありませんINT_MAX == 0x7FFFFFFF

+ 1023/2、丸められた変換を提供することです。

于 2016-12-14T17:16:12.683 に答える
0

おそらくbuf16 ビット整数で、ポット値が含まれています。おそらく、値が [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 に答える