乱数ジェネレーターの最小かつ最も単純なシードは何ですか?


40

小型のマイクロコントローラー(8ビットAtmel)は、多くの派手なランダム化されたライトシーケンスでライトショーを提示するために、多数のライトを制御します。

適切な擬似RNGがうまく機能しますが、私はそれのための良い種を探しています。誰かが複数のそのようなデバイスを同時にオンにした場合、個々のクロックソースのわずかな違いのためにゆっくりと離れるまで同じ効果のシーケンスをすべて生成した場合、見た目が悪くなるため、シードが必要になります。

よく使用する擬似RNGをシードする非常に良い方法は、ボタンを押すかスイッチを押すことで起動する必要があるデバイスの場合に可能です。µcの電源がオンになるとすぐに、非常に高速のタイマーを開始できます。このタイマーの値は、ボタンが初めて押されるとすぐにRNGをシードします。

問題は、このシナリオではボタンがないことです。デバイスの電源を入れたらすぐにプログラムを開始する必要があります。

PCB上の場所は非常に限られているため(非常に小さなSMDパーツがいくつか収まることはありません)、可能な限り最小で最もシンプルなソリューションを探しています。そのため、真のRNGハードウェア、ラジオ受信機などの派手なソリューションは除外します。

私が持っているのは、CPUの16ビットタイマーカウンターと、ADCにアクセスする未使用のポートピンだけです。

私の現在の解決策は、抵抗を使用して(できるだけ不正確)、ADCピンに約半分の電源電圧を供給し、RNGに最初のAD変換値をシードすることです。ただし、最近ではほとんどの10%抵抗器の精度が1%を大幅に下回っているため(見つけることができる最悪の品質のSMD抵抗器が必要だと伝えると、サプライヤーの顔を想像するのは楽しいでしょう)、非常に高い確率で同じシードで始まる複数のユニット。

より良い代替策は、複数の変換を行い、これらの測定値の最下位ビットから値を構築することです。ただし、以前はこのµcタイプのADCを使用しましたが、非常に正確であることはわかっています。ここでは、ADCを可能な限り速い速度で実行すると役立つ場合があります。

誰かより良い提案がありますか?シードは完全に均一に分布する必要はありませんが、分布が均一であればあるほど良いです。完全に均一な分布を持つ16ビットシードは、あまりにも良い夢ですが、5ビットまたは6ビットの中間のまともな分布で十分だと思います。


12
「サプライヤーが見つけられる最悪の品質のSMD抵抗器が欲しいと言ったら、サプライヤーの顔を想像するのは楽しいだろう」-この抵抗器の値を回路図で未定義にしておくとさらに面白くなる生産者は、PCBが配置マシンから出た後、持っているすべての抵抗値を混ぜ合わせたビンから、この1つの部品を手動ではんだ付けする必要があると考えています。-それは私が探しているRNGではなく、種だからです。そのため、ほとんど毎回同じ値を生成する場合、それほど悪くないのであれば、デバイス間で異なることがより重要です。
VSZ

8
量産プログラミング中にランダム値をEEPROMストレージに書き込んでみませんか?このように、エンドデバイスではなくプロダクションプログラマーにのみ存在するため、好みのRNGを使用できます。(@immibisへのクレジット:「わずかに異なるソフトウェアファイル」からアイデアが得られました。)
Calrion

2
それで、%100を明確にするために、問題は、それらが同じシーケンスで開始する可能性があることであり、時間の経過とともにばらばらになる可能性があることではありません。
wedstrom

2
RNGの選択は重要です。高品質のシードが必要なものとそうでないものがあります。たとえば、Xorshiftの場合、0以外のシードが機能し、同様に機能します。最初のシードにわずかな違いがあっても、RNGサイクルの開始位置は大きく異なります。
curiousdannii

3
すべてのADCの回答を統計とタイミングと組み合わせて、さらにランダム性を高めることができます。たとえば、下位3 LSBが101であるN個のサンプルと、下位3 LSBが110であるM個のサンプルを取得するまでにかかるプロセッサティック数を測定します。必要に応じてこの概念を拡張します。
wjl

回答:


24

A / Dピンとグランドの間に並列抵抗とコンデンサを配置します。抵抗をかなり高くし、できればA / Dの入力信号インピーダンス要件を十分に上回ってください。RC時定数を約10 µsに設定してください。たとえば、100kΩと100 pFは適切な組み合わせのように聞こえます。

ある程度ランダムな値を得るには、ピンをしばらくの間ハイに駆動し、それを高インピーダンスに設定し、数マイクロ秒後にA / Dを読み取ります。特に、A / D取得時間を適切に乱用した場合、表示される電圧は、RおよびCの値、ピンの漏れ電流、その他の近くのノイズ、および温度に依存します。

下位ビットまたは下位2ビットを取得し、必要に応じて繰り返して、任意の数のランダムビットを取得します。

よりランダムなパターンの場合、この手順を時々実行し、A / D結果の下位ビットを既に使用している乱数ジェネレーターに挿入します。


これはいいですね。必ずADCの入力インピーダンスを確認してください。Atmega8シリーズのアナログ入力インピーダンスは100Megであるため、Olinの抵抗値は少し低くなります。
stefandz

3
@stef:正しい変換に必要な入力インピーダンスと信号インピーダンスは、2つの異なるものです。はい、CMOSであるため入力インピーダンスは非常に高くなっています。ただし、信号には最大インピーダンス制限があり、指定された時間内にサンプルを充電してキャップを保持し、ピンの漏れを克服することができます。
オリンラスロップ

2
申し訳ありませんが、回答から、ソースインピーダンス仕様ではなく入力インピーダンスを参照していると思いました。10kはAtmega8が指定する最大ソースインピーダンスなので、答えはすぐにわかります。参考までに、誰かが興味を持った場合に備えて、内部のS / Hキャップは14pFです。
-stefandz

2
@stef:これをより明確にするために答えを編集しました。
オリンラスロップ

月相と銀行休業日を逃しました。また、特に低Cで十分にシールドされていない場合は、有用な追加物を手で振ってください。
ラッセルマクマホン

23

可能なオプション:

  1. 各デバイスに固有のシリアルアドレスを事前にプログラムします。十分に優れたRNGアルゴリズムを使用している場合、シリアルアドレスの連続したリストでさえ、大きく異なる結果を生成します。

  2. MCU /セットアップに応じて、システムクロックとウォッチドッグタイマー/タイマーカウンター入力に使用できる2つの異なるクロックソースがある場合があります。これらのいずれかまたは両方に大きなばらつきがある場合、これを使用して適切に異なるシードを生成できます。以下は、Arduinoの内部ウォッチドッグタイマーと外部XTALシステムクロックを使用する、私が書いた例です。

  3. BJTトランジスタを使用して、ベータ依存性の高い増幅器を構築します。これは、シードのADCから読み取ることができます。

  4. コンデンサ/インダクタは通常、抵抗よりもはるかに悪い許容誤差で指定されています。これらを使用して何らかのフィルター回路(RC、RL、LC)を構築し、ADCで出力を測定できます。


5
私はオプション1に投票します。これは、シーケンスが一致する必要がなくなるゼロパーツカウントソリューションです。シリアル番号とRNDジェネレーターは16ビットと言うことができ、どのデバイスでも他のパターンを模倣する可能性はほとんどありません。
-KalleMP

1
私も解決策が好きです。単純なハッシュアルゴリズムを使用する場合、シリアル番号が連続していても問題ありません。
magu_

6
オプション1の良いところは、一部のデバイスにシリアル番号が組み込まれていること(通常はネットワーク/ RF関連のマイクロ)であるため、シリアル番号を書き込むための別の手順さえ必要ない
-slebetman

3
以下のようにもゴミRNG LCGがします「のシリアルアドレスの順次リストのために乱暴に異なる結果をもたらします」。私も1に投票します。
BlueRaja-ダニーPflughoeft

3
タイムソースがある場合は、それをシードオンスイッチのベースとして使用すると、実行間で物事を相殺できます。デバイスにシリアルアドレス/番号またはMACアドレスがある場合はこれを組み合わせて、デバイス間の一致も修正します。再起動後であっても、シードとして使用するために生成された乱数の一部またはすべてを永続的に保存するソフトウェアを見てきました。デバイスの動作時間が異なる場合、デバイスはばらばらになるはずです。
TafT

8

初期化されていないメモリ

マイクロコントローラで初期化されていないメモリを使用してみてください。トリックは、最も「バランスの取れた」フリップフロップを持ち、実際にはランダムなビットを見つけることです。手順は、すべてのメモリを読み取り、リセットし、数回繰り返して、どのビットが本当にランダムであるかを測定することです。次に、このマップを使用して、PRNGまたはLFSRをシードするのに十分なランダムビットを読み取ります!

この方法は、同一のハードウェアであっても、ランダムなシードを提供するはずです。詳細(およびリンク)は、このハックデイの記事で入手できます。

