Generando números aleatorios en Arduino

Radom

Arduino incluye un generador de números pseudoaletorios. Su uso es muy sencillo primero, normalmente en el setup, se fija la semilla del generador usando la función randomSeed y un valor que se le pasa como parámetro.

La semilla se usa para generar una secuencia de números pseudoaleatorios. A diferencia de los números aleatorios que son distintos cada vez los pseudoaletaorios son siemrpe los mismos. Cada semilla genera una secuencia única de números aleatorios que es siempre la misma. Por lo que si queremos que cada que reiniciemos la placa la secuencia de números sea diferente tenemos que establecer la semilla con una fuente de ruido, un valor que sea aleatorio. Habitualmente se usan dos. El número de microsegundos desde que el software se inicio, que es útil sobre todo si la inicialización del software es larga (si la inicialización es muy simple es posible que el valor sea siempre el mismo) o el valor de de un puerto analógico donde no haya nada conectado.

Hay dos variables para generar números pseudoaleatorios:

random(max)
random(min, max)

La primera calcula un valor entre 0 y max la segunda entre min y max.

Un ejemplo de uso:

long randNumber;

void setup() {
  randomSeed(analogRead(0));
}

void loop() {
  //devuelve un número entre 0 y 300  
  randNumber = random(300);
  Serial.println(randNumber);

  //devuelve un número entre 10 y 200
  randNumber = random(10, 20);
  Serial.println(randNumber);

  delay(2000);
}

analogRead

Generalmente cuando buscas una manera de generar números aleatorios de verdad con Arduino te aconsejan recurrir a leer el valor puerto analógico que no este conectado a nada El problema es que realmente los valores obtenidos no son aleatorios. Suelen oscilar en torno a un valor sin alejarse demasiado de él. Es decir si el valor es el 150 es más probable que el siguiente número sea el 151 o el 149 que el 3 (en mis pruebas nunca he visto un  salto tan grande de valor). Cómo generador de números aleatorios no solo no es ninguna maravilla, es que es peor que el generador de números pseudoaleatorios.

Cómo solución se suele proponer usar el valor leído como semilla para la función random, lo malo de esto es que acaban siendo otra vez números pseudoaleatorios.

Hay montajes electrónicos que producen valores aleatorios a partir del ruido que sufren los componentes electrónicos, pero suelen ser complicados. Además ya no sería con un arduino y tengo que justificar que el articulo este en la sección de “arduino”.

Volviendo a nuestra idea de leer valores del puerto analógico vemos que el problema es que los números que devuelven oscilan entorno a un valor así que no podemos usar ese número como aleatorio, pero si una parte pequeña de él. El bit de menor peso. Vamos a tomar solo este bit y con ocho de ellos componer un byte. Ese byte debería ser aleatorio.

byte randomAnalog(int analogInput){
  byte rnd = 0;
  for(int i = 0; i < 8; i++){
    int aux = analogRead(analogInput)%2 << i; rnd += aux;
    delay(10);
  }
  return rnd;
}

Para aumentar el ruido se puede conectar un cable suelto en el  puerto que se va a leer, contra más largo y retorcido esté mejor, Por raro que suene si se mueve el cable o el arduino los números leídos del puerto analógico aun varían más.

Combinar varias fuentes

Si te fías poco puedes usar dos fuentes de aleatoriedad obteniendo bytes de dos puertos analógicos distintos y luego combinándolos con un xor.

byte r0 = randomAnalog(A0);
byte r1 = randomAnalog(A1);

byte r = r1 ^ r0;

Puede encontrar el código en el repositorio de github de ArduTips.

Un posible mejora es asegurarse de que el generar de números aleatorio es justo, es decir produce 0 o 1 con un 50% de probabilidades. Se puede leer aquí.

Un comentario en “Generando números aleatorios en Arduino

  1. Pingback: Generador justo de números aleatorios en arduino | Construyendo a Chispas

Los comentarios están cerrados.