Generate pseudo Gaussian random numbers for pwm pins

Hi ,

I would like to create a set of random natural numbers that resemble a Gaussian distribution. The reason I want natursl numbers is because I would like to give these numbers as pwm values for lighting an led

I found this library which can generate a set of random numbers from a Gaussian.

would making these numbers integers after getting the distribution be my best bet?

Any input is appreciated.

Hi, welcome to the forum.

Ask 10 programmers about random, and you get 100 opinions :rofl:
This topic might get flooded with everyone talking about random and what they think is best. In the end, the Arduino random() function which uses the GCC compiler random is not so bad, it pretty evenly distributed.

Sure, you can use that Gaussian library and convert the value to a 0...255 integer for the PWM.

Why do you need something sophisticated for just a led ?
If you want a certain visual effect, then there are easier ways to implement a curve.

Did you know that the human eye sees brightness with almost a 10log curve ? That is a very steep curve. Perhaps what you have in mind will be visually not the same.

At Github I have a Fun with millis page. The examples "millis_soft_pulsating_led.ino" and "millis_led_heartbeat.ino" have a curve. Click on the blue text for the sketch, use the green button for the simulation in Wokwi.
I'm thinking about a random, going through a Gaussian curve, and then through a 10log curve for the human eye.

Do you even have a choice? The PWM values for a LED are integers.

Hi thanks for the reply? I thought the random() function generates values from a uniform distribution? The experiment needs a set of values chosen from a Gaussian distribution. No i dont want to go through in an increasing order. I would like to generate an array which is drawn from some gaussain distribution

No. But what i wanted to know if there is a better way. Generating a Gaussian distribution from a set of finite values is impossible. I just want to be close to a Gaussian as possible. Thanks for the reply

"Better" is always conditioned by some specific need or benchmark. Without knowing your exact requirements, it is impossible to usefully assist.

By the way, you said "drawn" from a Gaussian distribution. Are you allowing or disallowing identical numbers in the "draw"?

Why do you think the library wouldn't work for you? Why would there be a "better way"? Is something deficient about it that needs to be fixed?

if you are compiling for non AVR Arduino (ESP32 for example) then you could use std::normal_distribution

here is an example:

#include <random>
std::default_random_engine generator;
std::normal_distribution<double> distribution(5.0, 2.0); // distribution parameters, mean (μ=5.0) and stddev (σ=2.0),

const size_t intervalCount = 10;
size_t draws[intervalCount+1] = {};

const size_t experimentCount = 10000;
const size_t starCount = 100; 

void setup() {
  Serial.begin(115200); Serial.println();

  for (size_t i = 0; i < experimentCount; i++) {
    double number = distribution(generator);
    if ((number >= 0.0) && (number < intervalCount)) ++draws[size_t(number)];
  }

  Serial.println("normal_distribution μ=5.0 / σ=2.0");

  for (size_t i = 0; i < intervalCount; ++i) {
    Serial.print(i); Serial.print(" - "); Serial.print(i + 1); Serial.write('\t');
    for (size_t j = 0; j < draws[i] * starCount / experimentCount; j++) Serial.write('*');
    Serial.println();
  }
  Serial.println();
}

void loop() {}

you should see in the Serial Monitor

normal_distribution μ=5.0 / σ=2.0
0 - 1	*
1 - 2	****
2 - 3	*********
3 - 4	***************
4 - 5	******************
5 - 6	*******************
6 - 7	***************
7 - 8	********
8 - 9	****
9 - 10	*

cf normal_distribution - C++ Reference

Identical numbers are fine. I am interested in getting fluctuations of light levels around some mean value. I actually just found the Gaussian library link just before posting this question. I also wanted to know if the values I generated can be saved to the pc for analysis purposes? Or do I need an SD card for this purpose.

Regarding the requirement. I am interested in learning the specific patterns of changes in light that cause responses from neurons in the retina. My LED will be my light source. Hope this helps

see post #7 which I was typing while you were answering (in case you missed it)
it will not compile on UNO and the likes though.

Anything you print to serial, is available at the PC serial port.

I use an UNO board

OK, then you those classes from the library are not available...

True, but using summation, it is trivial to generate a reasonable approximation to a Gaussian distribution from the uniform distribution.

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
}

void loop() {
int rg=0;
  // generate pseudo-Gaussian distribution with mean 0.0 and spread of +/- 1.0
for (int i=0; i<10; i++) rg+=random(1001);
Serial.println((rg-5000)/5000.0);
}

FYI this comes from the : Central limit theorem - Wikipedia

10 might be small in the context of the Central Limit Theorem

It is but a trivial example, demonstrating the principle.

OK - fair

Thanks. I will check this out as well. Thanks for the help. I can just try to plot it out and check how it looks. How would I save the numbers that have been generated to a file. Does that work using the Serial.println command?

By logging them to a terminal emulator program, that can save to a file. Putty, TeraTerm, etc...

@jremington reply #13
while it WILL give a set of numbers that correspond roughly to a gaussian distribution, they wont be random, as the OP requires.

Lots of good mathematical readings around this topic. One can start at