Qual è il seme più piccolo e più semplice per un generatore di numeri casuali?


40

Un piccolo microcontrollore (Atmel a 8 bit) controlla un numero di luci per presentare uno spettacolo di luci con molte sequenze di luce casuali fantasiose.

Uno pseudo-RNG adatto fa bene il suo lavoro, ma sto cercando un buon seme per questo. Sarà necessario un seme perché se qualcuno accende più dispositivi contemporaneamente, non sembrerà buono se tutti generassero le stesse sequenze di effetti finché non si allontanano lentamente a causa delle piccole differenze nelle loro singole sorgenti di clock.

Un ottimo metodo per seminare uno pseudo-RNG, che ho usato spesso, è possibile nel caso di un dispositivo che deve essere avviato con la pressione di un pulsante o la rotazione di un interruttore. Non appena µc è acceso, è possibile avviare un timer molto veloce e il valore di questo timer semina l'RNG non appena si preme il pulsante per la prima volta.

Il problema è che in questo scenario non ci sono pulsanti. Il programma deve iniziare non appena il dispositivo è acceso.

La posizione sul PCB è estremamente limitata (solo alcune delle parti SMD più piccole potrebbero adattarsi), quindi sto cercando la soluzione più piccola e più semplice possibile. Pertanto escluderò soluzioni fantasiose come hardware RNG reale, ricevitori radio, ecc.

Tutto quello che ho è un contatore-timer a 16 bit nella CPU e un portpin inutilizzato che ha accesso a un ADC.

La mia attuale soluzione è quella di utilizzare un resistore (il più impreciso possibile) per fornire circa la metà della tensione di alimentazione al pin ADC e inviare il RNG con il primo valore di conversione AD. Tuttavia, al giorno d'oggi la maggior parte dei resistori al 10% ha un'imprecisione ben al di sotto dell'1% (sarebbe divertente immaginare il volto di un fornitore quando dico loro che vogliamo i resistori SMD di peggiore qualità che riescano a trovare), quindi c'è un'alta probabilità di più unità che iniziano con lo stesso seme.

Un'alternativa migliore sarebbe quella di fare più conversioni e costruire un valore dai bit meno significativi di queste misurazioni. Tuttavia, ho usato l'ADC di questo tipo µc prima e so che è molto preciso. L'esecuzione dell'ADC alla massima velocità possibile potrebbe essere utile qui.

Qualcuno ha un suggerimento migliore? Non è necessario che il seme sia distribuito in modo perfettamente uniforme, ma più uniforme è la distribuzione, meglio è. Un seme a 16 bit con una distribuzione perfettamente uniforme sarebbe un sogno troppo bello per essere vero, ma penso che una distribuzione a metà strada decente su 5 o 6 bit potrebbe essere sufficiente.


12
"Sarebbe divertente immaginare il volto di un fornitore quando dico loro che vogliamo i resistori SMD di peggiore qualità che riescono a trovare" - sarebbe ancora più divertente lasciare che il valore di questo resistore fosse indefinito nello schema elettrico e dire al le persone in produzione che questa parte deve essere saldata manualmente dopo che il pcb esce dalla macchina di posizionamento, da un cestino in cui abbiamo mescolato insieme ogni valore di resistenza che abbiamo. - Perché non sto cercando un RNG, ma un seme . Quindi, se genera lo stesso valore quasi ogni volta che non è poi così male, è più importante essere diversi tra i dispositivi.
vsz

8
Perché non scrivere un valore casuale nella memoria EEPROM durante la programmazione della produzione? In questo modo, è possibile utilizzare l'RNG più elegante che ti piace in quanto sarà solo nei programmatori di produzione e non nei dispositivi finali. (Ringrazio @immibis: il tuo 'file software leggermente diverso' mi ha dato l'idea.)
Calrion,

2
Quindi, solo per essere chiari al 100%, il problema è che potrebbero iniziare sulla stessa sequenza, non che potrebbero andare alla deriva nel tempo, giusto?
wedstrom,

