Random() gives the same number in a library, no analog pins available for seed

Hello,
I’m writing a library that manages some stuff for RGB-leds.
Now having a function to generate random colors, I’d like to have a random number to be generated inside this library.
However, when I make the random integer, it’s always the same value.
When making random numbers in a loop, the numbers are random, but after closing the method, and recalling it, the numbers will be the same sequence again. So this means that the first number generated is 63, the second one 250, etc.
Isn’t there any other way to generate a really random number, other than using floating analogs to generate the noise? I’m already using all the pins on my arduino nano…

Yes, that's what pseudo random number generators do. If you want more randomness, you need to seed the random number generator with some randomness. Post your code. https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library

Isn't there any other way to generate a really random number, other than using floating analogs to generate the noise?

Floating analogs are a bad choice for seeding a pseudo random number generator... http://forum.arduino.cc/index.php?topic=66206.msg630884#msg630884 http://forum.arduino.cc/index.php?topic=66206.msg631681#msg631681

The [u]reliable[/u] but not very sexy way to seed random... http://forum.arduino.cc/index.php?topic=66206.0 http://forum.arduino.cc/index.php?topic=66206.msg537783#msg537783

If you using this “The reliable but not very sexy way to seed random”
Please add in this line

#include <avr/eeprom.h>

AWOL: Yes, that's what pseudo random number generators do. If you want more randomness, you need to seed the random number generator with some randomness. Post your code. https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library

And if all you want is a random seed, you don't need to use all of the resources that the library does. I have posted an example on the same site of using the technique I have used in that library to just generate a random seed.

https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library/arduino-random-seed

BTW, using a floating point pin to produce a random seed has been demonstrated repeatedly to NOT produce much of a difference from not doing anything at all...

BillHo:
Please add in this line

#include <avr/eeprom.h>

Huh. That’s odd. I know that compiled when I posted it.

Thanks for mentioning it. Post corrected.

BTW, using a floating point pin to produce a random seed has been demonstrated repeatedly to NOT produce much of a difference from not doing anything at all..

In this method, I’d like to generate two random long/ints, and make floats of them

void RGB::setFromRandomColor(double intensity){
	double h = random(360000.0) / 1000.0;
	double s = random(700, 1000) / 1000.0;
	double v = intensity;
	setFromHSV(h, s, v);
}

If I’m supposed to give the whole code:

#include "RGB.h"


RGB::RGB(int rPin, int gPin, int bPin){
	_rPin = rPin;
	_gPin = gPin;
	_bPin = bPin;

}

//getters
int RGB::getR(){
	return _r;
}
int RGB::getG(){
	return _g;
}
int RGB::getB(){
	return _b;
}


double RGB::getHue(){
	return _H;
}
double RGB::getSaturation(){
	return _S;
}
double RGB::getValue(){
	return _V;
}

void RGB::setFromHSV(double hue, double saturation, double value){
	double RGB[3]; // to store the 3 values of R, G & B

	//H = hue, S = saturation (saturation), V = Value(blackness) http://en.wikipedia.org/wiki/HSL_and_HSV

	_H = hue;
	_S = saturation;
	_V = value;
	double f, p, q, t;
	if (_H > 359) _H = 0.0;
	_H = constrain(_H, 0.0, 360.0);
	//Serial.println("test");
	int Hi = floor((_H / 60));
	f = _H / 60.0 - (Hi);
	p = (_V * (1.0 - _S));
	q = (_V * (1.0 - f * _S));
	t = ((_V * (1.0 - (1 - f) * _S)));

	switch (Hi) {
#pragma region cases
	case 0:
		RGB[0] = _V;
		RGB[1] = t;
		RGB[2] = p;

		break;
	case 1:
		RGB[0] = q;
		RGB[1] = _V;
		RGB[2] = p;

		break;
	case 2:
		RGB[0] = p;
		RGB[1] = _V;
		RGB[2] = t;

		break;
	case 3:
		RGB[0] = p;
		RGB[1] = q;
		RGB[2] = _V;

		break;
	case 4:
		RGB[0] = t;
		RGB[1] = p;
		RGB[2] = _V;

		break;
	case 5:
		RGB[0] = _V;
		RGB[1] = p;
		RGB[2] = q;

		break;
	default:
		RGB[0] = 0;
		RGB[1] = 0;
		RGB[2] = 0;
#pragma endregion
	}
	RGB[0] = round((RGB[0] * 255.0));
	RGB[1] = round((RGB[1] * 255.0));
	RGB[2] = round((RGB[2] * 255.0));

	_r = RGB[0];
	_g = RGB[1];
	_b = RGB[2];
	writeLeds();
}