追加の回路やピンを必要としないため、この方法が気に入っています。AVRには既にRAMがあります。不安定な(ランダムな)ビットを見つけるだけです。マッピング手順も自動化できます。同じコードと手順を各デバイスに適用し、真にランダムな結果を得ることができます!


1
どのビットがランダムであるかを実際に把握する必要はありません。すべてのバイトをXORすると、8ビットだけがランダムである場合でも、ランダムな結果が得られます。そして、写真が示すように、実際の値は時間的な意味でランダムではないかもしれません、それらは十分にユニークです-これはまさにここで必要なものです。
–MSalters

1
エントロピーを「ミックスイン」できるPRNGを見つけることができれば、XOR-then-seedオプションよりも優れている可能性があります。初期化されていないメモリを反復処理し、バイトをPRNGに混ぜます。例えば、私のsimplerandom Cライブラリ、mix functionを参照してください。
クレイグマックイーン

これでは、暗号品質のランダム性は得られません。

@CamilStapsもちろんそうではありません。
ナビン

1
これは機能しません。オペレーティングシステムがあり、メモリのどの部分をプログラムに割り当てるか、以前に何があったかを制御できない場合、未初期化メモリは未定義の動作です。OSのないマイクロコントローラーでは、これは当てはまりません。特にAVRでは、ブラウンアウトの電流消費によってコンデンサが空になるのに十分な時間が経過すると、すべてのRAMがゼロになるためです。
-vsz

7

ランダム機能を備えたMP3プレーヤーで行ったことは、電源を入れるたびに異なるシーケンシャルシードを使用することです。私は1から始めて、これをEEPROMに保存したので、次のパワーサイクルで2などを使用しました。これはATMEGA168にありました。helloworld922が指摘したように、単純なシーケンシャルシードでさえ、まったく異なる擬似ランダムシーケンスを生成します。

線形合同ランダムシーケンスジェネレーターの1つを使用しました。これにより、均一な分布が得られます。

int i;
seed = seed * 2053 + 13849;
i = (seed % max) + 1;  // max is the maximum value I want out of the function

もちろん、同じ数のパワーサイクルがあったとしても、複数のユニットに異なるシーケンスを持たせたい場合は、ランダムに開始するものが必要です。

これは、他のポスターで提案されている方法のいずれかで実行できます-考えられる方法の1つは、ACゼロクロッシングを使用している場合(たとえば、ランプの位相制御など)、プロセッサに入ることですか?これは、電源投入後の最初の交差でタイマーをサンプリングし、シードとして使用するために使用できます。

モードを選択するためのプッシュボタンはユニットにありますか?もしそうであれば、MCUがプログラムされた後に最初にボタンが押されたときにカウンターをサンプリングできる場合は、最初にランダムシードを生成し、それをEEPROMに保存できます。この時点以降のすべてのパワーアップでは、保存されたシードが使用されます。


5

ADCはランダム性の非常に優れたソースです。

抵抗の公差に依存する必要はありません。どの抵抗でも熱ノイズが発生し、同じ物理的効果により、すべてのサンプリングおよび変換ステップを実行するときにADCにノイズが導入されます。(データシートには、ノイズの量と、最悪/最良の構成設定が記載されています。)

ADCピンをフローティングのままにしないでください。これにより、電圧が過度にフロートし、入力が飽和する危険があります。
(多くのMCUでは、電源電圧の半分をADC入力として使用して、キャリブレーションを行うことができます。これにより、外部抵抗が節約され、ノイズが発生します。再び、最悪/最良の構成についてはデータシートを参照してください。)

単一のADC測定に依存する必要はありません。複数の測定値を単純なハッシュ関数またはチェックサム関数と組み合わせることができます(CRCで十分です)。RNGの使用をすぐに開始する必要がある場合は、後でADCの結果を現在のRNGシードと組み合わせることができます。


2
ジョンソンノイズがこのアプリケーションに適しているかどうかはわかりません。STPでは、10kHz帯域幅の10Meg抵抗に40uVはジョンソンノイズがあります。これを合理的に測定するには、14ビット以上のADCまたはアンプ回路が必要です。
helloworld922

STPは実際には関係ありません。温度は特に意図的に上げることができますが、STPに対して60度余分に加えるとノイズは10%だけ増えます。
–MSalters

1
同様のアプローチは、ダイオードでショットノイズを使用することです。en.wikipedia.org/wiki/Noise_generator#Shot_noise_generators
チームボブ

