270h Final Project

From CSclasswiki
Jump to: navigation, search

Proposal

Overview

The Goal: An Arduino only project that mimics the game of life on an 8x8 LED matrix. The project would also have a light sensor and an LED. If there is enough light received by the light sensor, the game would continue and the LED would turn on. Otherwise, the game would pause and the LED would be off.

The Game of Life is very simple and only has four rules:

  1. Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overpopulation.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

Plan of Attack

  1. Getting familiar with 8x8 LED matrix
    1. Program the 8x8 LED matrix to display my name
    2. Program the 8x8 LED matrix to mimic game of life
  2. Connect the LED, light sensor and the 8x8 LED matrix
  3. Finish and compile the code
  4. Testing

The Project

Materials

  1. Arduino
  2. MAX7219 64-LED matrix display
  3. Photoresistor
  4. Green LED
  5. Wires

Schematics

Arduino Code

Part 1

/*
  Display my name on 64-LED Matrix 
  Chujun He
  The Matrix displays "C-H-U-J-U-N-❤" repeatedly
*/
#include <LedControl.h>

int DIN = 8;
int CS = 9;
int CLK = 10;


// Define the letters 
byte C[8] = {B01111110,B01000000,B01000000,B01000000,B01000000,B01000000,B01000000,B01111110, };
byte H[8] = {B01000010,B01000010,B01000010,B01111110,B01000010,B01000010,B01000010,B01000010, };
byte U[8] = {B01000010,B01000010,B01000010,B01000010,B01000010,B01000010,B01000010,B01111110, };
byte J[8] = {B01111110,B00001000,B00001000,B00001000,B00001000,B00001000,B00001000,B01111000, };
byte N[8] = {B10000001,B11000001,B10100001,B10010001,B10001001,B10000101,B10000011,B10000001, };
byte HEART[8] = {0x00,0x66,0xff,0xff,0x7e,0x3c,0x18,0x00, };

LedControl lc = LedControl(DIN, CLK, CS, 0);

void setup() {
  lc.shutdown(0, false);
  lc.setIntensity(0,15);  // Set the brightness to maximum value
  lc.clearDisplay(0);     // and clear the display
}

void loop() {
  printByte(C);
  delay(1000);
  printByte(H);
  delay(1000);
  printByte(U);
  delay(1000);
  printByte(J);
  delay(1000);
  printByte(U);
  delay(1000);
  printByte(N);
  delay(1000);
  printByte(HEART);
  delay(1000);
}

// function that turn on the matrix as designated
void printByte(byte character [] ){
  int i = 0;
  for(i = 0; i < 8; i++){
    lc.setRow(0,i,character[i]);
  }
}

Part 4

/*
 * CSC270 Final Project
 * Chujun He
 * 
 * Mimic Conway's Game of Life on 64 LED matrix. The game would continue when the light sensor receives enough light and the LED would be on. 
 * Otherwise, the game would pause and the LED would be off.
*/

#include <LedControl.h>

int DIN = 8; // Digintal input
int CS = 9; // Chip select
int CLK = 10; // Clock signal
int lightSensor = A0; // photoresistor
int LED = 13; 

LedControl lc = LedControl(DIN, CLK, CS, 0);

void setup() {
  // 64 LED matrix 
  lc.shutdown(0, false);
  lc.setIntensity(0,8);  // Set the brightness to maximum value
  lc.clearDisplay(0);     // and clear the display

  // Set up LED
  pinMode(LED, OUTPUT); 
  
  // enable serial monitor for debugging
  Serial.begin(9600);
}