void RGB::setFromRGB(int r, int g, int b){
	_r = r;
	_g = g;
	_b = b;
	double R = _r / 255.0;
	double G = _g / 255.0;
	double B = _b / 255.0;

	double max = max(R, max(G, B));
	double min = min(R, min(G, B));
	if (max == R) _H = (0 + (G - B) / (max - min))*60.0;
	if (max == G) _H = (2 + (B - R) / (max - min))*60.0;
	if (max == B) _H = (4 + (R - G) / (max - min))*60.0;
	_S = (max - min) / max;
	_V = max;
	writeLeds();
}

void RGB::setCurrentColor(){
	setFromHSV(_H, _S, _V);
}

void RGB::setFromRandomColor(double intensity){
	double h = random(360000.0) / 1000.0;
	double s = random(700, 1000) / 1000.0;
	double v = intensity;
	setFromHSV(h, s, v);
}

void RGB::fade(int timeSeconds){
	for (double d = _V; d > 0; d -= 0.001){
		setFromHSV(_H, _S, d);
		delay(timeSeconds);
	}
}

void RGB::smoothOn(int timeSeconds, double intensity){

	for (double d = 0; d < intensity; d += 0.001){
		setFromHSV(_H, _S, d);
		delay(timeSeconds);
	}
}
void RGB::smoothOnRandom(int timeSeconds, double intensity){
	double d;
	for (int i = 0; i < 9; i++){
		_H = random(360000) / 1000.0;
		_S = random(700, 1000) / 1000.0;
		d = 0.001;
	}
	delay(1000);
	while (d < intensity){
		setFromHSV(_H, _S, d);
		delay(timeSeconds);
		d += 0.001;
	}
}
void RGB::smoothOnHSV(int timeSeconds, double h, double s, double v){
	for (double d = 0; d < v; d += 0.001){
		setFromHSV(h, s, d);
		delay(timeSeconds);
	}
}



bool RGB::fade(int timeSeconds, int abortPin, bool requestForInternalPullup){
	if (requestForInternalPullup) pinMode(abortPin, INPUT_PULLUP);
	else pinMode(abortPin, INPUT);
	double d = _V;
	double V = _V;
	bool abort = false;
	do{
		setFromHSV(_H, _S, d);
		delay(timeSeconds);
		d = d - 0.001;
		if (digitalRead(abortPin) == 0) abort = true; //trigger -> abort = true -> return false : faden mislukt!
		

	} while ((d > 0) && (abort == false));
	if (abort){
		while (d < V){
			setFromHSV(_H, _S, d);
			delayMicroseconds(timeSeconds * 100); //10x sneller dan het uitgaan
			d = d + 0.001;
		}
		return false;
	}
	Serial.println("faden done");
	delay(1000);
	return true; //faden gelukt

}


void RGB::writeLeds(){
	analogWrite(_rPin, _r);
	analogWrite(_gPin, _g);
	analogWrite(_bPin, _b);
}

void RGB::off(){
	analogWrite(_rPin, 0);
	analogWrite(_gPin, 0);
	analogWrite(_bPin, 0);
}

The random numbers could have to be generated 200 times a second… couldn’t it be that using the EEPROM, it wouldn’t last very long until the eeprom has reached it 100.000 cycles?

It seems like the entropy library isn’t using that, I think I’d go with the entropy random seed?

Ward123: The random numbers could have to be generated 200 times a second... couldn't it be that using the EEPROM, it wouldn't last very long until the eeprom has reached it 100.000 cycles?

You only initialize the random number generator in...

void setup( void ) { reseedRandomInit( &reseedRandomSeed, 42 ); reseedRandom( &reseedRandomSeed );

reseedRandomInit( (unsigned short) 0, 42 ); reseedRandom( (unsigned short) 0 ); }

My mistake, both Entropy and the reseedRandom methods are working fine. Just another question on both of them,

  • I understand that the Entropy library can generate only 2 32bit numbers, so it's rather a slow method.
  • If I'm using the reseedRandom method, and I would use some places of the EEPROM in my program, these could be overwritten? (This isn't the case at the moment, but I'd like to know to be sure in the future)

The reliable but not very sexy way to seed random... http://forum.arduino.cc/index.php?topic=66206.0 http://forum.arduino.cc/index.php?topic=66206.msg537783#msg537783

Ward123: I understand that the Entropy library can generate only 2 32bit numbers, so it's rather a slow method.

I believe the "simplified version" only generates one 32 bit number and it is a "rather slow method" (looks like about 500ms). But that's exactly what is needed to initialize a pseudo random number generator.

If I'm using the reseedRandom method, and I would use some places of the EEPROM in my program, these could be overwritten?

Yes. In the Arduino world, you are responsible for managing the EEPROM.

From what you have described, you should be calling reseedRandom exactly once in setup. reseedRandom takes one parameter, the EEPROM address to use. reseedRandom uses four sequential bytes of EEPROM. So, if you call reseedRandom like this...

void setup( void )
{
  reseedRandom( (unsigned short) 0 );
}

...EEPROM addresses 0, 1, 2, and 3 are used by reseedRandom. If you need it to use a different range, just change the zero to the starting address.