0
Offline
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« on: May 12, 2010, 04:07:45 pm » |
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 int count = neighbours(x, y); if (count == 3 && world // A new cell is born world } if ((count < 2 || count > 3) && world // Cell dies world } } } // Copy next generation into place for (int x = 0; x < SIZE; x++) { for (int y = 0; y < SIZE; y++) { world } } }
int neighbours(int x, int y) { return world[(x + 1) % SIZE][y][0] + world 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 == { 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
Sr. Member
Karma: 0
Posts: 388
|
 |
« Reply #1 on: May 13, 2010, 09:23:19 am » |
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(). // 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
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #2 on: May 13, 2010, 03:50:34 pm » |
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
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #3 on: May 16, 2010, 03:06:30 am » |
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
Sr. Member
Karma: 0
Posts: 388
|
 |
« Reply #4 on: May 16, 2010, 09:11:35 pm » |
[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
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #5 on: May 18, 2010, 08:32:45 am » |
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 int count = neighbours(x, y); if (count == 3 && world // A new cell is born world } if ((count < 2 || count > 3) && world // Cell dies world } } } // Copy next generation into place for (int x = 0; x < SIZE; x++) { for (int y = 0; y < SIZE; y++) { world } } }
int neighbours(int x, int y) { return world[(x + 1) % SIZE][y][0] + world 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 == { 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
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #6 on: May 18, 2010, 09:46:58 am » |
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
Sr. Member
Karma: 0
Posts: 388
|
 |
« Reply #7 on: May 18, 2010, 11:02:25 pm » |
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] 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
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #8 on: May 19, 2010, 10:27:08 am » |
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
Sr. Member
Karma: 0
Posts: 388
|
 |
« Reply #9 on: May 20, 2010, 09:34:03 am » |
Move it directly underneath void setup () {
|
|
|
|
« Last Edit: May 20, 2010, 09:35:15 am by TBAr »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #10 on: May 20, 2010, 10:35:26 am » |
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
Sr. Member
Karma: 0
Posts: 388
|
 |
« Reply #11 on: May 20, 2010, 11:35:56 am » |
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. like i said it works fine with your test software etc. That's good. Except that I never posted any test software. 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
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #12 on: May 20, 2010, 12:57:17 pm » |
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
Newbie
Karma: 0
Posts: 11
Arduino rocks
|
 |
« Reply #13 on: May 21, 2010, 12:39:05 pm » |
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
Full Member
Karma: 1
Posts: 150
It was all digital
|
 |
« Reply #14 on: May 24, 2010, 04:51:13 am » |
|
|
|
|
|
Logged
|
|
|
|
|
|