8x8 RGB LED matrix showing 1D cellular automata...

For a project this quarter, my group suggested using an Arduino to control an 8x8 matrix to show Steven Wolfram's 1D cellular automata. We are writing the code in java first. Before we go further, we'd like to know if this is a good idea! We only have a little experience with C/C++.

It's a fine idea in general, and there are a few people here, myself included, who can help with the interfacing-with-matrix part.

But a couple comments: (1) an 8x8 matrix is pretty small to see the effects of 1D automata. It's too small for a useful 2D like Conway's Life also. And (2) why Java? Not impossible by any means, but since the Arduino language is C/C++, if you do a lot of stuff "the Java way" you will find it challenging to port it.

Well, the only language that we know is Java. We figured that we'd hammer it out and then deal with translating it.

Do you have any suggestions for better ways to go about it? I'd really appreciate it, as this is my first real project on an Arduino!

I would say Java is fine as long as you don’t do anything too tricky. Here’s an 8x8 Life in Processing (Java) and then in Arduino (C/C++). Spot the difference in the “business logic” bits (“Birth and death cycle” and “neighbours” function). If you carefully separate code that implements your algorithm and code that deals with the hardware/environment then you’ll be OK.

Andrew

Processing:

int sx, sy;
float density = 0.5;
int size=8;
float scale = 1;
PImage b;
String imgName;
int world;

void setup()
{
size(400,400);
frameRate(12);
sx = sy = size;
scale = width / size;
world = new int[sx][sy][2];
ellipseMode(CORNER);
stroke(100);

// Set random cells to ‘on’
//for (int i = 0; i < sx * sy * density; i++) {
// world[(int)random(sx)][(int)random(sy)][1] = 1;
//}
// Want a fixed setup
world[4][0][1] = 1; world[5][0][1] = 1;
world[5][1][1] = 1; world[6][1][1] = 1;
world[6][2][1] = 1; world[7][2][1] = 1;
}

void draw()
{
background(250);
// Drawing and update cycle
for (int x = 0; x < sx; x=x+1) {
for (int y = 0; y < sy; y=y+1) {
//if (world[y][1] == 1)
// Change recommended by The.Lucky.Mutt
if ((world[y][1] == 1) || (world[y][1] == 0 && world[y][0] == 1))
{
world[y][0] = 1;
fill(255, 0, 0);
ellipse(xscale, yscale, scale, scale);
}
else {
fill(150);
ellipse(xscale, yscale, scale, scale);
}
if (world[y][1] == -1)
{
world[y][0] = 0;
}
world[y][1] = 0;
}
}
delay(500);
// Birth and death cycle
for (int x = 0; x < sx; x=x+1) {
for (int y = 0; y < sy; y=y+1) {
int count = neighbors(x, y);
if (count == 3 && world[y][0] == 0)
{
world[y][1] = 1;
}
if ((count < 2 || count > 3) && world[y][0] == 1)
{
world[y][1] = -1;
}
}
}
}

// Count the number of adjacent cells ‘on’
int neighbors(int x, int y)
{
return world[(x + 1) % sx][y][0] +
world[(y + 1) % sy][0] +
world[(x + sx - 1) % sx][y][0] +
world[(y + sy - 1) % sy][0] +
world[(x + 1) % sx][(y + 1) % sy][0] +
world[(x + sx - 1) % sx][(y + 1) % sy][0] +
world[(x + sx - 1) % sx][(y + sy - 1) % sy][0] +
world[(x + 1) % sx][(y + sy - 1) % sy][0];
}

Arduino:

/*

  • Conway’s “Life”
  • Adapted from the Life example
  • on the Processing.org site
  • Needs FrequencyTimer2 library
    */

#include <FrequencyTimer2.h>

byte col = 0;
byte leds[8][8];

// pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to make array start at pos 1)
int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};

// col[xx] of leds = pin yy on led matrix
int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};

// row[xx] of leds = pin yy on led matrix
int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};

#define DELAY 0
#define SIZE 8
extern byte leds;
byte world[2];
long density = 50;

void setup() {
setupLeds();
randomSeed(analogRead(5));
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (random(100) < density) {
world*[j][0] = 1;*

  • }*
  • else {*
    _ world*[j][0] = 0;_
    _
    }_
    _ world[j][1] = 0;
    }
    }
    }
    void loop() {
    // Display current generation*
    * for (int i = 0; i < SIZE; i++) {
    for (int j = 0; j < SIZE; j++) {
    leds[j] = world[j][0];
    }
    }
    delay(DELAY);
    // Birth and death cycle*

    * for (int x = 0; x < SIZE; x++) {
    for (int y = 0; y < SIZE; y++) {
    // Default is for cell to stay the same*

    * world[y][1] = world[y][0];
    int count = neighbours(x, y);
    if (count == 3 && world[y][0] == 0) {
    // A new cell is born*

    * world[y][1] = 1;
    }
    if ((count < 2 || count > 3) && world[y][0] == 1) {
    // Cell dies*

    * world[y][1] = 0;
    }
    }
    }
    // Copy next generation into place*

    * for (int x = 0; x < SIZE; x++) {
    for (int y = 0; y < SIZE; y++) {
    world[y][0] = world[y][1];
    }
    }
    }
    int neighbours(int x, int y) {
    return world[(x + 1) % SIZE][y][0] +
    world[(y + 1) % SIZE][0] +
    world[(x + SIZE - 1) % SIZE][y][0] +
    world[(y + SIZE - 1) % SIZE][0] +
    world[(x + 1) % SIZE][(y + 1) % SIZE][0] +
    world[(x + SIZE - 1) % SIZE][(y + 1) % SIZE][0] +
    world[(x + SIZE - 1) % SIZE][(y + SIZE - 1) % SIZE][0] +
    world[(x + 1) % SIZE][(y + SIZE - 1) % SIZE][0];
    }
    void setupLeds() {
    // sets the pins as output*

    * for (int i = 1; i <= 16; i++) {
    pinMode(pins, OUTPUT);
    }
    // set up cols and rows*

    * for (int i = 1; i <= 8; i++) {
    digitalWrite(cols[i - 1], LOW);
    }
    for (int i = 1; i <= 8; i++) {
    digitalWrite(rows[i - 1], LOW);
    }
    clearLeds();
    // Turn off toggling of pin 11 and 3*

    * FrequencyTimer2::disable();
    // Set refresh rate (interrupt timeout period)
    FrequencyTimer2::setPeriod(2000);
    // Set interrupt routine to be called*

    * FrequencyTimer2::setOnOverflow(display);
    }
    void clearLeds() {
    // Clear display array*

    * for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
    leds[j] = 0;
    }
    }
    }
    // Interrupt routine*

    void display() {
    * digitalWrite(cols[col], LOW); // Turn whole previous column off*
    * col++;
    if (col == 8) {
    col = 0;
    }
    for (int row = 0; row < 8; row++) {
    if (leds[col][7 - row] == 1) {
    digitalWrite(rows[row], LOW); // Turn on this led*

    * }
    else {
    digitalWrite(rows[row], HIGH); // Turn off this led*

    * }
    }
    digitalWrite(cols[col], HIGH); // Turn whole column on at once (for equal lighting times)
    delayMicroseconds(900); // Delay so that on times are longer than off time = brighter leds*

    }
    [/quote]_