Pages: [1]   Go Down
Author Topic: Arduino locking up while controlling LEDs... memory leak?  (Read 761 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm working on an interactive/arts project for an upcoming variety show, which will allow an audience member to control effects being displayed on an LED array made from the addressable RGB LED strips available from Sparkfun (http://www.sparkfun.com/products/10312).

The problem is, my sketch will run for 10-20 seconds, then the whole LED array will turn red and then the Arduino either locks up and becomes unresponsive or it resets itself.  I've ruled out problems with the SPI library I'm using, as the sample effects that came with it work fine and I hit the same problem with alternate SPI libraries/methods.  So I'm starting to think I might be maxing out the available memory or that there's a leak somewhere, but I can't see where if that's what's happening.

Here's a simplified version of the sketch that doesn't use any external library but exhibits the behavior I've described:

Code:
int SDI = 2;
int CKI = 3;
int ledPin = 13; //On board LED

#define STRIP_LENGTH 64
long strip_colors[STRIP_LENGTH];

long cellColors[8][8];
int tempo = 500;

void setup() {
  pinMode(SDI, OUTPUT);
  pinMode(CKI, OUTPUT);
  pinMode(ledPin, OUTPUT);
 
  //Clear out the arrays
  for(int x = 0 ; x < STRIP_LENGTH ; x++)
    strip_colors[x] = 0;
 
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      cellColors[i][j] = 0;
    }
  }
   
  randomSeed(analogRead(0));
}

void setCell(int x, int y, long color) {
  cellColors[x][y] = color;
  strip_colors[(x*8)+(7-y)] = color;
}

// from Sparkfun example code
long randomColor() {
  long new_color = 0;
  for(int x = 0; x < 3; x++){
    new_color <<= 8;
    new_color |= random(0xFF); //Give me a number from 0 to 0xFF
  }
 
  return new_color;
}

void shiftRows() {
  long newColor = randomColor();
 
  for (int y = 0; y < 7; y++) {
    for (int x = 0; x < 8; x++) {
      setCell(x, y, cellColors[x][y+1]);
    }
  }
  for (int x = 0; x < 8; x++) {
    setCell(x, 7, newColor);
  }
  post_frame();
}

void loop() {
  volatile int state = LOW;
 
  while(1){
    state = !state;
    digitalWrite(ledPin, state);
   
    shiftRows();
    delay(tempo);
  }
}

//Takes the current strip color array and pushes it out (from Sparkfun example code)
void post_frame (void) {
  //Each LED requires 24 bits of data
  //MSB: R7, R6, R5..., G7, G6..., B7, B6... B0
  //Once the 24 bits have been delivered, the IC immediately relays these bits to its neighbor
  //Pulling the clock low for 500us or more causes the IC to post the data.
  long this_led_color;
  long mask;

  for(int LED_number = 0 ; LED_number < STRIP_LENGTH ; LED_number++) {
    this_led_color = strip_colors[LED_number]; //24 bits of color data

    for(byte color_bit = 23 ; color_bit != 255 ; color_bit--) {
      //Feed color bit 23 first (red data MSB)
     
      digitalWrite(CKI, LOW); //Only change data when clock is low
     
      mask = 1L << color_bit;
      //The 1'L' forces the 1 to start as a 32 bit number, otherwise it defaults to 16-bit.
     
      if(this_led_color & mask)
        digitalWrite(SDI, HIGH);
      else
        digitalWrite(SDI, LOW);
 
      digitalWrite(CKI, HIGH); //Data is latched when clock goes high
    }
  }

  //Pull clock low to put strip into reset/post mode
  digitalWrite(CKI, LOW);
  delayMicroseconds(500); //Wait for 500us to go into reset
}

The reason for the abstraction of the grid is to allow various effects to be implemented at a higher level (with simple x,y coordinates in a single orientation), which can then be transformed (e.g. rotated) at a lower level (controlled by user-operated buttons or a joystick).  I've excluded that functionality from this simplification, since it still locks up without that.

Could the arrays be maxing out the memory on my Arduino Uno?  4 bytes * 64 * 2 = 512 bytes, which seems well within range of the 2kb I read about somewhere.

Is there any memory leak here that I'm missing?  Given that the program seems to run fine initially, shifting rows one by one until it locks up (as though it hit some sort of threshold), I'm wondering if I'm not cleaning something up properly.

I would appreciate any insights! Thanks!
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 544
Posts: 27352
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

So you've got