2
La scelta del tuo RNG è importante: alcuni hanno bisogno di semi di buona qualità, altri no. Ad esempio, per Xorshift, qualsiasi seme diverso da 0 funzionerà e funzionerà ugualmente bene. Anche una piccola differenza nel seme iniziale provocherà una posizione di partenza molto diversa nel ciclo del RNG.
curiousdannii,

3
Puoi combinare tutte le risposte ADC con statistiche e tempistiche per una casualità ancora maggiore. Ad esempio, misurare il numero di tick del processore necessari fino a quando non si prendono N campioni in cui i 3 LSB inferiori sono 101 e M campioni in cui i 3 LSB inferiori sono 110. Espandere questo concetto come desiderato.
wjl

Risposte:


24

Inserire una resistenza e un condensatore paralleli tra il pin A / D e la terra. Rendere il resistore abbastanza alto, preferibilmente ben al di sopra del requisito di impedenza del segnale di ingresso per l'A / D. Rendere costante il tempo RC forse intorno a 10 µs. Ad esempio, 100 kΩ e 100 pF sembrano una buona combinazione.

Per ottenere un valore con una certa casualità, spingere il perno in alto per un po ', quindi impostarlo su un'impedenza elevata e prendere una lettura A / D dopo alcuni µs. Soprattutto se si abusa correttamente del tempo di acquisizione A / D, la tensione che vedrà dipenderà dai valori R e C, dalla corrente di dispersione dei pin, da altri rumori vicini e dalla temperatura.

Prendi il bit basso o il minimo due e ripeti se necessario per ottenere un numero qualsiasi di bit casuali.

Per un modello più casuale, eseguire questa procedura di tanto in tanto e iniettare il bit basso del risultato A / D nel generatore di numeri casuali che si sta già utilizzando.


Questo suona bene. Assicurati di controllare l'impedenza di ingresso sull'ADC - la serie Atmega8 ha un'impedenza di ingresso analogica di 100Meg che rende il valore della resistenza di Olin un po 'basso.
Stefandz,

3
@stef: l'impedenza di ingresso e l'impedenza del segnale necessarie per una corretta conversione sono due cose diverse. Sì, l'impedenza di ingresso è molto elevata poiché è CMOS. Tuttavia, esiste un limite di impedenza massima sul segnale per consentirgli di caricare il campione e trattenere il tappo entro il tempo specificato e di superare qualsiasi perdita che può avere il pin.
Olin Lathrop,

2
scusate, dalla vostra risposta ho pensato che steste facendo riferimento all'impedenza di ingresso invece delle specifiche di impedenza della sorgente. 10k è l'impedenza massima specificata dell'Atmega8, quindi la tua risposta è perfetta. Per riferimento, il cappuccio S / H all'interno è 14pF, nel caso qualcuno fosse interessato.
Stefandz,

2
@stef: ho modificato la risposta per renderlo più chiaro.
Olin Lathrop,

Hai perso la fase lunare e le festività. Anche agitando a mano un'aggiunta utile, soprattutto se a bassa C e non ben schermato.
Russell McMahon,

23

Alcune opzioni possibili:

  1. Pre-programmare un indirizzo seriale univoco per ciascun dispositivo. Se disponi di un algoritmo RNG abbastanza buono, anche un elenco sequenziale di indirizzi seriali produrrà risultati molto diversi.

  2. A seconda dell'MCU / della configurazione, è possibile che siano disponibili due diverse sorgenti di clock per l'orologio di sistema e l'ingresso timer / timer contatore watchdog. Se uno / entrambi hanno una varianza significativa, puoi usarlo per generare un seme adeguatamente diverso. Ecco un esempio che ho scritto che utilizza un timer di watchdog interno di Arduino e un clock di sistema XTAL esterno .

  3. Usa un transistor BJT e costruisci un amplificatore altamente dipendente dalla beta. Questo può essere letto da un ADC per il seme.

  4. I condensatori / induttori sono generalmente indicati con una tolleranza molto peggiore rispetto ai resistori. Potresti costruire una sorta di circuito di filtro (RC, RL, LC) con questi e misurare l'uscita con l'ADC.


