Feedback!

Cellular Automata

Views: 2203 Difficulty: 4 Status: Pipeline
Cellular_automata_necklace2

From simple rules emerge mysterious and intricate patterns.

Cellular automata are dynamic, life-like algorithms that produce beautiful patterns. This tutorial shows how to program our Wearable Wayfinder or our Joy Gamer with an interactive cellular automata. Get one of your very own at our store! Now you can wear the famous rule 30 or the Sierpinski gasket. This project uses the 1.8" thin film transistor (TFT) Liquid Crystal Display (LCD) screen. You can buy them from adafruit either as a breakout board or just the screen.

Smart Bling

Cellular_automata_necklace_chain
Get some emergent, artificial life bling!

Video

Watch the cellular automata rules unfold line by line. The video is sped up from real time because little arduino takes her sweet time refreshing the TFT LCD screen.

Code

This code will display a set of interesting cellular automata on the screen.
/* LucidTronix Arduino HSB RGB Color library 
 * http://www.lucidtronix.com/tutorials/9
 * Control rgb color by specifying
 * Hue saturation and brightness.
 * This code shows a rainbow
 */
#include <ST7735.h>
#include <SPI.h>

#define cs 10   // for MEGAs you probably want this to be pin 53
#define dc 9
#define rst 8  // you can also connect this to the Arduino reset
ST7735 tft = ST7735(cs, dc, rst);

const int scanline_size = 20;
uint8_t scanline[scanline_size];
uint8_t nextline[scanline_size];
int cur_rule = 0;
const int num_rules = 8;
boolean rules[num_rules][8] = {

  { 0,1,0,1,1,0,1,0},
  { 0,0,0,1,1,1,1,0},
  { 1,0,1,1,0,1,1,0},
  { 0,1,1,1,1,1,1,0},
  { 0,1,0,1,1,1,1,0},
  { 1,1,0,1,1,0,1,1},
  { 0,1,1,1,1,0,1,0},
  { 0,1,0,1,1,0,1,0}
}; 
int btnPin0 = 0;

int btnPin1 = 1;
int cur_y = 0;

int mode = 0;
int num_modes = 4;

unsigned int last_press = 0;

int background_color = 0xFF;
int color = 0xFF;

int backlight_pwm_pin = 3;

void setup(){
  pinMode(btnPin1,INPUT);
  pinMode(btnPin0,INPUT);

  tft.initR();               // initialize a ST7735R chip
  tft.writecommand(ST7735_DISPON); 
 
  
  pinMode(backlight_pwm_pin,OUTPUT);
  digitalWrite(backlight_pwm_pin, HIGH);
  delay(1000);
  delay(500);
  int bx = 0;
  int by = 0;
  delay(2000);
  for (int i = 0; i < scanline_size; i++) {
    scanline[i] = 0;
    if ( i == scanline_size/2) scanline[i] = 0x08;
  }

  
}
void loop(){
  for (int i = 0; i < (scanline_size*8)-1; i++) {
      int left = 0;
      if (i > 0) left = get_bit_from_index(i-1);   // Left neighbor state
      int me = get_bit_from_index(i);       // Current state
      int right = get_bit_from_index(i+1);  // Right neighbor state
      boolean abit = get_bit_from_rules(left,me,right); // Compute next generation state based on ruleset
      set_bit_from_index(i, abit);
      if (mode == 0){
        int cur_r = 15;
        int cur_g = 2;
        int cur_b = random(20,28);
        background_color = cur_r  | (cur_g << 5) | (cur_b << 11); 
        cur_r = 30;
        cur_g = 62;
        cur_b = 0;
        color = cur_r  | (cur_g << 5) | (cur_b << 11); 
      }else if (mode == 1){
        int cur_r =  0;
        int cur_g =  0;
        int cur_b = 0;
        background_color = cur_r  | (cur_g << 5) | (cur_b << 11); 
        cur_r =  random(3,30);
        cur_g =   62;
        cur_b = 30;
        color = cur_r  | (cur_g << 5) | (cur_b << 11); 
      }else if (mode == 2){
        int cur_r =  5;
        int cur_g = random(50,62);
        int cur_b = 15;
        background_color = cur_r  | (cur_g << 5) | (cur_b << 11); 
        cur_r = 19;
        cur_g = 2;
        cur_b = 30;
        color = cur_r  | (cur_g << 5) | (cur_b << 11); 
      }
      if (abit )  tft.drawPixel(cur_y, i, color);
      else tft.drawPixel(cur_y, i, background_color);
      if( digitalRead(btnPin1) == HIGH && millis() - last_press > 500 ){
        cur_rule = ++cur_rule%num_rules;
        for (int i = 0; i < scanline_size; i++) {
          nextline[i] = 0;
          if ( i == scanline_size/2) nextline[i] = 0x08;
        }
        last_press = millis();
      }
      if( digitalRead(btnPin0) == HIGH ){
        tft.fillScreen(background_color);
        for (int i = 0; i < scanline_size; i++) {
          nextline[i] = 0;
          if ( i == scanline_size/2) nextline[i] = 0x08;
        }
        mode = ++mode%num_modes;
      }

  }
  cur_y++;
  if (cur_y > 128) cur_y = 0;
  for (int i = 0; i < scanline_size; i++) {
    scanline[i] = nextline[i];
  }
 
}

