Un pequeño microcontrolador (Atmel de 8 bits) controla una serie de luces para presentar un espectáculo de luces con muchas secuencias de luces aleatorias elegantes.
Un pseudo-RNG adecuado hace bien su trabajo, pero estoy buscando una buena semilla para él. Será necesaria una semilla porque si alguien enciende múltiples dispositivos de este tipo al mismo tiempo, no se verá bien si todos generaron las mismas secuencias de efectos hasta que se separen lentamente debido a las pequeñas diferencias en sus fuentes de reloj individuales.
Un método muy bueno para sembrar un pseudo-RNG, que solía usar, es posible en el caso de un dispositivo que debe iniciarse presionando un botón o presionando un interruptor. Tan pronto como se enciende el µc, se puede iniciar un temporizador muy rápido, y el valor de este temporizador genera el RNG tan pronto como se presiona el botón por primera vez.
El problema es que, en este escenario, no hay botones. El programa debe iniciarse tan pronto como se encienda el dispositivo.
El lugar en la PCB es extremadamente limitado (nada más que algunas de las piezas SMD más pequeñas pueden caber), por lo que estoy buscando la solución más pequeña y simple posible. Por lo tanto, descartaré soluciones sofisticadas como hardware RNG verdadero, receptores de radio, etc.
Todo lo que tengo es un contador de temporizador de 16 bits en la CPU y un portpin no utilizado que tiene acceso a un ADC.
Mi solución actual es usar una resistencia (lo más inexacta posible) para proporcionar aproximadamente la mitad del voltaje de alimentación al pin ADC, y sembrar el RNG con el primer valor de conversión AD. Sin embargo, hoy en día la mayoría de las resistencias del 10% tienen una imprecisión muy por debajo del 1% (sería divertido imaginar la cara de un proveedor cuando les digo que queremos las resistencias SMD de peor calidad que puedan encontrar), por lo que hay una gran probabilidad de unidades múltiples que comienzan con la misma semilla.
Una mejor alternativa sería hacer conversiones múltiples y construir un valor a partir de los bits menos significativos de estas mediciones. Sin embargo, usé el ADC de este tipo µc antes y sé que es muy preciso. Ejecutar el ADC a la velocidad más rápida posible podría ayudar aquí.
¿Alguien tiene una mejor sugerencia? No es necesario que la semilla esté distribuida de manera perfectamente uniforme, pero cuanto más uniforme sea la distribución, mejor. Una semilla de 16 bits con una distribución perfectamente uniforme sería un sueño demasiado bueno para ser verdad, pero creo que una distribución media decente de más de 5 o 6 bits podría ser suficiente.
fuente
Respuestas:
Coloque una resistencia paralela y un capacitor entre el pin A / D y tierra. Haga que la resistencia sea bastante alta, preferiblemente muy por encima del requisito de impedancia de la señal de entrada para A / D. Haga que el tiempo RC sea constante, tal vez alrededor de 10 µs. Por ejemplo, 100 kΩ y 100 pF suena como una buena combinación.
Para obtener un valor con cierta aleatoriedad, suba el pin por un tiempo, luego ajústelo a alta impedancia y tome una lectura A / D unos µs más tarde. Particularmente si abusa adecuadamente del tiempo de adquisición de A / D, el voltaje que verá dependerá de los valores R y C, la corriente de fuga del pin, otro ruido cercano y la temperatura.
Tome el bit bajo o los dos bits bajos y repita según sea necesario para obtener cualquier cantidad de bits aleatorios.
Para un patrón más aleatorio, realice este procedimiento ocasionalmente e inyecte el bit bajo del resultado A / D en el generador de números aleatorios que ya está utilizando.
fuente
Algunas opciones posibles:
Preprograme una dirección de serie única para cada dispositivo. Si tiene un algoritmo RNG lo suficientemente bueno, incluso una lista secuencial de direcciones en serie producirá resultados muy diferentes.
Dependiendo de su MCU / configuración, puede tener dos fuentes de reloj diferentes disponibles para el reloj del sistema y la entrada del temporizador de vigilancia / contador de temporizador. Si uno / ambos tienen una variación significativa, puede usar esto para generar una semilla adecuadamente diferente. Aquí hay un ejemplo que escribí que usa un temporizador de vigilancia interno de Arduino y un reloj del sistema XTAL externo .
Use un transistor BJT y construya un amplificador altamente dependiente de beta. Esto se puede leer de un ADC para la semilla.
Los condensadores / inductores generalmente se especifican con una tolerancia mucho peor que las resistencias. Puede construir algún tipo de circuito de filtro (RC, RL, LC) con estos y medir la salida con el ADC.
fuente
Memoria no inicializada
Puede intentar usar la memoria no inicializada en el microcontrolador. El truco es encontrar los bits que tienen los flip-flops más 'balanceados', y que en realidad son aleatorios. El procedimiento consiste en leer toda la memoria, restablecer y repetir varias veces para medir qué bits son verdaderamente aleatorios. ¡Luego usa este mapa para leer suficientes bits aleatorios para sembrar tu PRNG o LFSR!
Este método le debe dar semillas aleatorias, incluso con hardware idéntico, más detalles (y enlaces) están disponibles en este Hack-a-día artículo
Me gusta este método porque no requiere ningún circuito adicional o pines; su AVR ya tiene ram, solo necesita encontrar los bits inestables (aleatorios). También el procedimiento de mapeo podría ser automatizado; ¡puede aplicar el mismo código y procedimiento a cada dispositivo y obtener resultados verdaderamente aleatorios!
fuente
Lo que hice para un reproductor de MP3 con capacidad aleatoria es usar una semilla secuencial diferente en cada encendido. Comencé en 1 y almacené esto en la EEPROM para que en el siguiente ciclo de energía utilizara 2, etc. Esto estaba en un ATMEGA168. Como señaló helloworld922, incluso una semilla secuencial simple generará secuencias pseudoaleatorias completamente diferentes.
Usé uno de los generadores de secuencia aleatoria congruentes lineales, esto da una distribución uniforme.
Por supuesto, si desea que varias unidades tengan secuencias diferentes a pesar de que hayan tenido el mismo número de ciclos de potencia, entonces necesita algo para comenzar al azar.
Esto podría hacerse por cualquiera de los métodos propuestos por los otros carteles: un método que se me ocurra podría utilizar el cruce de cero de CA que entra en el procesador si lo tiene (para el control de fase de la lámpara, por ejemplo). Esto podría usarse para muestrear el temporizador en el primer cruce después del encendido y luego usarlo como semilla.
¿Hay botones en la unidad para seleccionar el modo, etc.? Si es así, puede probar el contador la primera vez que se presiona el botón después de que se programa la MCU, puede generar una semilla aleatoria inicialmente y almacenarla en EEPROM. Cada Power-up después de este punto usaría la semilla almacenada.
fuente
Un ADC es una muy buena fuente de aleatoriedad.
No necesita confiar en las tolerancias de resistencia. Cualquier resistencia generará ruido térmico , y el mismo efecto físico introducirá ruido en el ADC al realizar todos los pasos de muestreo y conversión. (La hoja de datos le informará sobre la cantidad de ruido y qué ajustes de configuración son peores / mejores).
No debe dejar el pin ADC flotando; Esto puede dejar que el voltaje flote demasiado y se corre el riesgo de saturar la entrada.
(Muchas MCU le permiten usar algo como la mitad del voltaje de alimentación como entrada de ADC, para la calibración. Esto ahorra la resistencia externa y aún le produce ruido. Nuevamente, consulte la hoja de datos para ver la peor / mejor configuración).
No necesita confiar en una sola medición de ADC; Puede combinar varias mediciones con una simple función hash o de suma de verificación (CRC sería suficiente). Si necesita comenzar a usar el RNG de inmediato, más tarde puede combinar el resultado de ADC con la semilla de RNG actual.
fuente
40uV
de banda de 10 kHz tiene ruido Johnson. Necesitaría un ADC> 14 bit o un circuito amplificador para medir esto razonablemente.¿Se puede guardar la semilla de una sesión a otra? Si es así, ¿es factible encender cada unidad durante un período de tiempo aleatorio después de la creación? De esa forma, todas las unidades se enviarán con semillas preestablecidas que probablemente no sean las mismas.
Otro pensamiento: ¿Cómo se unen varias unidades para que se enciendan simultáneamente? Si están en serie, agregue algún tipo de condensador para que el (n + 1) dispositivo inicie algunos ciclos de reloj después del dispositivo n. Idealmente, los condensadores se descargarían muy rápidamente en el apagado del dispositivo, por lo que cada inicio / reinicio hay una brecha más grande entre las secuencias.
Si están en paralelo, aún puede aleatorizar un poco el tiempo de inicio. Supongo que hay algún tipo de filtración de energía usando condensadores. Si es así, la fabricación de dispositivos con circuitos de filtración ligeramente diferentes provocaría que cada dispositivo se inicie en un momento ligeramente diferente, lo que provocaría divergencias después de varios reinicios.
Una variación de esto es agregar variación a sus señales de reloj si es posible. Una diferencia del 0.1% en la velocidad del reloj podría tener poco impacto en el espectáculo de luces, mientras cambia la velocidad con la que recorre la tabla PRNG con bastante rapidez.
fuente
Si se ejecuta en una fuente de reloj interna "calibrada". ¿No podría guardar una semilla después de un tiempo, preferiblemente en la EEPROM? El reloj se desplazará y diferirá de una unidad a otra. Para guardar un nuevo valor después de algún tiempo nuevamente (tal vez cada 10 minutos más o menos, o después de un tiempo que sea lo suficientemente corto como para que ocurra dentro del tiempo de funcionamiento normal del dispositivo. Cuanto más tiempo esté encendido el dispositivo, es más probable que ahorre un valor "diferente" en la EEPROM.
También dé un salto de vez en cuando (no con demasiada frecuencia) y reinicialice mientras el dispositivo está encendido (guarde este nuevo valor en EEPROM).
fuente
¿Qué pasa con extender su idea original de conversión AD basada en una resistencia variable agregando un LDR o termistor? (El primero debería ser capaz de "mirar" afuera, no sé si eso es factible; pero la variación en la luz puede ser mayor que la variación en la temperatura entre los dispositivos iniciados aproximadamente al mismo tiempo en el mismo lugar. ..)
fuente
2 soluciones potenciales, ambas suponiendo que necesita una semilla única por unidad.
Si actualiza sus unidades una por una en la fábrica, el archivo hexadecimal puede modificarse mediante programación mediante algún script intermedio en el programador. Si está controlado por PC, puede sobrescribir una inicialización variable con la fecha y la hora. ¡Garantizado para ser único para cada unidad!
Los dispositivos de cable Dallas 1 usan solo un pin y cada uno viene con un número de serie único de 64 bits. Puedes usar esto como la semilla.
fuente
Puede dejar un pin ADC flotante para alimentar el generador de números aleatorios (RNG) con el ruido capturado. Debería ser suficiente para generar una semilla o incluso usarla como generador de RNG.No olvides usar el mínimo tiempo de conversión posible.
La otra solución podría ser un generador de ruido aplicado en el pin ADC.
fuente
0
o cerca0
. Lo revisaré nuevamente para ver si ese es el caso.0
cuando flota?