Go Down

Topic: Help with 8x8 LED matrix and MAX7219 code Conway's Game of Life (almost done) (Read 1 time) previous topic - next topic

GeekGuyMJ

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: [Select]
//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);
   
 
}



johnwasser

My first recommendation would be to use 'unsigned char' instead of 'int' for each element of the arrays:
Code: [Select]

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.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

GeekGuyMJ

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

fungus


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...
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

GeekGuyMJ

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

johnwasser

You can greatly simplify the neighbor calculations using modulo math:

Code: [Select]

/*******************************************************************************/
/* 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;}
    }
  }
}
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

GeekGuyMJ

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

GeekGuyMJ

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

Go Up