void testdrawtext(int ax, int ay, char *text, uint16_t color) {
  tft.drawString(ax, ay, text, color);
}
boolean get_bit_from_index(int index){
  int byte_index = index / 8;
  int bit_index = 7 - (index % 8);
  byte cur_b = scanline[byte_index];
  if ( (cur_b & (1 << bit_index)) != 0x00 ) return 1;
  else return 0;
}
void set_bit_from_index(int index, boolean abit){
  int byte_index = index / 8;
  int bit_index = 7 - (index % 8);
  byte cur_b = nextline[byte_index];
  if ( abit)  cur_b |= (1 << bit_index);
  else cur_b &= ~(1 << bit_index) ;
  nextline[byte_index] = cur_b;
}
int get_bit_from_rules(int a, int b, int c) {
    if (a == 1 && b == 1 && c == 1) return rules[cur_rule][0];
    if (a == 1 && b == 1 && c == 0) return rules[cur_rule][1];
    if (a == 1 && b == 0 && c == 1) return rules[cur_rule][2];
    if (a == 1 && b == 0 && c == 0) return rules[cur_rule][3];
    if (a == 0 && b == 1 && c == 1) return rules[cur_rule][4];
    if (a == 0 && b == 1 && c == 0) return rules[cur_rule][5];
    if (a == 0 && b == 0 && c == 1) return rules[cur_rule][6];
    if (a == 0 && b == 0 && c == 0) return rules[cur_rule][7];
    return 0;
  }

Parts

Title Description # Cost Link Picture
TFT LCD Screen 1.8 inch 160 x 128 pixels LCD screen. ST7735R driver. JDT-1800. 1 $9.95 Link Id618_lrg
PCB Cellular Automata PCB holds color LCD screen and buttons. 1 $8.0 Link Screen_shot_2013-02-15_at_5.34.18_pm
Joystick SMD PSP thumbstick surface mount joystick. Value: x,y 10K pots 1 $3.5 Link Psp1000joystick_med
ATMEGA328P-AU Integrated Circuits (ICs) MCU AVR 32K FLASH 32TQFP Value: 1.8 V ~ 5.5 V 20MHz 1 $3.05 Link Screen_shot_2012-12-28_at_7.31.33_pm
Crystal CRYSTAL 16.00000 MHZ 20PF SMD Value: 16MHz 1 $0.53 Link Ecs-270-20-3x-en-tr
Button 6mm Through Hole Tactile Switch Through Hole SPST-NO 0.05A 12V Value: 0.05A @ 12VDC 1 $0.1 Link Screen_shot_2012-12-28_at_7.41.40_pm
Permalink: http://lucidtronix.com/tutorials/9
Two LED matrices give 70 LEDs to light up a necklace with messages....
Handheld gaming machine, based on the Arduino Leonardo, equipped with joystick, SD card and more....
Print bitmaps, cellular automata, drawings and text.....
Rainbow flower necklace using the TLC5940....
The heartduino is a heart-shaped arduino clone complete with onboard sensors and a 70 pixel LED matri...
Wearable digital compass displays the direction in green LEDs....
3d view of a face using an SD card, accelerometer and a TFT LCD Screen...
Wall-ter is a wall following robot....