Pages: [1]   Go Down
Author Topic: conways game of life and mstimer2 , 328 on 0018ide  (Read 1498 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, i have a 328 and using the 0018 ide.
im trying to get conways game of life working using mstimer2 as i get the impression that frequencytimer2 doesnt work. i cant get it to work anyway as i know zilch about this stuff. i just need this to work for a degree project.  Heres the code for game of life, mstimer2.cpp, and mstimer2.h
#include <MsTimer2.h>

/*
 * Conway's "Life"
 *
 * Adapted from the Life example
 * on the Processing.org site
 */

#include <MsTimer2.h>

byte analogPin = 5;
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[SIZE][SIZE];
byte world[SIZE][SIZE][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

  // Set refresh rate (interrupt timeout period)

  // Set interrupt routine to be called


}

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 == smiley-cool {
    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
}





now mstimer2.cpp
/*
  MsTimer2.h - Using timer2 with 1ms resolution
  Javier Valencia <javiervalencia80@gmail.com>
  
  History:
        29/May/09 - V0.5 added support for Atmega1280 (thanks to Manuel Negri)
        19/Mar/09 - V0.4 added support for ATmega328P (thanks to Jerome Despatis)
        11/Jun/08 - V0.3
              changes to allow working with different CPU frequencies
              added support for ATMega128 (using timer2)
              compatible with ATMega48/88/168/8
      10/May/08 - V0.2 added some security tests and volatile keywords
      9/May/08 - V0.1 released working on ATMEGA168 only
      

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <MsTimer2.h>

unsigned long MsTimer2::msecs;
void (*MsTimer2::func)();
volatile unsigned long MsTimer2::count;
volatile char MsTimer2::overflowing;
volatile unsigned int MsTimer2::tcnt2;

void MsTimer2::set(unsigned long ms, void (*f)()) {
      float prescaler = 0.0;
      
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
      TIMSK2 &= ~(1<<TOIE2);
      TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
      TCCR2B &= ~(1<<WGM22);
      ASSR &= ~(1<<AS2);
      TIMSK2 &= ~(1<<OCIE2A);
      
      if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) {      // prescaler set to 64
            TCCR2B |= (1<<CS22);
            TCCR2B &= ~((1<<CS21) | (1<<CS20));
            prescaler = 64.0;
      } else if (F_CPU < 1000000UL) {      // prescaler set to 8
            TCCR2B |= (1<<CS21);
            TCCR2B &= ~((1<<CS22) | (1<<CS20));
            prescaler = 8.0;
      } else { // F_CPU > 16Mhz, prescaler set to 128
            TCCR2B |= ((1<<CS22) | (1<<CS20));
            TCCR2B &= ~(1<<CS21);
            prescaler = 128.0;
      }
#elif defined (__AVR_ATmega8__)
      TIMSK &= ~(1<<TOIE2);
      TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
      TIMSK &= ~(1<<OCIE2);
      ASSR &= ~(1<<AS2);
      
      if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) {      // prescaler set to 64
            TCCR2 |= (1<<CS22);
            TCCR2 &= ~((1<<CS21) | (1<<CS20));
            prescaler = 64.0;
      } else if (F_CPU < 1000000UL) {      // prescaler set to 8
            TCCR2 |= (1<<CS21);
            TCCR2 &= ~((1<<CS22) | (1<<CS20));
            prescaler = 8.0;
      } else { // F_CPU > 16Mhz, prescaler set to 128
            TCCR2 |= ((1<<CS22) && (1<<CS20));
            TCCR2 &= ~(1<<CS21);
            prescaler = 128.0;
      }
#elif defined (__AVR_ATmega128__)
      TIMSK &= ~(1<<TOIE2);
      TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
      TIMSK &= ~(1<<OCIE2);
      
      if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) {      // prescaler set to 64
            TCCR2 |= ((1<<CS21) | (1<<CS20));
            TCCR2 &= ~(1<<CS22);
            prescaler = 64.0;
      } else if (F_CPU < 1000000UL) {      // prescaler set to 8
            TCCR2 |= (1<<CS21);
            TCCR2 &= ~((1<<CS22) | (1<<CS20));
            prescaler = 8.0;
      } else { // F_CPU > 16Mhz, prescaler set to 256
            TCCR2 |= (1<<CS22);
            TCCR2 &= ~((1<<CS21) | (1<<CS20));
            prescaler = 256.0;
      }
#endif
      
      tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler);
      
      if (ms == 0)
            msecs = 1;
      else
            msecs = ms;
            
      func = f;
}

void MsTimer2::start() {
      count = 0;
      overflowing = 0;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
      TCNT2 = tcnt2;
      TIMSK2 |= (1<<TOIE2);
#elif defined (__AVR_ATmega128__)
      TCNT2 = tcnt2;
      TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega8__)
      TCNT2 = tcnt2;
      TIMSK |= (1<<TOIE2);
#endif
}

void MsTimer2::stop() {
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
      TIMSK2 &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega128__)
      TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega8__)
      TIMSK &= ~(1<<TOIE2);
#endif
}

void MsTimer2::_overflow() {
      count += 1;
      
      if (count >= msecs && !overflowing) {
            overflowing = 1;
            count = 0;
            (*func)();
            overflowing = 0;
      }
}

ISR(TIMER2_OVF_vect) {
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
      TCNT2 = MsTimer2::tcnt2;
#elif defined (__AVR_ATmega128__)
      TCNT2 = MsTimer2::tcnt2;
#elif defined (__AVR_ATmega8__)
      TCNT2 = MsTimer2::tcnt2;
#endif
      MsTimer2::_overflow();
}
 


now mstimer2.h
#ifndef MsTimer2_h
#define MsTimer2_h

#include <avr/interrupt.h>

namespace MsTimer2 {
      extern unsigned long msecs;
      extern void (*func)();
      extern volatile unsigned long count;
      extern volatile char overflowing;
      extern volatile unsigned int tcnt2;
      
      void set(unsigned long ms, void (*f)());
      void start();
      void stop();
      void _overflow();
}

#endif




i hope someone can help me with this, im going insane with forum merry go round. please bare in mind that i know nothing of how to program. im only an artist trying to add a little pizzaz to a light.  thanks. jay
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have had success using the Timer1 library with that code.

You can find the Timer1 library at http://www.arduino.cc/playground/Code/Timer1. The "install instructions" on that page are no longer valid for IDE 0018, so create a TimerOne (note the spelling) directory in the libraries folder. Download the zip file and put the TimerOne.h and TimerOne.cpp files from it into that new directory.

Change your
   #include <MsTimer2.h>
to
   #include <TimerOne.h>
and add the following code somewhere in setup().
Code:
 // Establish an interrupt
  Timer1.initialize(100); // interrupt every 100 microseconds
  Timer1.attachInterrupt(display); // control will go to the display() function when the interrupt happens

Your code compiles with those changes, but I don't have a spare LED matrix to test with. Let us know how it goes, for the benefit of the next person to find this thread through a search of some kind.
« Last Edit: May 13, 2010, 09:29:04 am by TBAr » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, ive just done what you have suggested and bingo! it compiles. got to wait 12 agonising hours now to see if it works on my matrix at uni. so its fingers, toes and balls crossed. Thankyou for such a quick reply. ill let you know tomorrow what happens.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

HI, The new problem is that it tries to use com1  serial port to output, my board is on com 10. any ideas. thanks jay
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

[edit]The new problem is that [glow]it[/glow] tries to use com1  serial port to output[/edit]
I don't understand. "It" probably doesn't mean the sketch, since there are no serial commands there, and the sketch does not use digital pin 0 or 1. Does "it" refer to the Arduino IDE? If so, pull down Tools > Serial Port and select your com10 port before uploading. Com10 will only be available in the list when your Arduino is connected to your computer via the USB cable.

Can you post your operating system and version if that is not the solution?
« Last Edit: May 16, 2010, 09:12:56 pm by TBAr » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi, ive managed to compile and upload to the board. However, there are a few leds lit but no movement whatsoever. The matrix is directly connected to the output pins as shown in the example with the mod board(or whatever its called). Any ideas? Heres the code with 2 additional interupt lines as highlighted.
#include <TimerOne.h>

/*
 * Conway's "Life"
 *
 * Adapted from the Life example
 * on the Processing.org site
 */



byte analogPin = 5;
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[SIZE][SIZE];
byte world[SIZE][SIZE][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);
 [glow]   // Establish an interrupt
  Timer1.initialize(100); // interrupt every 100 microseconds
  Timer1.attachInterrupt(display); // control will go to the display() function when the interrupt happens[/glow]



  // 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();
  


}

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 == smiley-cool {
    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
}[glow][glow][/glow][/glow]
« Last Edit: May 18, 2010, 08:46:03 am by Jason_lewis » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why do attach the interrupt handler in loop? Isn't that something that needs to be done only once, in setup? Or, are you detaching it somewhere that I didn't see?