5
Io voto per l'opzione 1, è una soluzione di conteggio delle parti pari a zero che si tradurrà in sequenze mai dovute corrispondere. Il numero di serie e il generatore RND possono dire 16 bit rendendo ogni dispositivo ha una probabilità trascurabile di imitare il modello di un altro.
KalleMP

1
Mi piace anche la soluzione. Se usi un semplice algoritmo di hashing dovresti andare bene anche se hai numeri di serie sequenziali.
magu_

6
Una cosa bella dell'opzione 1 è che alcuni dispositivi sono dotati di numeri di serie integrati (di solito micro relativi alla rete / RF), quindi non è nemmeno necessario un passaggio separato per masterizzare i numeri di serie
slebetman,

3
Anche un RNG spazzatura come un LCG sarà "produrre risultati molto diversi per un elenco sequenziale di indirizzi seriali" . Voto anche per 1.
BlueRaja - Danny Pflughoeft il

3
Se hai una fonte di tempo, usarla come base per il tuo switch on seed ti aiuterà a compensare le cose tra le esecuzioni. Combina questo con un indirizzo / numero seriale o l'indirizzo MAC se il tuo dispositivo ne ha uno e correggerai anche la corrispondenza tra dispositivi. Ho visto alcuni software che memorizzano in modo persistente alcuni o tutti i numeri casuali generati per l'uso come seed, anche dopo un riavvio. Se i tuoi dispositivi hanno tempi di funzionamento diversi, devono andare alla deriva.
TafT

8

Memoria non inizializzata

È possibile provare a utilizzare la memoria non inizializzata nel micro controller. Il trucco è trovare i bit che hanno i flip-flop più "bilanciati" e in realtà casuali. La procedura è leggere tutta la memoria, ripristinare e ripetere alcune volte per misurare quali bit sono veramente casuali. Quindi usi questa mappa per leggere abbastanza bit casuali per seminare il tuo PRNG o LFSR!

Questo metodo dovrebbe darvi semi casuali, anche con hardware identico, maggiori dettagli (e link) sono disponibili in questo hack-a-day articolo

Mi piace questo metodo perché non richiede alcun circuito o pin aggiuntivo; il tuo AVR ha già ram, devi solo trovare i bit instabili (casuali). Anche la procedura di mappatura potrebbe essere automatizzata; puoi applicare lo stesso codice e la stessa procedura a ciascun dispositivo e ottenere risultati davvero casuali!


1
Non hai davvero bisogno di capire quali bit sono casuali. XORing di tutti i byte ti darà un risultato casuale anche se solo 8 bit sono casuali. E come mostra l'immagine, i valori reali potrebbero non essere casuali in senso temporale, sono abbastanza unici - che è esattamente ciò di cui abbiamo bisogno qui.
Salterio

1
Se riesci a trovare un PRNG che ti permetta di "mescolare" entropia, allora potrebbe essere persino migliore dell'opzione XOR-then-seed. Scorrere la memoria non inizializzata e mescolare i byte al PRNG. Ad esempio, vedi la mia libreria C più semplice: funzione mix .
Craig McQueen,

Questo non ti darà casualità di cripto qualità.

@CamilStaps ovviamente no.
Navin,

1
Questo non funzionerà. La memoria non inizializzata è un comportamento indefinito se ho un sistema operativo e non ho alcun controllo su quale parte della memoria verrà assegnata al mio programma e su cosa c'era prima. Su un microcontrollore senza sistema operativo, non è così. Soprattutto con AVR, perché lì tutta la RAM sarà zero se è trascorso abbastanza tempo perché i condensatori vengano svuotati dal consumo di corrente in brownout.
vsz,

7

Quello che ho fatto per un lettore MP3 con capacità casuale è semplicemente usare un seme sequenziale diverso ad ogni accensione. Ho iniziato da 1 e l'ho memorizzato nella EEPROM in modo che al successivo ciclo di alimentazione ho usato 2 ecc. Questo era su un ATMEGA168. Come notato da helloworld922, anche un semplice seme sequenziale genererà sequenze pseudo casuali completamente diverse.