2

セッション間でシードを保存できますか?もしそうなら、作成時にランダムな期間にすべてのユニットをオンにすることは可能ですか?そのようにして、すべてのユニットは、同じではない可能性のあるプリセットシードとともに出荷されます。

別の考え:複数のユニットをリンクして、同時にオンにする方法は?それらが直列の場合、(n + 1)番目のデバイスがn番目のデバイスの数クロックサイクル後に開始するように、何らかの種類のコンデンサを追加します。理想的には、デバイスのシャットダウン時にコンデンサが非常に急速に放電するため、起動/再起動のたびにシーケンス間に大きなギャップが生じます。

それらが並行している場合でも、起動時間を少しランダム化できます。コンデンサを使用した何らかのパワーフィルターがあると思います。その場合、わずかに異なるろ過回路を使用してデバイスを製造すると、各デバイスがわずかに異なる時間に起動し、数回の再起動後に発散します。

これのバリエーションは、可能であればクロック信号に分散を追加することです。クロック速度の0.1%の違いは、ライトショーにほとんど影響を与えないかもしれませんが、PRNGテーブルを横断するレートをかなり速く変更します。


1
おそらく大きなピンをアナログのアナログに接続し、「メインハム」の読み取り値を取得してRNGにシードします。
-Jasen

1
@Jasen、同じエクステンションリードに接続されているすべてのユニットは、同じメインハムを確認します。
イアンリングローズ

2

内部の「キャリブレーションされた」クロックソースで実行している場合。しばらくしてから、EEPROMにシードを保存してください。クロックはドリフトし、ユニットごとに異なります。しばらくしてから新しい値を保存するには(10分ごと、またはデバイスの通常のオン時間内に発生するのに十分短い時間後。デバイスの電源が長いほど保存される可能性が高くなります) EEPROMへの「異なる」値。

また、時々(一度だけ)飛躍し、デバイスがオンのときに再シードします(この新しい値をEEPROMに保存します)。


2

LDRまたはサーミスタを追加することにより、可変抵抗に基づいてAD変換の元のアイデアを拡張するのはどうですか?(最初は外を「見る」必要がありますが、それが実現可能かどうかはわかりませんが、光の変動は、ほぼ同じ場所でほぼ同時に開始されたデバイス間の温度の変動よりも大きい場合があります。 ..)


1
サーミスタには別の有用な特性があります。ほとんどのメーカーのいくつかのシリーズには、大きなばらつきと不正確さがあります。これにより、結果がさらに「改善」されます。
アライザー

1

2つの潜在的なソリューション。どちらもユニットごとに一意のシードが必要であると仮定しています。

  1. 工場でユニットを1つずつフラッシュする場合、16進数ファイルはプログラマーの中間スクリプトによってプログラムで変更できます。PC制御の場合、変数の初期化を日付と時刻で上書きできます。ユニットごとに一意であることが保証されています!

  2. ダラス1ワイヤデバイスは1つのピンのみを使用し、それぞれに一意の64ビットシリアル番号が付いています。これをシードとして使用できます。


1
私は2が好きですが、残念ながらDSの部品はすべてかなり高価です。
アライザー

暗号品質のランダム性にプロダクションタイムスタンプを使用しないでください。予測可能です。

2
@CamilStaps OPのアプリケーションでは、暗号品質は必要ありません
ハーゲンフォン

1
@HagenvonEitzen trueですが、暗号Qのランダム性を検索する他の人がこの質問に来る可能性があるため、言及する価値があります。

4
@CamilStaps ため息、あなたは人類をあきらめたようです:) ?「16ビット」または「5 o5 6ビット」シードは、シュレディンガー猫の束によって生成された場合でも暗号Qではありません:)
ハーゲンフォンエイツェン

1

キャプチャされたノイズをランダムジェネレーター(RNG)に供給するために、フローティングADCピンを残すことができます。シードを生成するか、RNGジェネレーターとして使用するのに十分なはずです。

最小限の変換時間を使用することを忘れないでください。

もう1つの解決策は、ADCピンにノイズジェネレータを適用することです。


2
いくつかの測定を行いますが、正しく覚えていれば、フローティングADCピンがを読み取る0か、近くにあり0ます。もう一度確認して、そうであるかどうかを確認します。
-vsz

1
興味がありますが0、浮いているときに読みますか?
ベンスカウリックス

2
問題は、これが開発ボードで機能し、最終製品で失敗する可能性があることです。
-vsz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.