One more question. Can you learn to post code properly, using the # button on the top row?
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS is right, the code that establishes the interrupt routine should go somewhere in setup(), as noted in reply #1. However, once the interrupt is established, re-establishing the same interrupt the same way over and over again inside loop() should not affect the rest of the logic or the display.
[edit]Hmmmm. Unless re-setting up an interrupt before it has a chance to fire keeps it from firing even the first time. So make the software change first -- move the highlighted lines of your code to the beginning of setup() -- and if things work after that you're all set, otherwise, continue with the rest of this reply.[/edit]

Quote
The matrix is directly connected to the output pins as shown in the example with the mod board(or whatever its called).
Your matrix may be wired incorrectly. Can you please provide
  • a link to the example you mentioned (I have no clue which example you're looking at)
  • a link to the data sheet for the LED matrix you have (it may be a different brand or model than the one in the example you are looking at)
  • a list of which of your Arduino pins is connected to which LED matrix pin, in the following form:
   Arduino digital pin 0 - no connection
    Arduino digital pin 1 - no connection
    Arduino digital pin 2 - LED matrix pin #__
    Arduino digital pin 3 - LED matrix pin #__
    Arduino digital pin 4 - LED matrix pin #__
    Arduino digital pin 5 - LED matrix pin #__
    etc.
(I will verify row/column attachments with the data sheet and the code)
[/list]
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi, the matrix is ok i m sure because ive run your test software that turns on one led at a time etc, its fine and so is the scrolling message one. ill try your suggestion of moving the interupt code but im clueless as to where exactly i should put it. do you mean pit it directly underneat the void setup () { line or above it? thanks. jay ;D ;D
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Move it directly underneath void setup () {
« Last Edit: May 20, 2010, 09:35:15 am by TBAr » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi, its working but there is a problem with the display now.It displays three columns more than the rest and when it finishes doing its thing like its supposed to it then displays them permenantly. Ive also tried the Hello one using timer one to see if that works. it does the same thing. like i said it works fine with your test software etc. my board is the duemeliova or something. The code was written for the deicimila. Any ideas? also i moved the code underneath void loop instead cos it didnt work under void setup. thanks
« Last Edit: May 20, 2010, 10:41:04 am by Jason_lewis » Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It displays [glow]three columns more than the rest[/glow] and when it finishes doing its thing like its supposed to it then displays them permenantly.
Well, you managed to completely lose me with that one.

Quote
like i said it works fine with your test software etc.
That's good. Except that I never posted any test software.

Quote
also i moved the code underneath void loop instead cos it didnt work under void setup.
So now it is working with the interrupt initialization in loop() when you reported in Reply #5 that it was not working with it there. At least it is working for you now.
« Last Edit: May 20, 2010, 11:53:09 am by TBAr » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi, ive done it at last. it was the pin definitions at the beginning. i made my own matrix so it was a simple matter of naming the row pins from 9-16, and the column pins from 1-8. any ideas on how to make this loopable when it stops. at the ,moment i have to do a hard reset?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi, i never meant you specifically. i meant the arduino people. sorry about the confusing post. i was confused too. i have never done anything like this before so its all very new to me. i appreciate your help non the less. thanks to you its working and i can now sleep. still the problem of making it loop though when the game of life cycle has ran its course. I have to hard reset at that point to run again. is there any way to do this in the software when the game of life comes to a point where it either repeats constantly, freezes with a few leds lit or clears the display totally. this would be a great help to me. thanks
Logged

0
Offline Offline
Full Member
***
Karma: 2
Posts: 156
It was all digital
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... or you could go by mechanical logic...




-Fletcher
Logged

Pages: [1]   Go Up
Jump to: