Issues with random() and lighting LEDs

I’m pretty new to Arduino, and after some success with some example sketches and a few of my own, I decided to attempt a simple project.

The intent here is to create what is basically a light responsive “cricket” with a few LEDs.

In high light, it should emit a random sound and light sequence and then sleep for a short time.
In medium light, it should emit a random sound and light and then sleep for a medium time.
In low light, it only blinks the Red LED and then sleeps for a long time.

The code below runs without errors.
It successfully measures the light and makes a decision based on that.
It successfully fills the soundArray and plays the sounds.
It successfully sleeps for a period of time.

However:
The notes (frequency) never seems to vary very much, no matter how large or small I make FREQRANGE (# of possible values) and FREQMOD (separation between possible values). Only FREQMOD2 (starting point of range) seems to have any real effect. DURMOD works perfectly.

The LED’s never light up. Not when reading the light level or when playing the sound and light sequence.

Does anyone have any insight here?
Are there certain pins I should be using for the LEDs? I have tried a few different ones, but have not seen a change.

Thanks,

Quick

This code uses the RocketScream LowPower library.
You could replace the sleep function with a delay for the same effect if you do not have this library.

#include <LowPower.h>

// set output pins
const int RED = 13;                                             // Red LED
const int GRN = 7;                                              // Green LED
const int BZZ = 8;                                              // Buzzer
const int LDR = A0;                                             // Light Detecting Resistor

// set constants
const int MAXLIGHT = 300;                                       // awakeness
const int MINLIGHT = 40;
const int MEDMIN = 2;// medium sleep 
                                             //SLEEP TIMES ARE IN 8s of SECONDS i.e. 15*8 seconds = 120 s = 2 min
const int MEDMAX = 5;
const int SHORTMIN = 1;                                         // short sleep
const int SHORTMAX = 2;
const int LONGMIN = 5;                                          // long sleep
const int LONGMAX = 6;
const int READDELAY = 300;                                      // delay between LED on and read (LED OFF)
const int FREQMOD = 1500;                                       // used to modify frequency values
const int FREQMOD2 = 200;                                       // minimum freq-FREQMOD
const int FREQRANGE = 80;                                       // num possible notes
const int DURMOD = 50;                                          // modify durations

// set variables
int count = 0;                                                  // used for many things
int soundDelay = 200;                                           // delay between notes
int soundArray[16];                                             // 8 freqs, 8 durs. F,D,F,D...
int lightArray[8];                                              // 4 variations of 2 LEDs
int sleepCount = 0;                                             // sleep time
int lightLevel = 0;                                               // light measurement



//Startup routine (run once)
void setup(){                                                   // set output pins
  pinMode(RED, OUTPUT);
  pinMode(GRN, OUTPUT);
  pinMode(BZZ, OUTPUT);
  Serial.begin(9600);                                        // Serial communication for debugging
  randomSeed(analogRead(A0));                       // set random seed for more varied behavior
}

//Main loop. runs repeatedly
void loop() {
  count = 0;                                                    // reset count
  digitalWrite(RED, HIGH);
  Serial.println("RED");
  delay(READDELAY);                                             // blink LED
  lightLevel = analogRead(LDR);                                 // get light reading
  Serial.println(lightLevel);
  if (lightLevel<MINLIGHT){                                     // low light
    Serial.println("low light");
    digitalWrite(RED, LOW);
    sleepCount = random(LONGMIN, LONGMAX);
  }
  else if (lightLevel>MAXLIGHT){                                // high light
    Serial.println("high light");
    soundLightPatternGen();
    count = 0;
    soundLightExecution();
    count = 0;
    sleepCount = random(SHORTMIN, SHORTMAX);
  }
  else{                                                         // medium light
    Serial.println("med light");
    soundLightPatternGen();
    count = 0;
    soundLightExecution();
    count = 0;
    sleepCount = random(MEDMIN, MEDMAX);
  }
  digitalWrite(RED, LOW);
  digitalWrite(GRN, LOW);
  timedSleep(sleepCount);
}
  
//Functions

void soundLightPatternGen(){
  Serial.println("Pattern gen");
  for (count = 0; count<16; count+=2){
    soundArray[count] = (random(FREQRANGE));                    // Frequency
    Serial.println(soundArray[count]);
    soundArray[count+1] = random(1,9)*DURMOD;                   // Duration
    Serial.println(soundArray[count+1]);
    lightArray[count/2] = random(4);                            // LED
    Serial.println(lightArray[count/2]);
  }
}

void soundLightExecution(){
  Serial.println("LED EXEC");
  digitalWrite(RED, LOW);
  digitalWrite(GRN, LOW);
  switch(count/2){
    case 0:
      break;
    case 1:
      digitalWrite(RED, HIGH);
      break;
    case 2:
      digitalWrite(GRN, HIGH);
      break;
    case 3:
      digitalWrite(RED, HIGH);
      digitalWrite(GRN, HIGH);
      break;
  }
  for (count=0; count<16; count+=2){
    Serial.println("sound exec");
    if (soundArray[count] = 0){                                 // Null Frequency
      delay((soundArray[count+1])*10);
    }
    else 
    {
      tone(BZZ, (((soundArray[count])*FREQMOD)+FREQMOD2), soundArray[count+1]);
      delay(soundDelay);
    }
  }
}

void funcLED(int x){
  digitalWrite(RED, LOW);
  digitalWrite(GRN, LOW);
  switch(x){
    case 0:
      break;
    case 1:
      digitalWrite(RED, HIGH);
      break;
    case 2:
      digitalWrite(GRN, HIGH);
      break;
    case 3:
      digitalWrite(RED, HIGH);
      digitalWrite(GRN, HIGH);
      break;
  }
}

void timedSleep(int x){
  for (int i=0; i<x; i++){
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
  }
}
const int FREQRANGE = 80;                                       // num possible notes

I miss the relationship between the comment and the variable name (or it's use).

    if (soundArray[count] = 0){

Assigning a value to an element of the array in an if statement is not normal.

FREQRANGE is used when generating the soundArray[]

Basically,

soundArray[x] = random(FREQRANGE);

It is intended to limit the possible values of soundArray[x] to some value between 0 and FREQRANGE. 0-79 in this case.

That if statement should have been

if (soundArray[count] == 0){

Good catch. I have a tendency to forget the second "="

I have a tendency to forget the second "="

And to use code tags, so the "code" you posted doesn't get mangled. I'm reasonably confident that your code does not look like that in the previous post.

Forgive me. I was not aware that square brackets around an "x" would result in a bullet point.

soundArray[x] = random(FREQRANGE);

Intended to limit the possible values of items within the array.

Have you noticed anything else I've forgotten?

The next step is to print the data in the soundArray array, to make sure that it contains what you expect it to contain.

If it does not, then you need to do one thing. If it does, you need to do something different.

I have no idea, at this time, what you need to do. But, if the data is good, it is pointless to waste time trying to figure out why it might not be good. If the data is no good, then it is pointless to waste time trying to figure out why the program does not properly function when given bad data.

Divide and conquer!

I corrected the if statement and that seemed to fix the sound problem (Yay). The notes are now sufficiently different, but the LEDs still do not light.

After some investigating, I realized that my LED function was incorrect. It was using the count value rather than the array value in the switch statement. This led to a lot of "default" cases.

I fixed it, but the LEDs still do not light. Not surprising, since the code sets the LED pins high a few times outside of the switch. The on board LED, however, will light when appropriate.

I have checked the wiring several times. It is correct, and I am using 220 Ohm resistors in series with the LEDs. I also tried no resistors at all.

I disconnected the buzzer to see if it was drawing too much power for both to run at the same time, but still no luck.

So, you've made a lot of code changes, without posting the code here, and it still doesn't work. All I can say is "bummer".

The code changes have no effect on the LEDs. digitalWrite(PIN, HIGH) still does not seem to function, even when the sketch is only a simple blinking sketch. I suppose it must be some wiring error on my part.

I did notice that the analog reading of the LDR does not seem to function as it did in my tests.
A well lit room should be a value between 800-860, and a dark room 0-20. The LDR now only seems to accurately measure the first reading with all subsequent readings being within 50 or so points.

I thought that this might have to do with turning the ADC off during sleep, so I replaced that bit with a delay() and tested it again. This had no noticeable effect.

I also thought that the reading might need time to “settle” since its response time was pretty slow in my initial tests, so I added a few more readings before the final, decision-making reading. This also seemed to have no noticeable effect.

#include <LowPower.h>

// set output pins
const int RED = 13;                                             // Red LED
const int GRN = 12;                                             // Green LED
const int BZZ = 8;                                              // Buzzer
const int LDR = A0;                                             // Light Detecting Resistor

// set constants
const int MAXLIGHT = 300;                                       // awakeness
const int MINLIGHT = 40;
const int MEDMIN = 2;                                           // medium sleep SLEEP TIMES ARE IN 8s of SECONDS i.e. 15*8 seconds = 120 s = 2 min
const int MEDMAX = 5;
const int SHORTMIN = 1;                                         // short sleep
const int SHORTMAX = 2;
const int LONGMIN = 5;                                          // long sleep
const int LONGMAX = 6;
const int READDELAY = 300;                                      // delay between LED on and read (LED OFF)
const int FREQMOD = 20;                                         // used to modify frequency values
const int FREQMOD2 = 50;                                        // minimum freq-FREQMOD
const int FREQRANGE = 17;                                       // num possible notes
const int DURMOD = 15;                                          // modify durations
const int DURRANGE = 20;                                        // num possible durations
const int DELAYRANGE = 8;                                       // num possible of delays (between sounds)

// set variables
int count = 0;                                                  // used for many things
int soundDelay = 200;                                           // delay between notes
int soundArray[16];                                             // 8 freqs, 8 durs. F,D,F,D...
int lightArray[8];                                              // 4 variations
int sleepCount = 0;                                             // sleep time
int lightLevel = 0; 
int ledCount = 0;


//Startup routine (run once)
void setup(){                                                   // set output pins
  pinMode(RED, OUTPUT);
  pinMode(GRN, OUTPUT);
  pinMode(BZZ, OUTPUT);
  Serial.begin(9600);
  randomSeed(analogRead(A0));
}

//Main loop. runs repeatedly
void loop() {
  count = 0;                                                    // reset count
  ledCount =0;
  digitalWrite(RED, HIGH);
  Serial.println("RED");
  delay(READDELAY);                                             // blink LED
  analogRead(LDR);                                              // switch to channel to read. supposed to make result more accurate (settle). Are the next ones necessary?
 lightLevel = analogRead(LDR);
 Serial.println(lightLevel);
 lightLevel = analogRead(LDR);
 Serial.println(lightLevel);
 lightLevel = analogRead(LDR);
 Serial.println(lightLevel);
  uint16_t lightLevel = analogRead(LDR);                        // get light reading *not sure what uint is
  Serial.println(lightLevel);
  if (lightLevel<MINLIGHT){                                     // low light
    Serial.println("low light");
    digitalWrite(RED, LOW);
    sleepCount = random(LONGMIN, LONGMAX);
  }
  else if (lightLevel>MAXLIGHT){                                // high light
    Serial.println("high light");
    soundLightPatternGen();
    count = 0;
    ledCount=0;
    soundLightExecution();
    ledCount=0;
    count = 0;
    sleepCount = random(SHORTMIN, SHORTMAX);
  }
  else{                                                         // medium light
    Serial.println("med light");
    soundLightPatternGen();
    count = 0;
    ledCount=0;
    soundLightExecution();
    ledCount=0;
    count = 0;
    sleepCount = random(MEDMIN, MEDMAX);
  }
  digitalWrite(RED, LOW);
  digitalWrite(GRN, LOW);
  timedSleep(sleepCount);
}
  
//Functions

void soundLightPatternGen(){
  //Serial.println("Pattern gen");
  for (count = 0; count<16; count+=2){
    soundArray[count] = (random(FREQRANGE));                    // Frequency
    //Serial.println(soundArray[count]);
    soundArray[count+1] = random(1,DURRANGE)*DURMOD;            // Duration
    //Serial.println(soundArray[count+1]);
    lightArray[ledCount] = random(3);                           // LED
    //Serial.println(lightArray[count/2]);
    ledCount++;
  }
}

void soundLightExecution(){
  
  for (count=0; count<16; count+=2){
    //Serial.println("LED EXEC");
    funcLED(ledCount);
    //Serial.println("sound exec");
    if (soundArray[count] == 0){                                 // Null Frequency
      delay((soundArray[count+1])*10);
    }
    else 
    {
      tone(BZZ, (((soundArray[count])*FREQMOD)+FREQMOD2), soundArray[count+1]);
      soundDelay = random(1, DELAYRANGE);
      delay(soundDelay*50);
    }
    ledCount++;
  }
}

void funcLED(int x){
  digitalWrite(RED, LOW);
  digitalWrite(GRN, LOW);
  //Serial.println("well, the function was called.");
  //Serial.println(x);
  switch(lightArray[x]){
    case 0:
      //Serial.println("NONE");
      break;
    case 1:
      digitalWrite(RED, HIGH);
      //Serial.println("RED");
      break;
    case 2:
      Serial.println("GREEN");
      //digitalWrite(GRN, HIGH);
      break;
    case 3:
      digitalWrite(RED, HIGH);
      digitalWrite(GRN, HIGH);
      //Serial.println("BOTH");
      break;
    default:
      //Serial.println("WTF");
      break;
  }
}

void timedSleep(int x){
  for (int i=0; i<x; i++){
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
  }
  //delay(x*1000);
}
 lightLevel = analogRead(LDR);
 Serial.println(lightLevel);
  uint16_t lightLevel = analogRead(LDR);

Why do you now have a local variable with the same name as a global variable?

The code changes have no effect on the LEDs. digitalWrite(PIN, HIGH) still does not seem to function, even when the sketch is only a simple blinking sketch. I suppose it must be some wiring error on my part.

That's easy enough to test, with a different sketch that simply turns the pin on for 5 seconds and off for 5 seconds.

  randomSeed(analogRead(A0));

The random() function depends on the amount of light in the room?

I really do not like loop index values being global variables. You do not need two index values for the two arrays. count and count/2 should be the same values as in count and ledCount, but with one value there is no way to get out of sync.

Does the behavior of the sketch/Arduino change if you drink lots of coffee (stop going to sleep)?

Well, I suppose I now know what uint16_t does. I was searching online for a relationship between sleep, which turns ADC off, and analog reads. The example I saw used this, but did not explain its purpose.

As I said in the previous post. I have tested the LEDs with a blink sketch and have not had success despite trying different pins and checking the wiring multiple times. (PIN - 220 Ohm - LED - GND) The LEDs do work when I test them with a battery.

The seed for the random function depends on the light in the room. random() is simply a very long sequence of random numbers. Rather than generating a random number each time it is called, it uses a set sequence of pseudorandom numbers. Setting the seed determines where the function will start in that sequence.

Basically, it makes the numbers more random.

I am aware that count/2 would suffice since it is an integer operation. I changed it to ledCount in a vain attempt to solve the LED problem and I did not change it back, yet.

As I said in the previous post, removing the sleep function had no discernable effect on the behavior.

Replying for the sake of anyone who might have a similar problem.

The LDR section of the circuit prevented the LEDs from lighting. Disconnecting the LDR from ground allowed the LEDs to light.

I will continue my queries in the circuit section.