Ho usato uno dei generatori di sequenza casuale congruenti lineari, questo dà una distribuzione uniforme.

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

Ovviamente se vuoi che più unità abbiano sequenze diverse anche se possono avere lo stesso numero di cicli di accensione, allora hai bisogno di qualcosa per iniziare in modo casuale.

Questo potrebbe essere fatto con uno qualsiasi dei metodi proposti dagli altri poster - Un metodo che mi viene in mente potrebbe usare il passaggio per lo zero CA che va nel processore se lo hai (per esempio per il controllo della fase della lampada)? Questo potrebbe essere usato per campionare il timer al primo incrocio dopo l'accensione e quindi usato come seme.

Ci sono pulsanti sull'unità per selezionare la modalità ecc.? In tal caso, è possibile campionare il contatore la prima volta che si preme il pulsante dopo la programmazione della MCU, è possibile generare inizialmente un seme casuale e memorizzarlo in EEPROM. Ogni accensione dopo questo punto userebbe il seme immagazzinato.


5

Un ADC è un'ottima fonte di casualità.

Non è necessario fare affidamento sulle tolleranze dei resistori. Qualsiasi resistenza genererà rumore termico e lo stesso effetto fisico introdurrà rumore nell'ADC quando eseguirà tutte le fasi di campionamento e conversione. (Il foglio dati ti dirà sulla quantità di rumore e quali impostazioni di configurazione sono le peggiori / migliori.)

Non si deve lasciare il pin ADC mobile; questo potrebbe far fluttuare troppo la tensione e rischiare di saturare l'ingresso.
(Molte MCU consentono di utilizzare qualcosa come la metà della tensione di alimentazione come ingresso ADC, per la calibrazione. Ciò consente di risparmiare la resistenza esterna e comunque di generare rumore. Ancora una volta, consultare la scheda tecnica per la configurazione peggiore / migliore.)

Non è necessario fare affidamento su una singola misurazione ADC; puoi combinare più misurazioni con una semplice funzione di hash o checksum (CRC sarebbe sufficiente). Se è necessario iniziare a utilizzare immediatamente l'RNG, è possibile in seguito combinare il risultato ADC con il seme RNG corrente.


2
Non sono sicuro che il rumore Johnson sia adatto in questa applicazione; A STP un resistore da 10Meg su una larghezza 40uVdi banda di 10kHz ha del rumore Johnson. Avresti bisogno di un ADC> 14 bit o di un circuito amplificatore per misurarlo ragionevolmente.
helloworld922,

STP non è molto rilevante. Soprattutto la temperatura potrebbe essere aumentata intenzionalmente, ma un extra di 60 gradi rispetto a STP è solo il 10% di rumore in più.
Salterio

1
Un approccio simile sarebbe quello di utilizzare il rumore di sparo in un diodo. en.wikipedia.org/wiki/Noise_generator#Shot_noise_generators
teambob

2

Puoi salvare il seme da una sessione all'altra? In tal caso, è possibile accendere ogni unità per un periodo di tempo casuale al momento della creazione? In questo modo tutte le unità verranno spedite con semi preimpostati che difficilmente saranno uguali.

Un altro pensiero: come si collegano più unità in modo che si accendano contemporaneamente? Se sono in serie, aggiungi un qualche tipo di condensatore in modo che il dispositivo (n + 1) inizi alcuni cicli di clock dopo l'ennesimo dispositivo. Idealmente, i condensatori si scaricherebbero molto rapidamente all'arresto del dispositivo, quindi ad ogni avvio / riavvio c'è uno spazio maggiore tra le sequenze.

Se sono in parallelo, potresti comunque randomizzare un po 'il tempo di avvio. Suppongo che ci sia una sorta di filtrazione di potenza usando condensatori. In tal caso, fabbricare i dispositivi con circuiti di filtraggio leggermente diversi provocherebbe l'avvio di ciascun dispositivo in un momento leggermente diverso, causando divergenze dopo diversi riavvii.

Una variazione su questo è quella di aggiungere una variazione ai segnali del tuo orologio, se possibile. Una differenza dello 0,1% nella velocità di clock potrebbe avere un impatto limitato sullo spettacolo di luci, mentre si modifica la velocità con cui si attraversa la tabella PRNG abbastanza rapidamente.


1
forse collegare un grande getto all'analogo in pin e prendere alcune letture di "ronzio di rete" per seminare l'RNG.
Jasen,

1
@Jasen, tutte le unità collegate allo stesso cavo di prolunga vedranno lo stesso ronzio di rete.
Ian Ringrose,

2

Se si esegue su una sorgente di clock "calibrata" interna. Non potresti salvare un seme dopo qualche tempo, preferibilmente nella EEPROM. L'orologio andrà alla deriva e differirà da unità a unità. Per salvare un nuovo valore dopo un po 'di tempo (forse ogni 10 minuti circa o dopo un tempo abbastanza breve da verificarsi entro il normale tempo di attività del dispositivo. Più a lungo è acceso, più è probabile che salverà un valore "diverso" nella EEPROM.

Fai anche un salto una volta ogni tanto (non troppo spesso) e ridimensiona mentre il dispositivo è acceso (salva questo nuovo valore in EEPROM).


2

Che ne dici di estendere la tua idea originale di conversione AD basata su un resistore variabile aggiungendo un LDR o un termistore? (Il primo dovrebbe essere in grado di "guardare" all'esterno, non so se sia possibile; ma la variazione di luce potrebbe essere superiore alla variazione di temperatura tra i dispositivi iniziata all'incirca nello stesso momento nello stesso posto. ..)


1
I termistori entrano con un'altra proprietà utile. Diverse serie della maggior parte dei produttori presentano un'enorme varianza e inesattezza. Ciò "migliorerà" ulteriormente il risultato.
Ariser,

1

2 potenziali soluzioni, entrambe supponendo che tu abbia bisogno di un seme unico per unità.

  1. Se esegui il flashing delle tue unità una alla volta in fabbrica, il file hex può essere modificato a livello di codice da alcuni script intermedi nel programmatore. Se è controllato da PC, è possibile sovrascrivere un'inizializzazione variabile con la data e l'ora. Garantito per essere unico per ogni unità!

  2. I dispositivi a 1 filo di Dallas utilizzano solo un pin e ognuno ha un numero seriale univoco a 64 bit. Puoi usarlo come seme.


1
Mi piacciono 2, ma sfortunatamente le parti DS sono tutte piuttosto costose.
Ariser,

Non usare il timestamp di produzione per casualità di qualità cripto, è prevedibile.

2
@CamilStaps Per l'applicazione dell'OP, la cripto-qualità non è richiesta
Hagen von Eitzen,

1
@HagenvonEitzen vero, ma altri potrebbero venire a questa domanda alla ricerca di casualità cripto-Q, quindi vale la pena menzionare.

4
@CamilStaps Sigh , sembra che tu abbia rinunciato all'umanità :) È davvero troppo impegnativo aspettarsi da qualcuno che vuole usare una risposta di electronicsSE per scopi crittografici che siano almeno abbastanza attenti da leggere la domanda a cui dovrebbe rispondere ? I semi "16bit" o "5 o5 6 bit" non sono cripto-Q anche se generati da un gruppo di gatti Schrödinger :)
Hagen von Eitzen,

1

È possibile lasciare un pin ADC mobile per alimentare il generatore di numeri casuali (RNG) con rumore acquisito. Dovrebbe essere sufficiente per generare un seme o addirittura usarlo come generatore di gas naturale.

Non dimenticare di utilizzare il tempo di conversione minimo possibile.

L'altra soluzione potrebbe essere un generatore di rumore applicato al pin ADC.


2
Farò alcune misurazioni ma se ricordo bene, un pin ADC mobile legge 0o si avvicina 0. Lo controllerò di nuovo per vedere se è così.
vsz,

1
Sono interessato, legge 0quando galleggia?
Bence Kaulics,

2
Il problema è che questo potrebbe funzionare su una scheda di sviluppo e non riuscire nel prodotto finale.
vsz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.