Pages: [1]   Go Down
Author Topic: Trying to scan rows with port manipulation MEGA256  (Read 939 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all! I am learning and trying my best to find out how to efficiently scan rows on and off for a large matrix, 8 x 96 LED's.

For some reason I cannot for the life of me get any port bit manipulation working, I've tried every port to no avail. Any suggestions?

Code:
/* Beginings of LED matrix  controlled by arduino mega 2560*/
#include "avr/io.h"
#include "avr/pgmspace.h"
#include "avr/interrupt.h"

/*******************************************************************************
************************** Global Variables ************************************
*******************************************************************************/
volatile uint8_t Row;                        //  DO NOT MODIFY!

/*********************************************************************************
************************ Port Settings *******************************************
*********************************************************************************/



//ROW SCANNER INTERRUPT SERVICE ROUTINE
ISR(TIMER1_OVF_vect) {
  cli();
  TCNT1=0xFD62; // set initial value to remove time error (16bit counter register) FBEF=60?
  Row++;
  if (Row == 8)
              Row = 0; // fixes overlap of transferByte counter
  if (Row == 0)
              PORTD = B10000000; // Turns on row 1
  if (Row == 1)
              PORTD = B01000000; // Turns on row 2
  if (Row == 2)
              PORTD = B00100000; // Turns on row 3
  if (Row == 3)
              PORTD = B00010000; // Turns on row 4
  if (Row == 4)
              PORTD = B00001000; // Turns on row 5
  if (Row == 5)
              PORTD = B00000100; // Turns on row 6
  if (Row == 6)
              PORTD = B00000010; // Turns on row 7
  if (Row == 7)
              PORTD = B00000001; // Turns on row 8  
sei();
}


void setup()
{
  DDRD = B11111111; // sets Arduino pins 0-7 as outputs
  Row = 0; //Preparing volatiles
  TIMSK1=0x01; // enabled global and timer overflow interrupt;
  TCCR1A = 0x00; // normal operation page 148 (mode0);
  TCNT1=0xFD62; // set initial value to remove time error (16bit counter register)
  TCCR1B = 0x04; // start timer/ set clock
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);

}
int main()
{
 setup();
 
  
}

void loop()
{
  
  digitalWrite(11, LOW);  //SET OUTPUT ENABLE ON
  digitalWrite(10, HIGH);   // set Strobe/Latch LOW
  digitalWrite(8, HIGH);   // set clock LOW
  digitalWrite(9, HIGH);   // set the data output high
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
  digitalWrite(9, LOW);   // set the data output
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
}
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
// [glow]Use less-then and greater-then so your future self (or anyone else using your code) knows that these are system headers...[/glow]

#include [glow]<[/glow]avr/io.h[glow]>[/glow]

...

//ROW SCANNER INTERRUPT SERVICE ROUTINE
ISR(TIMER1_OVF_vect) {
// [glow]Remove the following line.  Enabling / disabling interrupts in an interrupt service routine is a bad idea.[/glow]
//  cli();
...
// [glow]Remove the following line.  Enabling / disabling interrupts in an interrupt service routine is a bad idea.[/glow]
//sei();
}


// [glow]The pins should be configured before enabling the timer...[/glow]

void setup()
{
  DDRD = B11111111; // sets Arduino pins 0-7 as outputs
  Row = 0; //Preparing volatiles
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
[glow]
  TIMSK1=0x01; // enabled global and timer overflow interrupt;
  TCCR1A = 0x00; // normal operation page 148 (mode0);
  TCNT1=0xFD62; // set initial value to remove time error (16bit counter register)
  TCCR1B = 0x04; // start timer/ set clock
[/glow]
}

// [glow]Completely remove main...[/glow]

/*
int main()
{
 setup();
}
*/
Logged

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

Code:
 if (Row == 0)
              PORTD = B10000000; // Turns on row 1
  if (Row == 1)
              PORTD = B01000000; // Turns on row 2
  if (Row == 2)
              PORTD = B00100000; // Turns on row 3
  if (Row == 3)
              PORTD = B00010000; // Turns on row 4
  if (Row == 4)
              PORTD = B00001000; // Turns on row 5
  if (Row == 5)
              PORTD = B00000100; // Turns on row 6
  if (Row == 6)
              PORTD = B00000010; // Turns on row 7
  if (Row == 7)
              PORTD = B00000001; // Turns on row 8
How many of these if statements can be true on any one execution of the function? As written, each statement needs to be evaluated. If you change this to if/else if/else if/.../else, then when the first one evaluates to true, the rest can be skipped.

Since you are doing direct port manipulation, in an ISR, presumably speed is important. Wasting time evaluating 7 if statements is not in keeping with the speed theme.
Logged

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

Thanks for the advice everyone. I was curious why some tutorials in the arduino library show "" and some show <> for the system headers.

Please forgive my crummy code, as I am just now converting over from propeller basic stamps.  

