Controlling LED matrix with sensor

Using a matrix and a sensor I want random LEDs to light up.

Depending on the reading coming from a sensor, will depend on the number of LEDs activated on the matrix.

For now, I am using a 8x8 matrix using a 74hC595 and a TPIC6c595 chained together so that I only use 3 pins for the shift registers, and send in two bytes.

Eventually I want to use more matrix. Using the TPIC for the rows, and x amount of 74hC595s connected in parallel to control the columns. I’m still a way off from working that part out in the code, but if anyone has any direction it would be welcome.

Right now I was to focus on using a sensorValue to determine the percentage of LEDs turning on. For example - I was using a LDR:

0 LEDs = 100% light intensity
25% LEDs ON = 75% light intensity
50% LEDs ON = 50%
75%… and so on

Here is my code so far

int latchPin = 10;
int clockPin = 9; 
int dataPin = 8; 

int counter = 0;


int LEDs[8][8] = {   
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}      
};

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  Serial.begin(9600);  
}

void loop() {
  
int sensorValue = analogRead(A0);
  Serial.println(sensorValue);
  LEDs[random(8)][random(8)] = 1;
  if (counter > 200) 
  {
    blankLED();
    counter = 0;
  }
  
  lightLED();
  counter++;
}

void blankLED() {
  for (int x = 0; x < 8; x++) {
    for (int y = 0; y < 8; y ++) {
      LEDs[x][y] = 0; 
    }
  }
}

void lightLED() {
  byte columnbitsToSend = 0;
  byte rowbitsToSend = 0;

  for (int x = 0; x < 8; x++) // loop function - if x is smaller than 8 add 1, then return old value by x
  {
    columnbitsToSend = 0; // start with no bits column byte 
    rowbitsToSend = 0; // start with no bits for row byte 
      
    for (int y = 0; y < 8; y ++) { // loop function - if y is smaller than 8 add 1, then return old value by y 
      if (LEDs[x][y] == 1)
      
      // if LEDs in array are equal to 1
      {
        bitWrite(rowbitsToSend, y, HIGH); // write y bits to shift reg  
      } 
    }
    
    digitalWrite(latchPin, LOW); // set the latch pin low
    bitWrite(columnbitsToSend, x, HIGH); // write x bits to shift register 
    shiftOut(dataPin, clockPin, MSBFIRST, columnbitsToSend); // shift out col bits MSB
    shiftOut(dataPin, clockPin, MSBFIRST, rowbitsToSend); // shift out row bits MSB
    digitalWrite(latchPin, HIGH);  // set latch pin high, tell shift reg ready to enable outputs
    delay(2);
  }
}

From previous help, I understand that I want to be using something like this:

  if (sensorValue > random(1024));

Many thanks

If an approximate match is okay, then there is simple code that can do the job. I assume the sensor values go from 0 to 1023.

Then just before this line of your code:

  if (LEDs[x][y] == 1)

you can add this:

  LEDs[x][y] = (random(1024) < sensor_value) ? 0 : 1;

or the same logic can be expressed as:

  if (random(1024) < sensor_value)
     LEDs[x][y] = 0;
  else
     LEDs[x][y] = 1;

Note that this logic will not result in a perfect match. For example say the reading was 511 which is a sensor value of 50%. On average 32 of your LEDs would be lit, but it might be 28 or it might be 36. Also unless you need the array for something else, you could get rid of it and move the logic into your ‘if’ statement.

If you want a perfect match between the readings and lights, then you will need a different approach. One way would be to create an array of length 64 in which each entry was a value between 0 and 63. Then each time you want a random set, you would shuffle the array and then pick the top n entries for lighting. The value would need to be mapped to your 2D array.