# Getting a random number for electronic dice

I am making a "Electronic Dice".

I have 7 LEDs to form the output, and this works fine.

My problem is getting a random result on the output.

``````int die_face = 1;

void loop()
{
{
paintDieFace((die_face % 6) + 1);
}

die_face += 1;
}
``````

The problem is, that roughly 95% of the time I get a 1.
Most of the time it's not a 1, it's a 2, or very rarely a 3.

I've tried paintDieFace() with millis()%6+1 too, but always get the same result. When it's painted with random(1,7); I get 1, 2 or 3 100% of the time.

Is this some sort of timing issue? I just don't get it.

Just to clarify - The paintDieFace() function is working perfectly, I'm logging the result to serial too.

• This code is for a high-school student workshop, so it really needs to be kept simple. Aug 19, 2014 at 22:02
• I tested your code and I don't have this problem. Aug 19, 2014 at 22:37

First of all, look at this line of code:

``````if (analogRead(BUTTON_PIN) == HIGH)
``````

You probably want to use `digitalRead()`. Note that it is okay to use digitalRead() on an analog pin, just make sure to use the right pin number (`A0`, etc.)

From the Arduino Source:

``````#define HIGH 0x1
#define LOW  0x0
``````

(Ignore the `0x`, that is just specifying that it's hexadecimal. However, 0 and 1 are the same in any base)

So, really, this function is only activated when `analogRead()` returns 1, which could possibly cause a problem later if it doesn't check at the right time. Note: now is a good time to remind you about debouncing...

For your actual code, since you want it to be simple, I suggest you forget that code that you wrote. Arduino has a built in random library, which works unless you have some special need for a random number.

Your final code should look like something like this in the end:

``````void loop() {
paintDieFace(random(1, 6);
}
}
``````

Note that you should also use this code here in your setup (make sure that analog pin is floating: nothing should be attached to it):

``````randomSeed(analogRead(A1));
``````

It actually isn't random, just pseudo-random. That means it relies on an equation to generate what seem to be random numbers. Because there has to be a default value of where the equation starts (the seed), it will repeat the same numbers every time you run it.

If you're wondering how this works, know that the analog pin is affected by a ton of external factors when there is no other electric signal attached.

• De...BOUNCING, not denouncing. 8) Aug 20, 2014 at 1:21
• for a HS project it doesn't matter, but in terms of security, `randomSeed(analogRead(A1));` is terrible. `random()` is deterministic, and it's not hard to try all 1024 sequences. If you do that, run `random()` in the loop so that it's unpredictable how many times it's been called, and thus unpredictable in terms of the next result. `randomSeed((analogRead(A1)+1)*millis()*micros()*(analogRead(A1)+1))` is better Apr 7, 2017 at 19:39
• @dandavis two issues with that: a) its stronger for sure, but still incredibly weak. You shouldn't be using a pseudorandom generator if it needs to be secure end of discussion. B) since seeding is traditionally at the start of the program, millis and micros are going to be very similar each time, if not the exact same. Of course, seeding when the button was first pressed may overcome this partially, but there are ways to overcome this (hold down the button before plugging it in so the first iteration of the loop reads HIGH, advanced cameras and timers, etc.) Apr 7, 2017 at 21:12
• @AnonymousPenguin: good point about the timing. i'm used to 8266s, where you can put that after the wifi connect part, which takes 1-3 seconds... a prior `delay(analogRead(A0)%250)` adds cheap entropy from micros(). an empty wire connected only to A0 collects noise and widens the sample range considerably, might be worth noting in the answer. "security" was probably the wrong word; i'm just suggesting low-effort/cost ways to make a game (much) harder to cheat using an app... Apr 7, 2017 at 22:07
• @dandavis very true, although I'm sure the teacher would be pleased if the student did the work to reverse engineer the random functions and build a separate program that calculated sequences with the random seed and matched a sequence to the appropriate seed. :) Apr 7, 2017 at 22:12

I've had better success with this version.

I did not work out the problem with the first version. Although I did find the rear legs of the push-button were lighting up a LED - but only when pushed. As the result is only displayed when the button is not pushed, I don't see how it could make a difference.

I believe the modulus of 6 is a problem, perhaps this does really output more ones than anything else. Obviously looping the dice_number variable 1->6 removes the necessity for it.

``````#define LEDS_34_PIN 2  // Output pins used
#define LEDS_16_PIN 3
#define LEDS_25_PIN 4
#define LED_7_PIN   5

#define BUTTON_PIN  6  // Input

unsigned char dice_number  = 0;     // this is what will be shown on the die face

void setup()
{
// Tell the Arduino we're writing to some pins
pinMode(LEDS_34_PIN, OUTPUT);
pinMode(LEDS_16_PIN, OUTPUT);
pinMode(LEDS_25_PIN, OUTPUT);
pinMode(LED_7_PIN,   OUTPUT);

// ... and reading a button
pinMode(BUTTON_PIN, INPUT);

// Do a testing-dance first
for (int i=1; i<=6; i++)
{
paintDieFace(i);
delay(500);
}
paintDieFace(0);

}

// Show a dice-dot-style number
// based on LEDs laid out like
//    [1]     [4]
//    [2] [7] [5]
//    [3]     [6]
void paintDieFace(unsigned char number)
{
// Turn off all LEDs
digitalWrite(LEDS_34_PIN, LOW);
digitalWrite(LEDS_16_PIN, LOW);
digitalWrite(LEDS_25_PIN, LOW);
digitalWrite(LED_7_PIN,   LOW);

if (number == 1 || number == 3 || number == 5 || number > 6)
{
digitalWrite(LED_7_PIN, HIGH);
}
if (number >= 2)
{
// LEDs 3 & 4 are on for all numbers greater-than 1
digitalWrite(LEDS_34_PIN, HIGH);
}
if (number >= 4)
{
// LEDs 1 & 6 are on for 4, 5 and 6
digitalWrite(LEDS_16_PIN, HIGH);
}
if (number >= 6)
{
// LEDs 2 & 5 are only on for 6 (or more)
digitalWrite(LEDS_25_PIN, HIGH);
}
}

void loop()
{
if (button_pushed == HIGH)
{
// The user has pushed the button, change the die reading
paintDieFace(dice_number);
delay(20);  // flicker the LEDs if button held in
}

dice_number += 1;
if (dice_number == 7)
dice_number = 1;
}
``````
• Just as a sidenote. Remember that you need a pull-down resistor on the button pin, to get reliable data from `digitalRead(BUTTON_PIN)`. Aug 20, 2014 at 16:27
• @Gerben: it's cheaper/easier to just set the pin mode to `INPUT_PULLUP` and hook button to GND... Apr 7, 2017 at 19:41