PaulS, Yes you are correct about my wasting of those commands, but at the time, and still possibly now, I couldn't even get port manipulation working so I threw in some random code to do the switching.

Basically the port manipulation is to turn on one pin, then turn it off and turn on the next pin, and do this in a loop one change per ISR call, effectively creating a common cathode duty cycle of 12.5% per pin. Those pins are connected to n-mosfets.

I would love to learn a better way than if-then statements, in fact I will likely be Forced to in order to keep the program running fast. Would you suggest a better way? or point me in the right direction? I am good at searching, but alas searching returns bad coders and good coders, I have yet to be that good at knowing what I'm looking at.
Logged

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

Quote
I would love to learn a better way than if-then statements, in fact I will likely be Forced to in order to keep the program running fast.
If you look at the value you are setting PORTD to, you see that there is an inverse relationship between the value and the value in Row. You could do this
Code:
byte portdVal = 0;
bitSet(portdVal, (8-Row));
PORTD = portdVal;
and skip all the if tests.

You could even learn about bit shifting, and combine all three statements into one.
« Last Edit: December 23, 2010, 09:46:32 am by PaulS » Logged

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

That code makes sense, but from what I can tell, it does not clear the previous bits. Bit shifting is exactly what I want to do! I'm going to work on that now!

thanks PaulS!
Logged

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

Quote
but from what I can tell, it does not clear the previous bits.
Code:
byte portdVal = 0;
I do believe that this just set all 8 bits to 0. But, I could be mistaken. smiley
Logged

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

ARR! you are right, I was thinking maybe that was NOT in the ISR but the setup area, but you put it there just for that purpose! Good job, lol.

Hey on bitshifting, I would eventually have to reset the variable from 00000000 to 10000000 once the 1 has been shifted off the byte. This would mean having an if-then statement of some sort to check and fix the byte. Would I be faster to use the port manipulation without any logic checking?

here's what I noticed using bitshifting:

Code:
/* Beginings of LED matrix  controlled by arduino mega 2560*/
#include <avr/IO.h>
#include <avr/pgmspace.h>
#include <avr/Interrupt.h>
#include <SPI.h>
/*******************************************************************************
************************** Global Variables ************************************
*******************************************************************************/
volatile byte Row;      //  Volatiles - Variables that can jump into ISRs!

/*********************************************************************************
************************ Port Settings *******************************************
*********************************************************************************/



//ROW SCANNER INTERRUPT SERVICE ROUTINE
ISR(TIMER1_OVF_vect) {
  TCNT1=0xFD62; // set initial value to remove time error (16bit counter register) FBEF=60?
  Row = Row << 1; //shifts the row that is one over 1 bit, 00000001 to 00000010 and so on
  if (Row==0) {
        Row = B00000001;   //Checks for Row = 00000000 then starts at row 00000001 again
                }
  PORTD = Row;  //Puts all port D to output based on Row Byte

  
}


void setup()
{
  DDRD = B11111111; // sets Arduino pins 0-7 as outputs
  Row = B00000001; //Preparing volatiles
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  TIMSK1=0x01; // enabled global and timer overflow interrupt;
  TCCR1A = 0x00; // normal operation page 148 (mode0);
  TCNT1=0xFD62; // set initial value to remove time error (16bit counter register)
  TCCR1B = 0x04; // start timer/ set clock


}
void loop()
{
  digitalWrite(11, LOW);  //SET OUTPUT ENABLE ON
  digitalWrite(10, HIGH);   // set Strobe/Latch LOW
  digitalWrite(8, HIGH);   // set clock LOW
  digitalWrite(9, HIGH);   // set the data output high
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
  digitalWrite(9, LOW);   // set the data output
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
  digitalWrite(8, LOW);   // set clock LOW
  digitalWrite(8, HIGH);   // set the clock HIGH
  delay(200);              // wait for a second
}


AWSOME! I got it working, One problem solved of many to come! lol, now I need to get this thing refreshing faster, currently it is flickering horribly, mainly because it was set to do 60hz and 50% duty cycle on a single row, but I just added 7 rows to the 60hz refresh ISR, leaving each individual row at like 10hz refresh rate and 12.5% duty cycle....

I'll be back...

If you have any other optimization suggestions I would gladly accept your advice and compare.
« Last Edit: December 23, 2010, 10:16:08 am by deuplonicus » Logged

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

hey I thought I would show you a little bit of what I've got. here's a picture of this thing in action. Now what perplexes me is those green LEDs you see turned on off to the left of the picture.




Those green LEDs as well as just about all the green LEDs turn on dimly whenever the columns switch, what is perplexing is that at the moment, those dimly lit LEDs only have a ground, their positive anode columns are currently NOT connected to anything those LEDS simply have a ground and are connected to 12" lengths of wire for the columns (anodes). Any ideas what would cause this?

Logged

Pages: [1]   Go Up
Jump to: