Ein kleiner Mikrocontroller (8-Bit-Atmel) steuert eine Reihe von Lichtern, um eine Lichtshow mit vielen ausgefallenen zufälligen Lichtsequenzen zu präsentieren.
Ein geeignetes Pseudo-RNG macht seine Arbeit gut, aber ich suche einen guten Samen dafür. Ein Startwert ist erforderlich, da es nicht gut aussieht, wenn jemand mehrere solcher Geräte gleichzeitig einschaltet, wenn alle dieselben Effektsequenzen erzeugen, bis sie aufgrund der winzigen Unterschiede in ihren einzelnen Taktquellen langsam auseinander driften.
Eine sehr gute Methode, um ein Pseudo-RNG zu setzen, das ich oft verwendet habe, ist bei einem Gerät möglich, das per Knopfdruck oder durch Drücken eines Schalters gestartet werden muss. Sobald der µc eingeschaltet ist, kann ein sehr schneller Timer gestartet werden, und der Wert dieses Timers setzt den RNG, sobald die Taste zum ersten Mal gedrückt wird.
Das Problem ist, dass in diesem Szenario keine Schaltflächen vorhanden sind. Das Programm muss gestartet werden, sobald das Gerät eingeschaltet wird.
Der Platz auf der Leiterplatte ist extrem begrenzt (es passen möglicherweise nicht mehr als ein paar der kleinsten SMD-Teile), daher suche ich nach der kleinsten und einfachsten möglichen Lösung. Daher schließe ich ausgefallene Lösungen wie echte RNG-Hardware, Funkempfänger usw. aus.
Alles, was ich habe, ist ein 16-Bit-Timer-Zähler in der CPU und ein unbenutzter Portpin, der Zugriff auf einen ADC hat.
Meine derzeitige Lösung besteht darin, nur einen Widerstand (so ungenau wie möglich) zu verwenden, um ungefähr die Hälfte der Versorgungsspannung für den ADC-Pin bereitzustellen, und den RNG mit dem ersten AD-Umwandlungswert zu setzen. Heutzutage haben die meisten 10% -Widerstände jedoch eine Ungenauigkeit von weit unter 1% (es wäre lustig, sich das Gesicht eines Lieferanten vorzustellen, wenn ich ihnen sage, dass wir die schlechtesten SMD-Widerstände suchen, die sie finden können), daher besteht eine sehr hohe Wahrscheinlichkeit für mehrere Einheiten, die mit demselben Samen beginnen.
Eine bessere Alternative wäre, mehrere Konvertierungen durchzuführen und einen Wert aus den niedrigstwertigen Bits dieser Messungen zu erstellen. Ich habe jedoch zuvor den ADC dieses µc-Typs verwendet und weiß, dass er sehr genau ist. Hier kann es hilfreich sein, den ADC mit der schnellstmöglichen Geschwindigkeit zu betreiben.
Hat jemand einen besseren Vorschlag? Es ist nicht erforderlich, dass das Saatgut perfekt gleichmäßig verteilt ist, aber je gleichmäßiger die Verteilung ist, desto besser. Ein 16-Bit-Startwert mit einer vollkommen gleichmäßigen Verteilung wäre ein Traum, der zu schön ist, um wahr zu sein, aber ich denke, eine halbwegs anständige Verteilung über 5 oder 6 Bits könnte ausreichen.
quelle
Antworten:
Legen Sie einen Parallelwiderstand und einen Kondensator zwischen den A / D-Pin und Masse. Stellen Sie den Widerstand ziemlich hoch ein, vorzugsweise weit über der Impedanzanforderung für das Eingangssignal für den A / D. Stellen Sie die RC-Zeitkonstante auf etwa 10 µs ein. Zum Beispiel klingt 100 kΩ und 100 pF wie eine gute Kombination.
Um einen Wert mit einer gewissen Zufälligkeit zu erhalten, fahren Sie den Stift eine Weile hoch, stellen Sie ihn dann auf hohe Impedanz und führen Sie einige µs später eine A / D-Messung durch. Insbesondere wenn Sie die A / D-Erfassungszeit richtig ausnutzen, hängt die Spannung, die angezeigt wird, von den R- und C-Werten, dem Pin-Leckstrom, anderen Nebengeräuschen und der Temperatur ab.
Ergreifen Sie das niedrige Bit oder die niedrigen zwei Bits und wiederholen Sie diese Schritte nach Bedarf, um eine beliebige Anzahl von Zufallsbits zu erhalten.
Für ein zufälligeres Muster führen Sie diesen Vorgang gelegentlich durch und injizieren Sie das niedrige Bit des A / D-Ergebnisses in den Zufallszahlengenerator, den Sie bereits verwenden.
quelle
Einige mögliche Optionen:
Programmieren Sie eine eindeutige Serienadresse für jedes Gerät vor. Wenn Sie über einen ausreichend guten RNG-Algorithmus verfügen, führt auch eine fortlaufende Liste serieller Adressen zu völlig unterschiedlichen Ergebnissen.
Abhängig von Ihrer MCU / Ihrem Setup stehen möglicherweise zwei unterschiedliche Taktquellen für die Systemuhr und den Watchdog-Timer / Timer-Zähler-Eingang zur Verfügung. Wenn eine / beide signifikante Abweichungen aufweisen, können Sie diese verwenden, um einen entsprechend anderen Samen zu erzeugen. Hier ist ein Beispiel, das ich geschrieben habe und das einen internen Watchdog-Timer von Arduino und eine externe XTAL-Systemuhr verwendet .
Verwenden Sie einen BJT-Transistor und bauen Sie einen in hohem Maße Beta-abhängigen Verstärker. Dies kann von einem ADC für den Startwert gelesen werden.
Kondensatoren / Induktivitäten weisen normalerweise eine viel schlechtere Toleranz als Widerstände auf. Sie könnten damit eine Art Filterschaltung (RC, RL, LC) aufbauen und den Ausgang mit dem ADC messen.
quelle
Nicht initialisierter Speicher
Sie können versuchen, den nicht initialisierten Speicher des Mikrocontrollers zu verwenden. Der Trick besteht darin, die Bits zu finden, die die "ausgeglichensten" Flip-Flops aufweisen und tatsächlich zufällig sind. Das Verfahren besteht darin, den gesamten Speicher auszulesen, zurückzusetzen und einige Male zu wiederholen, um zu messen, welche Bits wirklich zufällig sind. Dann verwenden Sie diese Karte, um genügend zufällige Bits auszulesen, um Ihr PRNG oder LFSR zu setzen!
Diese Methode sollte Ihnen auch bei identischer Hardware zufällige Startwerte liefern. Weitere Details (und Links) finden Sie in diesem Artikel
Diese Methode gefällt mir, weil keine zusätzlichen Schaltkreise oder Pins erforderlich sind. Ihr AVR hat bereits RAM, Sie müssen nur die instabilen (zufälligen) Bits finden. Auch das Mapping-Verfahren könnte automatisiert werden; Sie können auf jedes Gerät denselben Code und dieselbe Prozedur anwenden und wirklich zufällige Ergebnisse erzielen!
quelle
Was ich für einen MP3-Player mit Zufallsfunktion getan habe, ist, bei jedem Einschalten einfach einen anderen sequentiellen Startwert zu verwenden. Ich habe bei 1 begonnen und dies im EEPROM gespeichert, so dass ich beim nächsten Ein- und Ausschalten 2 usw. verwendete. Dies war auf einem ATMEGA168. Wie helloworld922 feststellte, wird selbst ein einfacher sequentieller Startwert völlig unterschiedliche Pseudozufallssequenzen erzeugen.
Ich habe einen der linear kongruenten Zufallsgeneratoren verwendet, dies ergibt eine gleichmäßige Verteilung.
Natürlich, wenn Sie möchten, dass mehrere Geräte unterschiedliche Sequenzen haben, obwohl sie möglicherweise die gleiche Anzahl von Einschaltzyklen hatten, müssen Sie etwas nach dem Zufallsprinzip starten.
Dies könnte mit einer der Methoden geschehen, die auf den anderen Postern vorgeschlagen wurden. Eine Methode, die ich mir vorstellen kann, könnte den Wechselstrom-Nulldurchgang verwenden, der in den Prozessor fließt, wenn Sie ihn haben (zum Beispiel zur Steuerung der Lampenphase). Dies könnte verwendet werden, um den Timer bei der ersten Kreuzung nach dem Einschalten abzutasten und dann als Startwert zu verwenden.
Befinden sich am Gerät Tasten zur Auswahl des Modus usw.? Wenn dies der Fall ist, können Sie den Zähler beim ersten Drücken der Taste nach dem Programmieren der MCU abtasten. Sie können zunächst einen zufälligen Startwert generieren und im EEPROM speichern. Bei jedem Einschalten nach diesem Zeitpunkt wird der gespeicherte Startwert verwendet.
quelle
Ein ADC ist eine sehr gute Quelle für Zufälligkeiten.
Sie müssen sich nicht auf Widerstandstoleranzen verlassen. Jeder Widerstand erzeugt thermisches Rauschen und der gleiche physikalische Effekt führt bei allen Abtast- und Umwandlungsschritten Rauschen in den ADC ein. (Das Datenblatt gibt Auskunft über die Lautstärke und die schlechtesten / besten Konfigurationseinstellungen.)
Sie sollten den ADC-Pin nicht schweben lassen. Dies kann dazu führen, dass die Spannung zu weit schwimmt und der Eingang möglicherweise gesättigt wird.
(Bei vielen MCUs können Sie ungefähr die Hälfte der Versorgungsspannung als ADC-Eingang für die Kalibrierung verwenden. Dadurch wird der externe Widerstand geschont und es treten weiterhin Störungen auf. Die schlechteste / beste Konfiguration finden Sie im Datenblatt.)
Sie müssen sich nicht auf eine einzige ADC-Messung verlassen. Sie können mehrere Messungen mit einer einfachen Hash- oder Prüfsummenfunktion kombinieren (CRC würde ausreichen). Wenn Sie den RNG sofort verwenden müssen, können Sie das ADC-Ergebnis später mit dem aktuellen RNG-Startwert kombinieren.
quelle
40uV
Johnson-Rauschen. Sie benötigen einen> 14-Bit-ADC oder eine Verstärkerschaltung, um dies angemessen zu messen.Können Sie den Samen von Sitzung zu Sitzung speichern? Wenn ja, ist es möglich, jedes Gerät nach der Erstellung für einen zufälligen Zeitraum einzuschalten? Auf diese Weise werden alle Einheiten mit voreingestellten Samen geliefert, die wahrscheinlich nicht gleich sind.
Ein anderer Gedanke: Wie können Sie mehrere Geräte miteinander verbinden, damit sie gleichzeitig eingeschaltet werden? Wenn sie in Reihe geschaltet sind, fügen Sie eine Art Kondensator hinzu, damit das (n + 1) -te Gerät einige Taktzyklen nach dem n-ten Gerät startet. Im Idealfall entladen sich Kondensatoren beim Herunterfahren des Geräts sehr schnell, sodass bei jedem Start / Neustart eine größere Lücke zwischen den Sequenzen entsteht.
Wenn sie parallel sind, können Sie die Startzeit noch ein wenig zufällig einstellen. Ich gehe davon aus, dass es eine Art Leistungsfilterung mit Kondensatoren gibt. In diesem Fall würde die Herstellung der Geräte mit geringfügig unterschiedlichen Filterkreisläufen dazu führen, dass jedes Gerät zu einem geringfügig unterschiedlichen Zeitpunkt startet und nach mehreren Neustarts eine Divergenz auftritt.
Eine Variation hiervon besteht darin, Ihren Taktsignalen nach Möglichkeit eine Varianz hinzuzufügen. Ein Unterschied von 0,1% in der Taktrate hat möglicherweise nur geringe Auswirkungen auf die Lichtshow, während Sie die Geschwindigkeit, mit der Sie die PRNG-Tabelle durchlaufen, relativ schnell ändern.
quelle
Wenn Sie mit einer internen "kalibrierten" Taktquelle arbeiten. Könnten Sie einen Startwert nach einiger Zeit nicht speichern, vorzugsweise in das EEPROM. Die Uhr driftet und unterscheidet sich von Gerät zu Gerät. Zum erneuten Speichern eines neuen Werts nach einiger Zeit (etwa alle 10 Minuten oder nach einer Zeit, die kurz genug ist, um innerhalb der normalen Einschaltdauer des Geräts zu liegen. Je länger das Gerät eingeschaltet ist, desto wahrscheinlicher ist die Speicherung ein "anderer" Wert in das EEPROM.
Machen Sie auch ab und zu einen Sprung (nicht zu oft) und wiederholen Sie die Zeit, während das Gerät eingeschaltet ist (speichern Sie diesen neuen Wert im EEPROM).
quelle
Wie wäre es, wenn Sie Ihre ursprüngliche Idee der AD-Wandlung basierend auf einem variierenden Widerstand durch Hinzufügen eines LDR oder Thermistors erweitern würden? (Der erste müsste in der Lage sein, nach draußen zu "schauen", ich weiß nicht, ob das machbar ist; aber die Variation des Lichts kann höher sein als die Variation der Temperatur zwischen Geräten, die ungefähr zur selben Zeit an ungefähr derselben Stelle gestartet wurden. ..)
quelle
2 mögliche Lösungen, vorausgesetzt, Sie benötigen einen eindeutigen Startwert pro Einheit.
Wenn Sie Ihre Einheiten ab Werk einzeln flashen, kann die Hex-Datei durch ein Zwischenskript im Programmierer programmgesteuert geändert werden. Wenn es PC-gesteuert ist, können Sie eine variable Initialisierung mit Datum und Uhrzeit überschreiben. Garantiert einzigartig für jede Einheit!
Dallas 1-Draht-Geräte verwenden nur einen Pin und haben jeweils eine eindeutige 64-Bit-Seriennummer. Sie können dies als Samen verwenden.
quelle
Sie können einen potentialfreien ADC-Pin belassen, um den Zufallszahlengenerator (RNG) mit erfasstem Rauschen zu versorgen. Es sollte ausreichen, einen Startwert zu generieren oder ihn sogar als RNG-Generator zu verwenden.Vergessen Sie nicht, die minimal mögliche Konvertierungszeit zu verwenden.
Die andere Lösung könnte ein Rauschgenerator sein, der in den ADC-Pin eingesetzt wird.
quelle
0
oder nähert sich0
. Ich werde es noch einmal überprüfen, um festzustellen, ob dies der Fall ist.0
beim schweben?