void loop(){
  // get the lightsensor data
  int val = analogRead(lightSensor);
  
  // define the game of life data
  bool cgrid[8][8], ngrid[8][8]; // define current grid and next grid
  int neighbors = 0;
  bool gameover = false; // breaks the game loop

  randomSeed(millis()); //random seed

  // initialize the game grid with random cells
  for (int i = 0; i < 7; i ++){
    for(int j = 0; j <7; j ++){
      if(random(5) > 3){
        cgrid[i][j] = true;
      }else{
        cgrid[i][j] = false;
      }
      ngrid[i][j] = false; // Initialize next grid to be dead.
    }
  }

  Serial.println("new game");

  // when the game should begin/continue
  while(gameover == false){
    int val = analogRead(lightSensor);
    Serial.println(val);
    gameover = true; // initialize it to be true and change accordingly

    // display the current grids
    displayGeneration(cgrid);
    delay(2000); // delay for a second
    
    // If there is enough light, the game continues to next generation
    if(val >= 100){
         digitalWrite(LED, HIGH);
         for(int i = 0; i<8; i ++){
          for(int j = 0; j<8; j ++){
            neighbors = countNeighbors(cgrid, i, j);
            //If a cell is alive, the game continues
            if(cgrid[i][j] == true){ 
              gameover = false;
              
              // if the cell has less than 2 neighbors, it dies in the next generation
              if(neighbors < 2){
                ngrid[i][j] = false;
                }else if(neighbors == 3){ // 3 neighbors make the cell remain alive
                  ngrid[i][j] = true; 
                  }else if(neighbors > 3){ // die due to overpopulation
                    ngrid[i][j] = false;
                    }
             }else{ //if the cell is currently dead, apply dead cell rules.
              if(neighbors == 3){
                ngrid[i][j] = true;  //become alive by reproduction
                }
              }
            }
          } 

          // next generation becomes current generation if not in stable states
         if(memcmp(cgrid, ngrid, sizeof(cgrid)) == 0){ // If in stable or repetitive state, restart.
            gameover = true;
          }else{
            memcpy(cgrid, ngrid, sizeof(cgrid));    //Current grid becomes next grid.
          }
    }else{ // If there is not enough light, remain on the current generation
      gameover = false;
      digitalWrite(LED, LOW);
    }
  }
}

// Display generation on the 64 LED matrix
void displayGeneration(bool ba[8][8]){
  for (int i = 0; i < 8; i++){
    lc.setRow(0, i, (byte) (ba[i][0] | ba[i][1] << 1 | ba[i][2] << 2 | ba[i][3] << 3 | ba[i][4] << 4 | ba[i][5] << 5 | ba[i][6] << 6 | ba[i][7] << 7));
  }
}

// count number of neighbors for the cell
int countNeighbors(bool grid[8][8], int i, int j){
  int neighbors = 0;
  for (int x = -1; x < 2; x++){ //Continue statements detect and skip off-field cells
    if ((i + x < 0) | (i + x > 7)) continue;
    for (int y = -1; y < 2; y++){
      if ((j + y < 0) | (j + y > 7)) continue;
      if ((x == 0) && (y == 0)) continue;
      if (grid[i + x][j + y] == true) neighbors++;
    }
  }
return neighbors;
}

Languages & Libraries

  • Libraries: LedControl

Final Project Demo



Progress Log

2020-04-22 Update:

Objective: Display my name on the 64-LED matrix dislay.

I programmed the 64-LED matrix display to show my name: C-H-U-J-U-N.

2020-04-23 Update:

Objective: Display game of life on the 64-LED matrix display.

I programmed the 64-LED matrix display the game of life.

GAME OF LIFE LOG.jpeg

2020-04-24 Update:

Objective: Add button switch and LED to the project.

I added the sound sensor to the project so that only when the sound sensors receives the sound higher than a certain level, the game would continue. Otherwise, the game would pause. After experiments, I found that the sound sensor is not very stable and can't remain HIGH or LOW for a certain time since it's more sensitive to clip and things like that. Thus, I decided to use switch to control the game of life instead.

2020-04-28 Update:

Objective: Replace switch with light sensor.

Instead of using switch to control the circuit, I would use the light sensor. The game of life would continue only if the light sensor receives a certain amount of light. Otherwise, the game of life would pause and the green LED would be off.

References

LED Hex/ Binary Pattern Generator For Arduino

  • An online led matrix font generator with binary and hex codes for Arduino.

LED Matrix Tutorial

  • A tutorial for programming 64 LED matrix on Arduino.

Game of Life Tutorial

  • A tutorial for programming game of life on 64 LED matrix.

How to Use a Photoresistor (or Photocell) - Arduino Tutorial

  • A tutorial for using a photoresistor.