0

コントローラーなしでLEDの明るさを制御するためにいくつかのバイナリ配列を生成したいと思います。マイクロコントローラーでパルス幅を生成するのではなく(他の用途に使用する必要のある命令サイクルを消費します)、ルックアップテーブルとしてハードコーディングし、バイナリ配列を繰り返しループして設定します。その命令でLEDがオンまたはオフになります。

配列の長さが4であるとすると、5つの輝度レベルがあります。

{{ 0, 0, 0, 0 },
 { 1, 0, 0, 0 },
 { 1, 0, 1, 0 },
 { 1, 1, 1, 0 },
 { 1, 1, 1, 1 }}

アレイ全体で1をできるだけ均等に分散しようとしたことに注意してください。これは常に可能であるとは限りませんが、人間の目には小さな異常が表示されないようにする必要があります。

配列の長さが8で、明るさを5/8にしたいとします。

{ 1, 0, 1, 1, 0, 1, 1, 0 };

これは良い広がりのようですが、私も使用できたはずです:

{ 1, 0, 1, 1, 1, 0, 1, 0 };

どちらが良いですか?もちろん、平均的な明るさは同じです。ある状態から別の状態への変化の数も同じです。標準偏差は同じです。ただし、ランを見ると、最初の例ではランレングスの分散がはるかに小さく、より均一であるため、より優れています。

ともかく。与えられた長さと明るさでこれらの配列を生成するアルゴリズムが必要です。可能であれば、アルゴリズムは最適な配列(可能な限り均一な配列)を見つける必要があります。

思ったほど簡単ではありません。正直なところ、私はすべての可能性を比較し、最良のものを返すブルートフォースアルゴリズムを書きたくなります。

整数計画モデルをまとめることも考えていましたが、それはこの問題にはやり過ぎのようです。

誰かがより良いアイデアを持っていない限り?

編集:

{ 1, 1, 1, 1, 0, 0, 0, 0 }同じ実行分散{ 1, 0, 1, 0, 1, 0, 1, 0 }あることがわかります。したがって、2番目の例は最初の例よりも明らかに優れているため、メトリックはもう少し複雑にする必要があります。(アレイの長さが長い場合は、1が集まっているときにLEDのちらつきが見える場合があります)。

4

2 に答える 2

2

わかりました。基本的に、実行したいのは、最大ランレングスの0または1を最小化することです。一般的な考え方は、可能な限り分散することです。残りの部分は、前面に詰め込むだけです。

N=合計ビット数n=1の数

void pwm(int N, int n, char* z = 0) {
    if (n == 0) {
        // degenerate case!
        for (int i = 0; i < N; i++) {
            printf("0");
        }
        printf("\n");
        return;
    } else if (n == N) {
        // degenerate case!
        for (int i = 0; i < N; i++) {
            printf("1");
        }
        printf("\n");
        return;
    }
    int m = N - n;
    int sep = m/n;
    int rem = m%n;
    int pre;
    int i,j;
    std::list<char> clist;

    if (z == 0) {
        // if more 1 than 0, then flip
        if (sep > 0) pwm(N,n,"01");
        else pwm(N,N-n,"10");
        return;
    }

    pre = sep/2;

    for (j = 0; j < pre; j++)
        clist.push_back(z[0]);
    if (rem > 0) {
        clist.push_back(z[0]);
        rem--;
    }

    for (i = 0; i < n; i++) {
        if (i!=0) {
            for (j = 0; j < sep; j++)
                clist.push_back(z[0]);
            if (rem > 0) {
                clist.push_back(z[0]);
                rem--;
            }
        }
        clist.push_back(z[1]);
    }

    for (j = 0; j < sep-pre; j++)
        clist.push_back(z[0]);


    // output the data so we can see
    char* res = new char[N+1];
    memset(res, ' ', N);
    res[N] = 0;
    char* u = res;
    for (std::list<char>::iterator cli = clist.begin(); cli != clist.end(); cli++) {
        (*u) = *cli;
        u++;
    }

    printf("%s\n", res);


    delete [] res;
}

N=25の出力は次のとおりです。

0000000000000000000000000
0000000000001000000000000
0000001000000000001000000
0000100000001000000010000
0001000001000001000001000
0010000100001000010000100
0010001000100010001000100
0010001000100010010010010
0010010010010010010010010
0100100100100100100101010
0100100100100101010101010
0100100101010101010101010
0101010101010101010101010
1010101010101010101010101
1011011010101010101010101
1011011011011010101010101
1011011011011011011010101
1101101101101101101101101
1101110111011101101101101
1101110111011101110111011
1101111011110111101111011
1110111110111110111110111
1111011111110111111101111
1111110111111111110111111
1111111111110111111111111
于 2013-01-10T01:42:55.053 に答える
0

nポイントのグリッドでkポイントを照らす必要があると仮定します。次の確率論的アプローチに従うことができます。

remk=k
remn=n
for i in range(n):
    x[i] = 1 if rand()< remk*1.0/remn else 0
    remk-=x[i]
    remn-=1

xは、照明配置を含む配列です。

于 2013-01-10T01:22:36.800 に答える