Un petit microcontrôleur (Atmel 8 bits) contrôle un certain nombre de lumières afin de présenter un spectacle lumineux avec de nombreuses séquences lumineuses aléatoires fantaisistes.
Un pseudo-RNG approprié fait bien son travail, mais je cherche une bonne graine pour cela. Une graine sera nécessaire, car si quelqu'un allume plusieurs de ces dispositifs en même temps, il ne semblera pas bon qu'ils génèrent tous les mêmes séquences d'effets jusqu'à ce qu'ils se séparent lentement en raison des différences minimes entre leurs sources d'horloge individuelles.
Une très bonne méthode pour générer un pseudo-RNG, que j'ai souvent utilisée, est possible dans le cas d'un périphérique devant être démarré par une simple pression sur un bouton ou un commutateur. Dès que le µc est mis en marche, une minuterie très rapide peut être démarrée et la valeur de cette minuterie sème le RNG dès que le bouton est pressé pour la première fois.
Le problème est que, dans ce scénario, il n'y a pas de boutons. Le programme doit démarrer dès que l'appareil est allumé.
La place sur le circuit imprimé est extrêmement limitée (seules quelques-unes des plus petites pièces CMS peuvent être utilisées), je recherche donc la solution la plus petite et la plus simple possible. Par conséquent, j'éliminerai les solutions sophistiquées telles que le vrai matériel RNG, les récepteurs radio, etc.
Tout ce que j'ai est un compteur de minuterie 16 bits dans la CPU, et un portpin inutilisé qui a accès à un ADC.
Ma solution actuelle consiste simplement à utiliser une résistance (aussi imprécise que possible) pour fournir environ la moitié de la tension d'alimentation à la broche du convertisseur analogique-numérique, et ensemencer le générateur de base de réseau avec la première valeur de conversion AD. Cependant, de nos jours, la plupart des résistances à 10% ont une imprécision bien inférieure à 1% (il serait amusant d’imaginer le visage d’un fournisseur lorsque je leur dis que nous voulons les résistances CMS les plus médiocres qu’elles puissent trouver). plusieurs unités commençant par la même graine.
Une meilleure solution consisterait à effectuer plusieurs conversions et à créer une valeur à partir des bits les moins significatifs de ces mesures. Cependant, j’avais utilisé un ADC de ce type avant et je sais que c’est très précis. Faire fonctionner le CAN à la vitesse la plus rapide possible pourrait aider ici.
Quelqu'un a-t-il une meilleure suggestion? Il n'est pas nécessaire que la graine soit parfaitement uniformément distribuée, mais plus la distribution est uniforme, mieux c'est. Une graine de 16 bits avec une distribution parfaitement uniforme serait un rêve trop beau pour être vrai, mais je pense qu'une distribution à peu près décente sur 5 ou 6 bits pourrait suffire.
Réponses:
Placez une résistance parallèle et un condensateur entre la broche A / D et la terre. Rendez la résistance assez haute, de préférence bien au-dessus de l'impédance du signal d'entrée requise pour le convertisseur analogique-numérique. Faites la constante de temps RC peut-être autour de 10 µs. Par exemple, 100 kΩ et 100 pF semblent constituer une bonne combinaison.
Pour obtenir une valeur quelque peu aléatoire, enfoncez la broche pendant un moment, puis réglez-la sur une impédance élevée et effectuez une lecture A / N quelques µs plus tard. En particulier si vous abusez correctement du temps d’acquisition A / N, la tension qu’elle verra dépendra des valeurs de R et C, du courant de fuite de la broche, des autres bruits à proximité et de la température.
Saisissez le bit bas ou les deux bits bas et répétez-le si nécessaire pour obtenir un nombre quelconque de bits aléatoires.
Pour un motif plus aléatoire, effectuez de temps en temps cette procédure et injectez le bit le plus faible du résultat A / D dans le générateur de nombre aléatoire que vous utilisez déjà.
la source
Quelques options possibles:
Pré-programmez une adresse série unique pour chaque périphérique. Si vous avez un assez bon algorithme RNG, alors même une liste séquentielle d'adresses série produira des résultats très différents.
En fonction de votre MCU / configuration, vous pouvez avoir deux sources d'horloge différentes disponibles pour l'horloge système et l'entrée de chien de garde / compteur. Si l'une / les deux ont une variance significative, vous pouvez l'utiliser pour générer une graine convenablement différente. Voici un exemple que j'ai écrit et qui utilise un minuteur de surveillance interne Arduino et une horloge système XTAL externe .
Utilisez un transistor BJT et construisez un amplificateur fortement dépendant de la bêta. Cela peut être lu à partir d'un ADC pour la graine.
Les condensateurs / inducteurs sont généralement spécifiés avec une tolérance bien plus mauvaise que les résistances. Vous pouvez construire une sorte de circuit de filtrage (RC, RL, LC) avec ceux-ci et mesurer la sortie avec le CAN.
la source
Mémoire non initialisée
Vous pouvez essayer d'utiliser la mémoire non initialisée dans le microcontrôleur. L'astuce consiste à trouver les bits qui ont les bascules les plus «équilibrées» et qui sont réellement aléatoires. La procédure consiste à lire toute la mémoire, à réinitialiser et à répéter plusieurs fois pour déterminer quels bits sont réellement aléatoires. Ensuite, vous utilisez cette carte pour lire suffisamment de bits aléatoires pour ensemencer votre PRNG ou votre LFSR!
Cette méthode devrait vous donner des graines au hasard, même avec un matériel identique, plus de détails (et liens) sont disponibles dans ce hack-a-jour l' article
J'aime cette méthode car elle ne nécessite pas de circuit supplémentaire ni de broches; votre AVR a déjà de la RAM, il vous suffit de trouver les bits instables (aléatoires). La procédure de mappage pourrait également être automatisée; vous pouvez appliquer le même code et la même procédure à chaque appareil et obtenir des résultats vraiment aléatoires!
la source
Ce que j'ai fait pour un lecteur MP3 avec une capacité aléatoire, c'est simplement d'utiliser une graine séquentielle différente à chaque mise sous tension. J'ai commencé à 1 et l'ai stocké dans l'EEPROM afin qu'au prochain cycle d'alimentation, j'en ai utilisé 2, etc. C'était sur un ATMEGA168. Comme helloworld922 l'a noté, même une simple graine séquentielle générera des séquences pseudo aléatoires complètement différentes.
J'ai utilisé l'un des générateurs de séquence aléatoire congruente linéaire, ce qui donne une distribution uniforme.
Bien sûr, si vous voulez que plusieurs unités aient différentes séquences même si elles ont eu le même nombre de cycles d'alimentation, vous avez besoin de quelque chose pour commencer de manière aléatoire.
Cela pourrait être fait par l’une des méthodes proposées par les autres affiches - une méthode à laquelle je peux penser pourrait utiliser le passage à zéro alternatif entrant dans le processeur si vous l’avez (pour le contrôle de la phase de la lampe, par exemple)? Cela pourrait être utilisé pour échantillonner la minuterie lors du premier passage suivant la mise sous tension, puis utilisé comme germe.
Y a-t-il des boutons sur l'appareil pour sélectionner le mode, etc.? Si vous pouvez ainsi échantillonner le compteur la toute première fois que vous appuyez sur le bouton après la programmation de la MCU, vous pouvez générer une graine aléatoire au départ et la stocker dans une EEPROM. Chaque mise sous tension après ce point utiliserait la graine stockée.
la source
Un ADC est une très bonne source d’aléatoire.
Vous n'avez pas besoin de vous fier aux tolérances de la résistance. Toute résistance générera du bruit thermique et le même effet physique introduira du bruit dans le CAN lors de toutes les étapes d'échantillonnage et de conversion. (La fiche technique vous indiquera la quantité de bruit et les paramètres de configuration les plus défavorables.)
Vous ne devriez pas laisser la broche ADC flottante; cela pourrait laisser la tension flotter trop loin et risquer de saturer l'entrée.
(De nombreux microcontrôleurs vous permettent d'utiliser environ la moitié de la tension d'alimentation comme entrée ADC, pour l'étalonnage. Cela permet d'économiser la résistance externe tout en générant du bruit. Consultez à nouveau la fiche technique pour connaître la configuration la plus mauvaise / meilleure.)
Vous n'avez pas besoin de compter sur une seule mesure ADC; vous pouvez combiner plusieurs mesures avec une simple fonction de hachage ou de somme de contrôle (un contrôle CRC suffirait). Si vous devez commencer à utiliser le RNG immédiatement, vous pouvez ultérieurement combiner le résultat de l'ADC avec le germe RNG actuel.
la source
40uV
bruit de Johnson. Vous aurez besoin d’un CAN> 14 bits ou d’un circuit amplificateur pour pouvoir mesurer ce phénomène.Pouvez-vous sauvegarder la graine d'une session à l'autre? Dans l’affirmative, est-il possible d’allumer chaque unité pendant un certain temps après sa création? Ainsi, toutes les unités seront expédiées avec des semences prédéfinies qui ne seront probablement pas les mêmes.
Une autre pensée: comment relier plusieurs unités afin qu’elles s’allument simultanément? S'ils sont en série, ajoutez une sorte de condensateur pour que le (n + 1) ème appareil commence quelques cycles d'horloge après le nième appareil. Dans l’idéal, les condensateurs se déchargent très rapidement à l’arrêt de l’appareil. Ainsi, chaque démarrage / redémarrage crée un intervalle plus grand entre les séquences.
S'ils sont en parallèle, vous pouvez toujours randomiser un peu le temps de démarrage. Je suppose qu'il existe une sorte de filtrage de puissance utilisant des condensateurs. Dans ce cas, la fabrication des appareils avec des circuits de filtration légèrement différents provoquerait le démarrage de chaque appareil à une heure légèrement différente, ce qui causerait une divergence après plusieurs redémarrages.
Une variante consiste à ajouter de la variance à vos signaux d'horloge, si possible. Une différence de 0,1% de la vitesse d'horloge peut avoir peu d'impact sur le jeu de lumière, tout en modifiant assez rapidement le taux de traversée du tableau PRNG.
la source
Si vous utilisez une source d'horloge interne "calibrée". Ne pourriez-vous pas conserver une graine après un certain temps, de préférence dans l’EEPROM. L'horloge va dériver et différer d'une unité à l'autre. Pour enregistrer une nouvelle valeur après un certain temps (toutes les 10 minutes environ, ou après un temps suffisamment court pour se produire dans les délais impartis pour le périphérique. Plus le périphérique est allumé longtemps, plus il économisera une valeur "différente" dans la mémoire EEPROM.
Faites également un saut de temps en temps (pas trop souvent) et réamorcez lorsque le périphérique est allumé (enregistrez cette nouvelle valeur dans EEPROM).
la source
Que diriez-vous d'étendre votre idée originale de conversion AD basée sur une résistance variable en ajoutant un LDR ou une thermistance? (Le premier devrait pouvoir "regarder" dehors, je ne sais pas si c'est faisable, mais la variation de la lumière peut être supérieure à la variation de la température entre les dispositifs démarrés à peu près au même moment à peu près au même endroit. ..)
la source
Deux solutions potentielles, les deux supposant que vous avez besoin d'une graine unique par unité.
Si vous flashez vos unités une à une dans l'usine, le fichier hexadécimal peut être modifié par programme par un script intermédiaire du programmeur. S'il est contrôlé par l'ordinateur, vous pouvez écraser une initialisation de variable avec la date et l'heure. Garanti d'être unique pour chaque unité!
Les appareils Dallas 1 wire utilisent une seule broche et sont dotés d’un numéro de série 64 bits unique. Vous pouvez l'utiliser comme la graine.
la source
Vous pouvez laisser une broche ADC flottante pour alimenter le générateur de nombres aléatoires (RNG) avec le bruit capturé. Cela devrait suffire à générer une graine ou même à l'utiliser comme générateur de GNA.N'oubliez pas d'utiliser le temps de conversion minimum possible.
L'autre solution pourrait être un générateur de bruit appliqué à la broche ADC.
la source
0
ou près de0
. Je vais vérifier à nouveau pour voir si c'est le cas.0
quand on flotte?