Project tutorial
8x8 LED Matrix Random Number Display

8x8 LED Matrix Random Number Display © GPL3+

Randomly select from the 64 LED of an 8x8 matrix. Once a predetermined percent of the total have been selected, display the stats in colors.

  • 8 views
  • 0 comments
  • 0 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
SunFounder Full Color RGB LED Matrix Driver Shield + RGB Matrix Screen for Arduino
×1
4x4 inch box (10.16x10.16 cm) From Craft store or online to house the project
×1

Apps and online services

About this project

The project uses the Arduino random number generator library to (psuedo) randomly select numbers between 0 and 63. Selected number is illuminated on the LED matrix.

Once a predetermined percent of the total array size (of 64) has been randomly selected at least once, the cycle is deemed complete. LED matrix with then light the selected numbers in green and the numbers not selected the time in red for a a few seconds before starting the whole process again.

Commands via the Serial Monitor can be sent to set the percentage and other selected parameters.

This was a (hopefully) fun project to learn the Colorduino Library and to experiment with the random number library as well.

Code

DW1Arduino
Arduino Uno board type programmed with Arduino IDE
//Scott Mangiacotti
//Marlborough, Massachusetts USA
//August 2019
//DW1
//8x8 LED Matrix Random Number Display

#include <Time.h>
#include <TimeLib.h>
#include <Colorduino.h>

//Global constants
int const ARRAY_SIZE = 64;

//Global variables
bool gSystemEnabled = false;
bool gSystemPaused = false;
bool gVerboseMessages = false;
int gDutyCycle = 25;
unsigned long gTimeSnapshot = 0;

float gTargetPercent = 0.90;
long gRnd;
int gDistro[ARRAY_SIZE];
bool gToggle = false;

void setup()
{
  //Initialize LED array
  Colorduino.Init();
  initializeDistroArray();
 
  //Open a serial port
  Serial.begin(9600);

  //Setup
  postAppData();

  //Startup enabled
  ableSystem(true);
  
}


void loop()
{
  //Serial port processing
  if (Serial.available() > 0)
  {
    int iControlCode;
    iControlCode = Serial.parseInt();
    processMessage(iControlCode);
  }

  //Determine what to do based on enable status
  if (gSystemEnabled == true && gSystemPaused == false)
  {
    randomize();
    
  }
  else if (gSystemEnabled == true && gSystemPaused == true)
  {
    processPauseState();
    
  }
  
  //Give back processing time
  delay(gDutyCycle);

}


void randomize()
{

  //Initialize randomization
  long lSeed;
  lSeed = (long)second() * (long)minute() * (long)hour() * (long)weekday() * (long)analogRead(0);

  //Comment out one of the two following lines to experiment with different entropy for pseudo-randomness
  //randomSeed(lSeed);
  randomSeed(micros());

  int iDiv;
  int iModulo;

  //Randomly select an LED to energize every other scan
  gToggle = !gToggle;

  if (gToggle == true)
  {
    gRnd = random(0, 64);  //designed for 8x8 RGB Matrix
    incrementDistroArray(gRnd);
    
    iDiv = gRnd / 8;
    iModulo = gRnd % 8;
    Colorduino.SetPixel(iDiv, iModulo, 0, 0, 255);
  }
  else
  {
    Colorduino.ColorFill(0, 0, 0);
  }

  //Paint
  Colorduino.FlipPage();

  //Results
  float fRes;
  fRes = checkDistroArrayResults();

  //Check if we reached the target coverage
  if (fRes >= gTargetPercent)
  {
    coverageResultsAchieved(fRes);
    gTimeSnapshot = millis();
  }
}


void initializeDistroArray()
{
  //Iterate
  for (int i=0; i<ARRAY_SIZE; i++)
  {
    gDistro[i] = 0;
  }

  //Post results
  Serial.println("Array distribution list initialized");
  
}


void incrementDistroArray(int iIndex)
{
  //Validate
  if (iIndex < 0 || iIndex >= ARRAY_SIZE)
  {
    return;
  }

  //Increment
  gDistro[iIndex]++;

  //Post results
  if (gVerboseMessages == true)
  {
    Serial.print("Distro array index: ");
    Serial.print(iIndex);
    Serial.print(". New value: ");
    Serial.println(gDistro[iIndex]);
  }
  
}


//Return value in decimal. 14% to be returned as 0.14
float checkDistroArrayResults()
{
  int iCount;
  float fResult;

  //Initialize
  iCount = 0;
  
  //Iterate
  for (int i=0; i<ARRAY_SIZE; i++)
  {
    if (gDistro[i] > 0)
    {
      iCount++;
    }
  }

  //Check results
  fResult = ((float)iCount/(float)ARRAY_SIZE);

  if (gVerboseMessages == true)
  {
    Serial.print("Success count: ");
    Serial.print(iCount);
    Serial.print(". Percent: ");
    Serial.println(fResult);
  }

  return fResult;
}


void coverageResultsAchieved(float fResPct)
{
  //ilmo
  int iDiv;
  int iModulo;

  //Clear display in prep for displaying results
  Colorduino.ColorFill(0, 0, 0);
  Colorduino.FlipPage();

  //Iterate
  for (int i=0; i<ARRAY_SIZE; i++)
  {
    //Determine row and column from array index
    iDiv = i / 8;
    iModulo = i % 8;

    //Illuminate LED  
    if (gDistro[i] > 0)
    { //green this value was randomly selected
      Colorduino.SetPixel(iDiv, iModulo, 0, 255, 0);
    }
    else
    { //red this value was not randomly selected
      Colorduino.SetPixel(iDiv, iModulo, 255, 0, 0);
    }
    
  }

  //Paint
  Colorduino.FlipPage();

  //Post results
  Serial.print(fResPct * 100.00);
  Serial.println("% coverage achieved. Pausing system.");

  //Pause
  gSystemPaused = true;
  
}