long strip_colors[STRIP_LENGTH];
to create an array with 4 bytes at each location
So 256 bytes with STRIP_LENGTH  = 64

Then the same here
long cellColors[8][8];
so 4 bytes each at 8x8 locations for another 256

then another couple dozen for the various int and long variables.
Seems like it'd be okay for variable use as you indicated.
Don't know what the compiler is assigning.  
Have you tried Freemem() or whatever that command is to see how much the IDE says is available?





Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 495
Posts: 19026
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Running your code on my Uno (however without anything connected to it) it does not appear to lock up. Also a debugging display in setup is only shown once.

I suspect an electrical problem, you are possibly trying to drive too much, overheating the processor, and it resets.
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 544
Posts: 27352
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Technical Parameter
Current
 1.8A

Yeah, could be overheating the regulator, going into thermal shutdown.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

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

This is cute:
Code:
void loop() {
  volatile int state = LOW;
 
  while(1){
    state = !state;
    digitalWrite(ledPin, state);
   
    shiftRows();
    delay(tempo);
  }
}
An infinite loop inside an infinite loop.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I should have caught the current requirements.  I guess I assumed that since other effects were working fine across all 64 LEDs that must mean it's a software problem.  But those effects didn't have all 64 LEDs constantly lit either, and they did exhibit some strange behavior when I switched from USB power to a separate (9V, 3A) power supply.  So that's probably it.

My power supply can be switched to 5V, 4A, but the Arduino won't run on that will it?  If I run the Arduino off a USB or 9V supply, then run the SPI pins through an optoisolator and power the LEDs with the 5V supply, that should work, right?

Re: the infinite loops, hey, I've just been trying to get the damn thing to work. smiley-wink
Logged

Fort Lauderdale, FL
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6144
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
My power supply can be switched to 5V, 4A
If you connect to the 5V pin, yes that will work.  However, you have to question how much current you want running through the Arduino board itself.  Personally, if my project needs more than 500mA I separate out the supplies.
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.c

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I've got what I think is the right circuit for isolating the Arduino from the LEDs, but now I'm getting to the edge of my electronics experience.  I've got my CKI and SDI pins connected to separate optoisolator channels (I'm using a PS2501 from http://www.sparkfun.com/products/784) with in series resistors.  I think that part is right, but I'm not sure how to wire the other side.  The phototransistors in the optoisolator can't handle much current, so I'm guessing I'll need a couple regular transistors in the mix.  Am I on the right track?  If so how do I wire those in? 

Attached is what I've tried so far with no luck.  The transistors are 2N2222.  The WS2801 represents the entire 64 LED strip.

Even if that's how to go about the wiring, are the SPI signals going to translate through the optoisolator appropriately?  Will it be able to keep up?

If not, is there another way to separate power supplies?

Thanks for your help!


* ArcadeLights_bb_sm.png (41.53 KB, 704x453 - viewed 7 times.)

* ArcadeLights_schem_sm.png (72.59 KB, 1154x812 - viewed 11 times.)
* ArcadeLights.fzz (25.71 KB - downloaded 2 times.)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 495
Posts: 19026
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't see why you have to opto-isolate, and in any case the PS2501 is far too slow to switch (depending on your data rate I suppose). According to the datasheet it will switch in about 8 uS (3 rise + 5 fall).

Looking at this screenshot from my logic analyzer:



It won't be fast enough IMHO. Maybe the more experienced circuit guys will disagree.

I don't see why you can't just throw the optoisolator out the window, and simply power your WS2801 from your high-current source. And then just connect the grounds together, and CKI/SDI from the Arduino (no isolators).

Subject to what the electronics experts say, but it seems to me that should work.

Warning: programming is my stronger suit, not electronics. Better get someone else to confirm what I am saying.
Logged


nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8583
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there any particular reason to isolate the circuit? That seems like a lot of work to drive a chip.

That opto is very slow, even bit-banging as you are you could be too fast. One way to find out is to add a few delayMicros() in the shift routine.

Why are you bit banging anyway, you can use SPI or shifhOut().

You're driving Q1 and Q2 with no base resistors, that's not very kosher. Why do you need them?

______
Rob

 
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks guys, I think it's going to work without the optoisolator like you suggested.  I'm a software guy as well, so this is a brave new world for me.

Re: the bit banging, that was just example code to illustrate what I thought was a memory leak.  I have a couple SPI libraries I'm working with, at least one of which seems to be working now with my revised and simplified circuit.  No more lockups!
Logged

Pages: [1]   Go Up
Jump to: