Pages: [1]   Go Down
Author Topic: Help with 8x8 LED matrix and MAX7219 code Conway's Game of Life (almost done)  (Read 1211 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello.  I'm about half done with a project of making a 8x8 LED matrix and controlling it with a MAX7219 IC.  I want it to run Conway's Game of Life and I'll make it into a wall hanging.  I have tinkered with some code I found and got it mostly working.  Can someone look over the code and tell me if (and how) it can be improved.  I noticed that (in my video) the lower left LED if on, stays on till it starts over, when it looks as if it should be blinking with the others, and I don't know why.  So I'm just looking for some advice.  Much thanks.  Here is my code and a link to a short video.
http://youtu.be/tB7lS_1KeGI

Code:
//Game of Life with MAX7219

/*

     * dataPin pin on the Arduino where data gets shifted out
     * clockPin pin for the clock
     * csPin pin for selecting the device
     * numDevices maximum number of devices that can be controled
LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
*/
/*******************************************************************************/

#include "LedControl.h"     //Imports the library

LedControl lc=LedControl(12,11,10,1);

#define SIZEX 8             //Sets the X axis size
#define SIZEY 8             //Sets the Y axis size
#define reseedrate 30       //Sets the rate the world is re-seeded
#define brightness 15       //Values from 1 to 15 to set the brightness
long density = 35;          //Sets density % during seeding
unsigned long delaytime=150;  //Sets the time each generation is shown
int generation = 0;         //Counter for re-seeding
int analogPin = 0;          //analogPin for the random seed data
int world1[8][8] = {{0, 0, 0, 1, 0, 0, 0, 0},
                    {0, 0, 1, 0, 1, 0, 0, 0},
                    {0, 1, 0, 1, 1, 0, 0, 0},
                    {1, 0, 1, 0, 0, 1, 1, 0},
                    {0, 1, 1, 0, 0, 1, 0, 1},
                    {0, 0, 0, 1, 1, 0, 1, 0},
                    {0, 0, 0, 1, 0, 1, 0, 0},
                    {0, 0, 0, 0, 1, 0, 0, 0}};
int world2[8][8];

/*******************************************************************************/
/* display cells */

void display_cells(int world1[8][8])
{
  int i,j;
  for(i=0;i<SIZEX;i++)
  {
    for(j=0;j<SIZEY;j++)
    {
      lc.setLed(0,i,j,world1[i][j]);

    }
  }
}

/*******************************************************************************/
/* compute previous generation*/

void previous_generation(int world1[8][8],int world2[8][8])
{
  int i,j;

  for(i=0;i<SIZEX;i++)
  {
    for(j=0;j<SIZEY;j++)
    {
      world2[i][j]=world1[i][j];
    }
  }
}

/*******************************************************************************/
/* compute next generation */

void next_generation(int world1[8][8],int world2[8][8])
{
  int i,j;

  for(i=0;i<SIZEX;i++)
  {
    for(j=0;j<SIZEY;j++)
    {
      world1[i][j]=world2[i][j];
    }
  }
}

/*******************************************************************************/
/* compute neighborough cells */
#
void neighbours(int world1[8][8],int world2[8][8])
{
  int i,j,a;

  for(i=0;i<SIZEX;i++)
  {
    for(j=0;j<SIZEY;j++)
    {
      if((i==0)&&(j==0))
      {
        a=world1[i][j+1]+world1[i+1][j]+world1[i+1][j+1]+world1[i][69]+world1[i+1][69]+world1[19][j]+world1[19][j+1]+world1[19][69];
      }

      if((i!=0)&&(j!=0)&&(i!=(SIZEX-1))&&(j!=(SIZEY-1)))
      {
        a=world1[i-1][j-1]+world1[i-1][j]+world1[i-1][j+1]+world1[i][j+1]+world1[i+1][j+1]+world1[i+1][j]+world1[i+1][j-1]+world1[i][j-1];
      }
     
      if((i==0)&&(j!=0)&&(j!=(SIZEY-1)))
      {
        a=world1[i][j-1]+world1[i+1][j-1]+world1[i+1][j]+world1[i+1][j+1]+world1[i][j+1]+world1[19][j-1]+world1[19][j]+world1[19][j+1];
      }

      if((i==0)&&(j==(SIZEY-1)))
      {
        a=world1[i][j-1]+world1[i+1][j-1]+world1[i+1][j]+world1[i][0]+world1[i+1][0]+world1[19][0]+world1[19][j]+world1[19][j-1];
      }
     
      if((i==(SIZEX-1))&&(j==0))
      {
        a=world1[i-1][j]+world1[i-1][j+1]+world1[i][j+1]+world1[i][69]+world1[i-1][69]+world1[0][j]+world1[0][j+1]+world1[0][69];
      }
     
      if((i==(SIZEX-1))&&(j!=0)&&(j!=(SIZEY-1)))
      {
        a=world1[i][j-1]+world1[i][j+1]+world1[i-1][j-1]+world1[i-1][j]+world1[i-1][j+1]+world1[0][j]+world1[0][j-1]+world1[0][j+1];
      }
     
      if((i==(SIZEX-1))&&(j==(SIZEY-1)))
      {
        a=world1[i][j-1]+world1[i-1][j-1]+world1[i-1][j]+world1[0][j]+world1[0][j-1]+world1[i][0]+world1[i-1][0]+world1[0][0];
      }

      if((i!=0)&&(i!=(SIZEX-1))&&(j==0))
      {
        a=world1[i-1][j]+world1[i-1][j+1]+world1[i][j+1]+world1[i+1][j+1]+world1[i+1][j]+world1[i][69]+world1[i-1][69]+world1[i+1][69];
      }

      if((i!=0)&&(i!=(SIZEX-1))&&(j==(SIZEY-1)))
      {
        a=world1[i-1][j]+world1[i-1][j-1]+world1[i][j-1]+world1[i+1][j-1]+world1[i+1][j]+world1[i][0]+world1[i-1][0]+world1[i+1][0];
      }

      if((world1[i][j]==0)&&(a==3)){world2[i][j]=1;}
      if((world1[i][j]==1)&&((a==2)||(a==3))){world2[i][j]=1;}
      if((world1[i][j]==1)&&((a==1)||(a==0)||(a>3))){world2[i][j]=0;}
    }
  }
}

/*******************************************************************************/
/* randomize */

void seedWorld(int world1[8][8])
{
  int i,j;
  randomSeed(analogRead(analogPin));
  for(i=0;i<SIZEX;i++)
  {
    for(j=0;j<SIZEY;j++)
    {
      if (random(100) < density); {
    world1[i][j]=random(2);
      }
  }
  }
}

/*******************************************************************************/

void setup() {
   lc.shutdown(0,false);
   lc.setIntensity(0,brightness);
   lc.clearDisplay(0);
   seedWorld(world1);
}

/*******************************************************************************/

void loop()
{

   if (generation++ > reseedrate)
   {
     seedWorld(world1);
     lc.clearDisplay(0);
     delay(300);
     generation=0;
   }
     
    previous_generation(world1,world2);
    neighbours(world1,world2);
    next_generation(world1,world2);
    display_cells(world1);
    delay(delaytime);
   
 
}

Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My first recommendation would be to use 'unsigned char' instead of 'int' for each element of the arrays:
Code:
unsigned char world1[8][8] = {{0, 0, 0, 1, 0, 0, 0, 0},
                    {0, 0, 1, 0, 1, 0, 0, 0},
                    {0, 1, 0, 1, 1, 0, 0, 0},
                    {1, 0, 1, 0, 0, 1, 1, 0},
                    {0, 1, 1, 0, 0, 1, 0, 1},
                    {0, 0, 0, 1, 1, 0, 1, 0},
                    {0, 0, 0, 1, 0, 1, 0, 0},
                    {0, 0, 0, 0, 1, 0, 0, 0}};
unsigned char world2[8][8];
This will save 50% of the memory space.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the tip John. I appreciate it.  I'll make the change.

Has anyone else written a Conway's Game of Life for 8x8 with MAX7219?  If someone else has a MAX7219 with a 8x8 set up, can you try my code and let me know what you think? What should be changed.  It's not a big deal but there is that one LED that doesn't seem to play by the same rules, and I don't know why. Dose someone else notice, or have the same issue? I think GOL is fun to watch and once it's working well I can post instructions for others. Thanks a bunch.
Matt
Logged

Valencia, Spain
Online Online
Faraday Member
**
Karma: 118
Posts: 4539
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's not a big deal but there is that one LED that doesn't seem to play by the same rules, and I don't know why. Dose someone else notice, or have the same issue?

The corner LEDs have a special code all of their own. I suspect that's where the problem is.

Where do the numbers "19" and "69" come from in that code? Seems to me like that would read memory outside the array...
Logged

No, I don't answer questions sent in private messages...

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That is a good question.  I don't know why the 19s and 69s are there.  I got the code from the forum http://arduino.cc/forum/index.php/topic,7091.0.html.  It was the only example code for GOL with max7219 I could find. I tried to rework it the best I could to make more sense, but that whole section with 19s and 69s i don't understand.  I also tried to rework the GOL code on http://www.arduino.cc/playground/Main/DirectDriveLEDMatrix to work with max7219 and the ledcontrol.h library but could not get it working. I'm fairly new to the more complicated part of coding but i'm trying.  I would appreciate any tips or any help anyone can offer in doing this.
Much thanks,
Matt
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can greatly simplify the neighbor calculations using modulo math:

Code:
/*******************************************************************************/
/* compute neighboring cells */

void neighbours(int world1[8][8],int world2[8][8])
{
  int a = 0;

  for(int i=0;i<SIZEX;i++)
  {
  int above = (i+SIZEX-1)%SIZEX;
  int below = (i+1)%SIZEX;

    for(int j=0;j<SIZEY;j++)
    {
    int left = (j+SIZEY-1)%SIZEY;
    int right = (j+1)%SIZEY

      a += world1[above][left];
      a += world1[above][j];
      a += world1[above][right];
      a += world1[i][left];
      a += world1[i][right];
      a += world1[below][left];
      a += world1[below][j];
      a += world1[below][right];

      if((world1[i][j]==0)&&(a==3)){world2[i][j]=1;}
      if((world1[i][j]==1)&&((a==2)||(a==3))){world2[i][j]=1;}
      if((world1[i][j]==1)&&((a==1)||(a==0)||(a>3))){world2[i][j]=0;}
    }
  }
}
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow, John that is awesome.  I'll test it out when I get home tonight.  Thank you so much for you help.
Matt
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi JohnWasser. I changed the int to unsigned char and that made the display work better. The corner led is now working.

I tried your "neighboring cells" code in place of the one I had but only one row blinked a bit. So it must be missing something, but I appreciated your time in writing it.

If there are any more recommendations to make the code better I'd be happy to hear them. This will be a walling hanging so if you have an idea to add something that is cool to look at and runs autonomously I'd love to hear about it.
Thanks
Matt
Logged

Pages: [1]   Go Up
Jump to: