pseudo random number between X and Y?

Nov 17, 2009 19 Replies

Hello all


I need a function, when called returns a pseudo random number between X and Y.


I have many boards that periodically broadcasts their board addresses on an RF link. All boards use the same RF-channel frequency, so data collisions is going to happen. So I need to randomly delay between those broadcasts to be able to avoid collisions with other boards broadcasts.


I want to make a pseudo random delay (X ms - Y ms) before sending the package again.


Why not just use some microsecond counter and use some of the lower order bits as delay, if receivers detect a collision situation.

Even with mains powered systems, a typical microprocessor crystal will soon drift so much that collisions do not occur frequently after a mains failure.

Paul

I would like to add that the microprocessor system crystal drift is so bad that in one system with identical processor cards distributed over a large area, the drift was so bad after a reset signal on the common serial line (break) the system became useless after a few seconds due to the crystal drift at various boards.

We had to use the 50 Hz mains (with very bad short time accuracy) as our common timing reference.

Paul

The boards use different addresses I assume. Should a delay calculated from (part of) the board's address not suffice?

Wil

The boards use a 32-bit address that is unique. So I should be able to use it. If I for example take 8-bits from theboard address to specify a delay. And the next time I take the next 8 bits.

For example

delay = bit(7 to 0) of address delay = bit(8 to 1) of address delay = bit(9 to 2) of address ... delay = bit(31 to 24) of address

and then start again at:

delay = bit(7 to 0) of address

But some combinations of addresses works better than others. And it gets bad if i enumerate all boards starting at address 1 and the 2, 3, 4, 5 etc.

You could have a look at the Aloha radio network or ethernet spec, to see how it's been done before...

Regards,

Chris

That assumes that all the address bits are distributed fairly evenly, which may be unlikely. A better way might be to use a hash of the address and use this to create a backoff table in memory.

Dunno, I would still have a look at Aloha first, which solved exactly that problem and was the forerunner of ethernet...

Regards,

Chris (Who should be getting on with some work today :-)

If you have unique seed values you could use a Linear Feedback Shift Register to shake them up and get series of different pseudo-random values. With the right constant you can get good fairly patternless results.

The Wikipedia article at

formatting link
has some sample code.

Mel.

Oh, dear.

Abandon this task. It is not for the sorrow programmers like you.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Did you do a web search for "random number generator"?

For your purposes a linear shift register ought to work, particularly if you seed it with your board address. There's a nifty way to go through a linear shift register N bits at a time; it requires a table of register states 2^N words long and as wide as your register but the code is short

-- depending on your program storage space you could use that and get a really big change from one number to the next. Otherwise just iterating the thing once and taking the bottom bits would probably be random enough.

www.wescottdesign.com

use the devices address as a delay.... collisions will be random, and so will the address.

If you have a cheap (enough) 32 bit multiply, this method works pretty well:

x(n)=a*x(n-1)+carry

Finding a value for 'a' that results in a large period is left as an exercise.

You'll probably also want exponential backoff after detecting a collision. Everytime a board detects a collision (by lack of acknowledgement) it should double the upper bound of its random generator.

An easy way to do this is to use an increasing number of bits from your x(n) value above.

nd

For the interval [X, Y), assuming _unsigned_ integers and 'C' syntax:

random =3D X + (rnd() % (Y - X));

Where "rnd()" is your source of pseudo-random unsigned integer. Choosing that is however dependent on your resources and expectations.

An elegant formula, isn't it? Unfortunately it has a serious problem: the result doesn't have the qualities usually requested from it. It's not uniformly distributed unless (Y-X) just so happens to exactly divide the range of the random number generator. Otherwise you get (RND_MAX+1)%(Y-X) outcomes that are more probable than the others.

Even with all the spam I have to parse through on the Google groups page, I have never considered going back to a newsreader. But this might just be a good reason, to be able to killfile someone... I wonder who...

But then I am just feeding the troll, so maybe I should killfile myself...

Rick

I've wondered why he bothers. It doesn't often appear to be for teaching anyone.

He has a point if you take his assumptions. It's kind of a sad comment on the general state of embedded programming affairs, if you assume the OP is someone who is charged with the engineering of a system of RF boards and is then asking about how to generate a random delay. The assumption may be false, though. It's possible this is someone who knows their application space well but isn't an engineer

-- more of an integrator?? -- and who could use a gentle clue. It's also possible that the OP is asking for practical experience and just stating it poorly. Still, it does beg a few questions.

Since I've now bothered writing at all, the OP may google up "linear congruential generator" (LCG) and keep in mind also the basic idea of a linear expression that yields something within a specified range, X+(Y-X)*(R-Rmin)/(Rmax-Rmin+1), where the X and Y are his own values from his post and the Rmax and Rmin are the minimum and maximum values that the LCG produces. Rmin is often 0, but not always. The expression assumes real numbers. If integers are exclusively used, finding an LCG with a nice (Rmax-Rmin+1)=2^N, with N a positive integer, might help somewhat. Scaling to produce a desired precision in milliseconds may also be warranted. Also, I very much support another poster's comment about reading Donald Knuth's volume on Seminumerical Algorithms from the early 1970's (I completely read his three books, cover to cover including the long discussions on tape sorting, when they came out and they added a lot to my earlier education.)

Jon

I don't care what the issue is, VV's approach is rude and accomplishes nothing. I wish he would just go away unless he is willing to actually help someone. There are any number of things I am ignorant about in the field of EE which I have been earning a living in for 30 years. Does that make me stupid? That is why we are here for the most part I think, to learn things we don't know.

I know that school taught me a lot of basics, but I have learned all the practical stuff while working. Does that mean my schooling was lacking?

There are any number of reasons why someone posts angry replies. Regardless, they reflect badly on the poster and annoy the rest of us.

Rick

X and

I am glad there is enough sarcasm in Usenet to keep boredom away.

It fits the OP's request which I had explicitly commented on.

Of course it doesn't guarantee uniform distribution for any choice of parameters, I didn't even wanted it to. :-) It's the most basic stuff you can do with - this and some PRNG of your choice. And you get what you paid for.

There is enough literature on PRNGs, in case OP wants to know more.

Gotcha, Rick, and understood. Largely agreed.

  • While I'm at it, to the OP: You can combine the LCG's equation with the linear one used to provide a chosen range into a single linear expression with the same operation count as only one would require. Some care may be needed, though, to retain bits appropriately.

Jon

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required