void processPauseState()
{

  unsigned long lNow;
  unsigned long lDelta;
  
  //Initialize
  lNow = millis();

  //Calculate time difference in milliseconds
  lDelta = lNow - gTimeSnapshot;

  //Compare
  if (lDelta > 14000) //14000 milliseconds or 14 seconds
  {
    initializeDistroArray();
    gSystemPaused = false;
    Serial.println("Pause time expired. Restart Randomizing");
  }
  
}


void ableSystem(bool bEnable)
{
  if (bEnable == true)
  {
    //ilmoReset all counters in preparation for starting
    initializeDistroArray();
    Colorduino.ColorFill(0, 0, 0);

    //Set parameters as needed
    gSystemEnabled  = true;
    gSystemPaused = false;

    //Post results
    Serial.print("System enabled. Target: ");
    Serial.print(gTargetPercent*100.00);
    Serial.println("%");
  }
  else
  {
    //Disable system
    gSystemEnabled  = false;
    gSystemPaused = false;
    Colorduino.ColorFill(0, 0, 0);

    //Post results
    Serial.println("System disabled");
  }

  //Paint
  Colorduino.FlipPage();
  
}


//Read data from serial port and process message from user
//Format is: XXnnnn
//XX is a value between 1 - 32 and represents the command type or area (for example manual commands to the HOUR servo motor)
//nnnn is a value between 0-1000 and represents the value for the target command type
//For example, 01180 is type 02 and value 180. It represents HOUR servo motor move to position 180 degrees
//See documentation for command definitions and value ranges
void processMessage(int iMessage)
{
  int iControlCode;
  int iControlValue;

  //Process the serial port message
  if (iMessage > 0)
  {
    iControlCode = iMessage / 1000;
    iControlValue = iMessage % 1000;
  }

  //Misc control and command codes
  if (iControlCode == 10)
  {
    if (iControlValue == 0)
    {
      postAppData();
      
    }
    //Control codes and commands
    else if (iControlValue == 1)
    {
      if (gSystemEnabled == false)
      {
        ableSystem(true);  
      }
      else
      {
        Serial.println("System already enabled");
      }
      
    }
    else if (iControlValue == 2)
    {
      ableSystem(false);  

    }
    else if (iControlValue == 3)
    {
      gVerboseMessages = !gVerboseMessages;

      if (gVerboseMessages == false)
      {
        Serial.println("Verbose mode disabled");
      }
      else
      {
        Serial.println("Verbose mode enabled");
      }
    }
    else if (iControlValue == 4)
    { //report all settings

      Serial.print("Target percent = ");
      Serial.print(gTargetPercent*100.00);
      Serial.println("%");
      //Iterate array ilmo
      for (int i=0; i<ARRAY_SIZE;  i++)
      {
        Serial.print("LED[");
        Serial.print(i);
        Serial.print("] = ");
        Serial.println(gDistro[i]);
      }
      
           
    }
    else
    {
      Serial.print("Invalid Control Value: ");
      Serial.println(iControlValue);
    }
  }

  if (iControlCode == 11)
  { //New Target Percent
    if (iControlValue >= 10 && iControlValue <= 100)
    {
      gTargetPercent = (float)iControlValue / 100.0;
      Serial.print("Target percent changed to: ");
      Serial.print(gTargetPercent*100);
      Serial.println("%");
    }
    else
    {
      Serial.print("New Target Percent Value out of range: ");
      Serial.println(iControlValue);
    }
  }

  //Draw separator
  Serial.println("-----");

}


void postAppData()
{
  Serial.println("DW1");
  Serial.println("8x8 LED Matrix Random Number Display");
  Serial.println("By Scott Mangiacotti");
  Serial.println("Marlborough, Massachusetts USA");
  Serial.println("August 2019");
}

Custom parts and enclosures

Instructions and documentation
uploads2ftmp2f269e080b-3dba-4768-955e-4382ca150eee2fdw1_jatyszvKCU.xlsx
Number Stencil
Print this stencil to layer on the LED matrix array

Comments

Similar projects you might like

Random Number Generator with 8x8 LED Matrix and Arduino

Project tutorial by LAGSILVA

  • 1,015 views
  • 2 comments
  • 6 respects

LED Matrix + Motion Sensor Door Display [Arduino Holiday]

Project tutorial by HeathenHacks

  • 3,872 views
  • 2 comments
  • 21 respects

Bluetooth control led with lcd led status display real time.

Project tutorial by Youssef Sabaa

  • 24,111 views
  • 4 comments
  • 44 respects

8x8 Matrix LED Snake Game (Smartphone Motion)

Project tutorial by hmkim

  • 6,311 views
  • 2 comments
  • 20 respects

16x16 LED Matrix Display

Project showcase by Treebug842

  • 6,109 views
  • 2 comments
  • 14 respects

Arduino 32x8 LED Matrix Info Display

Project showcase by ericBcreator

  • 37,349 views
  • 81 comments
  • 70 respects
Add projectSign up / Login