Using millis, random, or randomSeed

Hi guys, I need an arbitrarily odd or even number.

I am using this elsewhere in my program to count down time (from the Blink w/o delay example)

unsigned long currentMillis = millis();

If I just mask off the lowest bit

long number = currentMillis & 0x01;  // some othermask needed for type long??

and then decide based on number = 0 or 1, that will more or less give a random result, won't it?

I just broke my power connection wiring, will fix so I can try this tomorrow.

Thanks

Nope.

Is there some formatting behind it that results in it being odd or even all the time?

and then decide based on number = 0 or 1, that will more or less give a random result, won't it?

If the rest of the program is deterministic you will get the same {0,1} sequence every time. A better random source is a floating analog line (see below) The check even/odd should hover around 1.0000 to "prove" they have equal chance of occurring.

long odd = 0;
long even = 0;
void setup()
{
  Serial.begin(115200);
}

void loop()
{
 int n = analogRead(A0) % 2;     
// Serial.print(n);
 if (n == 1) odd++;
 else even++;
 // Serial.print(odd); Serial.print("\t"); Serial.print(even);
 Serial.println(1.0 * odd / even, 4);
}

On the first pass, if the value is odd, you just divided by 0.

That will definitely give a random result :) but you are right

I saw the playground thing on using analog lines, that doesn't work for my case as I already have all the analog lines being used as digital outputs controlling registers & acting as clock lines to the registers. I really need a s/w solution. That's why I was thinking with millis() running all the time, if I just read it when I get a wireless button push from the user then millis() will end in 1 or 0, no programmed sequence to deal with. If the LSB is 0 or 1 all the time, then I could mask for some other bit instead.

Crossroads,

millis() isn't such a good idea, it changes too slowly. If you want to use a time component use micros(). If you have hardware inputs which might vary, use all read port values plus micros as a random seed (perhaps combined with XOR). This might still give you a rather small starting range for your random generator, but it's still better than millis().

In the end it all depends on what you need the random values for - is it for something harmless or something serious (eg gambling, statistical methods like the Monte Carlo Integration, security). In the latter case, go for a proper hardware solution.

Korman

The trick with millis() has the following big drawback. If you want 5 random numbers within 1 ms (could happen?) than they will be the same. within 2 ms you know it will be the opposite. In terms of cryptology it is too predictable, but it may be random enough for your sketch.

Do you have any inputlines that have random timeing or so, or a temperature these could be used to set randomSeed() and you could just use random() after that.

Also possible is to check what an analogRead() returns, even with the hardware connected, might be random enough.

Another a SW only pseudo-random generator I once saw was an application that calculated PI in as many digits as possible. These are quite random even and odd as far as I know. You need to rewrite such PI decimal calculator to be a function that returns the next digit. Can be a quite a project in itself.

Robtillaart, I doubt that Crossroads really considered millis() directly and not as the input for RandomSeed. That would be a beginner's gaffe.

Korman

Hi guys, Thanks for the feedback. All I want to do is have a quick digital cointoss. 0 or 1, that's all I need. That's why I was thinking just use the LBS of millis(). The referee will push the cointoss button, I have the code look at what millis() was the last time it was read, and go from there. Very simple. Is only being used to decide who gets priority in a club fencing match, no $ involved or anything. (score is tied after 3 minutes of fencing; there is one more minute added. If no single touches are scored, the fencer with priority wins). I have seen referees without a coin spin a pencil on the floor to decide the same, so we're not talking high tech here.

I have all 19 IO lines tied up as digital lines - serial ports, SPI ports, virtual wire in, and the rest are digital IO to the rest of my control board. Really making the most of this Promini! And am thinking about changing the 4 pins I have set aside for a 0-15 address select (to compare to the same in an incoming wireless message) into a serial input to shift in 4 bits instead so I can have a couple of more lines to read in some switch that another box is creating now (so I can ditch that box).

But first, am gonna solder the power wire back on right now so & can power the box up again....

A better random source is a floating analog line

Nope. That doesn't work well either. They tend to pick up noise from nearby digital sources. The end result is a very non-random sequence of values.

If you want to use a time component use micros

That has problems as well.

I really need a s/w solution

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283911573/7#7

Sadly you don't have an ethernet connection : http://www.random.org/coins/ or ?

Can you add the referee to the "coin toss"? Does your device include a pushbutton?

Yes, the referee gets to decide when to randomly push the button. Typically a statement is made "score is tied at the end of regulation time, we'll now have 1 minute of fencing. (at which point the button is pushed, the lights will blink back & forth a little for effect, and stop on one.) "Priority is (left or right, depending on the light)".

Done correctly, you can use the button press as the source of entropy. The simplest and most reliable method is to use the processor’s hardware. Introducing any software means it has to be done carefully to ensure no bias is introduced.

Assuming you’re using a '168 or '328 processor… You obviously need to leave Timer 0 alone so millis works. Are you using Timer 1 or Timer 2? PWM? Servo? Tone?

Any chance you can move the button to pin 8 (PB0)? Or to one of the interrupt pins (pin 2 or pin 3)?

Okay, back from fencing classes, broken wire fixed so power is back, box is reassembled & working again. I have a 7 segment display set up to to display either a “c” or a backwards “c” (for values hex A or B into a 74LS47 driver). (Rest of my 1690 line program only uses 0-9.)

Ready to come up with a random 0 or 1 somehow. If 0 will write out A, if 1 will write out B.

To answer questions:
Yes, 328 (ProMini, 5V/16MHz)
Not intentionally using Timer 1, 2, PWM, Servo, Tone (unless Libraries VirtualWire, SPI, or Serial use them).
Can not move the button - code for this actually runs when selected via Switch:case after getting the remote button press ‘A’ via virtual wire. When it is given, a 3:00 bout has gone down to 0:00 and the score is tied.

I've got the following running, seems to do an okay job of picking sides randomly.

      case 'A':  /* Send coin flip to FF (or do own coin flip & set Priority)  */
        //Serial.println("A / Coin Flip");
        if ((time_running ==1) || (time_running == 2)) {
          break;
        }  // case is stopped if time is running
        else {
        // use LSB of previousMillis to determine who has priority.
        unsigned long currentMillis = millis();
        long mask = 1;
        long side = mask & currentMillis;
        if (side == 0) {period = 0x0A;}
        else {period = 0x0B;}
        
        update_period = 1;  // update the digit in the period display section
        
        }
        break;     // end switch (buf[0]), case A

In case you want an alternative...

Put this in setup...

  TCCR2B = 0;
  TCCR2A = 0;
  TCCR2B = _BV(CS20);

TCNT2 is the current Counter 2 value. When you want to flip a coin, do this after the referee clicks the button...

  if ( TCNT2 & 1 )
  {
    // heads
  }
  else
  {
    // tails
  }

I hope whatever you decide to use works well!

The referee will push the cointoss button

Why not randomseed with micros() the verry first time the button is pressed?

-Fletcher