*Solved* Charlierplexie LEDs, Problem interfacing with the OpenHeart.

TL:DR - I’m having some issues trying to wrap my brain around how to build a visualization on an LED array using charlieplexing. I could use some help figuring out where my issues are.

I’ve had this OpenHeart for many years, but I’m just now getting around to putting it to some use. I’m having some issues getting it to interface with my arduino, and I’m not sure what is going on.

Here is the original code as provided by the designer.

This code doesn’t even compile for me. After a little bit of googling, I found that the likely culprit was the way the heart variable was assigned. So after a bit of fiddling I ended up changing this line:

byte heart[][27] PROGMEM ={

To this:

char heart[][27] ={

This lets it compile, but it still doesn’t run correctly. Even after changing the pinouts around to make things more obvious to me, it still doesn’t work. If I run the code posted below, I just get a single LED that lights up, LED22.

#include <avr/pgmspace.h>  //This is in the Arduino library

int pin1 = 2;
int pin2 = 3;
int pin3 = 4;
int pin4 = 5;
int pin5 = 6;
int pin6 = 7;

const int pins[] = {
  pin1,pin2,pin3,pin4,pin5,pin6};

const int heartpins[27][2] ={
  {pin3,pin1}, {pin1,pin3},              {pin2,pin1}, {pin1,pin2},
  {pin3,pin4}, {pin4,pin1}, {pin1,pin4}, {pin1,pin5}, {pin6,pin1}, {pin1,pin6}, {pin6,pin2},
  {pin4,pin3}, {pin3,pin5}, {pin5,pin3}, {pin5,pin1}, {pin2,pin5}, {pin5,pin2}, {pin2,pin6},
               {pin4,pin5}, {pin5,pin4}, {pin3,pin2}, {pin6,pin5}, {pin5,pin6}, 
                            {pin4,pin6}, {pin2,pin3}, {pin6,pin4},
                                         {pin4,pin2}
};

int blinkdelay = 200;   //This basically controls brightness. Lower is dimmer
int runspeed = 50;      //smaller = faster

char heart[][27] ={  // This stores the array in Flash ROM. You can easily have 500+ frames.


  //Blinks all on and off
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
  //Fills the heart up from the bottom
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1},
  {0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1},
  {0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1},
  {0,1,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

 //Parts fall off the bottom
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1},
  {1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,0},
  {1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1},
  {1,1,1,1,0,0,1,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,0},
  {0,1,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1},
  {0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,1,0,1,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},

  //Fills up from the center
  {0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0},
  {0,0,0,0,0,1,1,0,1,1,0,0,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,1},
  {1,1,1,1,1,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1},
  {1,1,1,1,1,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1},
 
  //Kill line
  {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};

 
void setup()
{
//  blinkall(2);  // useful for testing
}
 

void loop()
{
// sequenceon();  // useful for testing
  play();
}

 
void turnon(int led)
{
  int pospin = heartpins[led][0];
  int negpin = heartpins[led][1];
  pinMode (pospin, OUTPUT);
  pinMode (negpin, OUTPUT);
  digitalWrite (pospin, HIGH);
  digitalWrite (negpin, LOW);
}


void alloff()
{
  for(int i = 0; i < 6; i++)
  {
    pinMode (pins[i], INPUT);
  }
}



void play()
{
  boolean run = true;
  byte k;
  int t = 0;
  while(run == true)
  {
    for(int i = 0; i < runspeed; i++)
    {
      for(int j = 0; j < 27; j++)
      {
        k = pgm_read_byte(&(heart[t][j]));
        if (k == 2)
        {
          run = false;
        }
        else if(k == 1)
        {
          turnon(j);
          delayMicroseconds(blinkdelay);
          alloff();
        }
        else if(k == 0)
        {
          delayMicroseconds(blinkdelay);
        }
      }
    }
    t++;
  }
}


void blinkall(int numblink)
{
  alloff();
  for(int n = 0; n < numblink; n++)
  {
    for(int i = 0; i < runspeed; i++)
    {
      for(int j = 0; j < 27; j++)
      {
        turnon(j);
        delay(blinkdelay);
        alloff();
      }
    }
    delay(500);
  }
}

 
void sequenceon()
{
  for(int i = 0; i < 27; i++)
  {
    turnon(i);
    delay(800);   
    alloff();
    delay(800);   
  }
}

So I fiddled around even more, and finally got a piece of code that does something that makes sense. This piece of code just counts through the LEDs one at a time, in order. But even with this, I still haven’t been able to figure out how to get it to blink through the animations the original code contained.

#include <avr/pgmspace.h>  //This is in the Arduino library

int pin1 = 2;
int pin2 = 3;
int pin3 = 4;
int pin4 = 5;
int pin5 = 6;
int pin6 = 7;

const int pins[] = {
  pin1,pin2,pin3,pin4,pin5,pin6};

const int heartpins[27][2] ={
               {pin3,pin1}, {pin1,pin3},              {pin2,pin1}, {pin1,pin2},
  {pin3,pin4}, {pin4,pin1}, {pin1,pin4}, {pin1,pin5}, {pin6,pin1}, {pin1,pin6}, {pin6,pin2},
  {pin4,pin3}, {pin3,pin5}, {pin5,pin3}, {pin5,pin1}, {pin2,pin5}, {pin5,pin2}, {pin2,pin6},
               {pin4,pin5}, {pin5,pin4}, {pin3,pin2}, {pin6,pin5}, {pin5,pin6}, 
                            {pin4,pin6}, {pin2,pin3}, {pin6,pin4},
                                         {pin4,pin2}
};


int blinkdelay = 200;   //This basically controls brightness. Lower is dimmer
int runspeed = 500;      //smaller = faster

char heart[][27] ={  // This stores the array in Flash ROM. You can easily have 500+ frames.

  //Fills up from the center
  {0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0},
  {0,0,0,0,0,1,1,0,1,1,0,0,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,1},
  {1,1,1,1,1,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1},
  {1,1,1,1,1,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,1,0,1,1},

};

 
void setup()
{
//  blinkall(2);  // useful for testing
}
 

void loop()
{
 sequenceon();  // useful for testing
//  play();
}

 
void turnon(int led)
{
  int pospin = heartpins[led][0];
  int negpin = heartpins[led][1];
  pinMode (pospin, OUTPUT);
  pinMode (negpin, OUTPUT);
  digitalWrite (pospin, HIGH);
  digitalWrite (negpin, LOW);
}


void alloff()
{
  for(int i = 0; i < 6; i++)
  {
    pinMode (pins[i], INPUT);
  }
}



void play()
{
  boolean run = true;
  byte k;
  int t = 0;
  while(run == true)
  {
    for(int i = 0; i < runspeed; i++)
    {
      for(int j = 0; j < 27; j++)
      {
        k = pgm_read_byte(&(heart[t][j]));
        if (k == 2)
        {
          run = false;
        }
        else if(k == 1)
        {
          turnon(j);
          delayMicroseconds(blinkdelay);
          alloff();
        }
        else if(k == 0)
        {
          delayMicroseconds(blinkdelay);
        }
      }
    }
    t++;
  }
}


void blinkall(int numblink)
{
  alloff();
  for(int n = 0; n < numblink; n++)
  {
    for(int i = 0; i < runspeed; i++)
    {
      for(int j = 0; j < 27; j++)
      {
        turnon(j);
        delay(blinkdelay);
        alloff();
      }
    }
    delay(500);
  }
}

 
void sequenceon()
{
  for(int i = 0; i < 27; i++)
  {
    turnon(i);
    delay(800);   
    alloff();
    delay(800);   
  }
}

Does anyone have any ideas what I can try? I’m sure I could eventually figure out how to make these animations work, but I I’m really not sure where to begin to figure out how to store them while working with charlieplexing, this is all a bit new to me.

Charlieplexing works by starting with all the pins set to INPUT. This makes them look disconnected as far as the LEDs are concerned. Then one pin is set OUTPUT/HIGH and one is set OUTPUT/LOW. The one LED that has the anode (+) end connected to the HIGH pin and cathode (-) end connected to the LOW pin lights up. No significant current will flow through any of the other LEDs so they remain off.

To draw an image on the 27 LEDs you repeatedly blink each of the desired LEDs. As long as you can get through the list of LEDs to light in less than about 1/60th of a second the blinks blur together and the output appears steady.

sneasle:
Here is the original code as provided by the designer.

This code doesn't even compile for me.

The code compiles fine with Arduino IDE 1.0.5 for Windows.
So what's the problem?

For Arduiono versions 1.5.7 and above, which uses a newer version of the GCC compiler, you would have to declare all 'PROGMEM' variables explicitly as "const". But that cannot really be a big problem.

const byte heart[][27] PROGMEM ={  // This stores the array in Flash ROM. You can easily have 500+ frames.

So the code compiles fine without any changes and Arduino versions lower than 1.5.7.
And code compiles with very small changes with Arduino version 1.5.7 or above.

So what?

Thank you jurs, that little bit of extra wording was a giant help.

I am using 1.6, the way I interpreted the change needed made me replace byte with const, not add it in front. doh

johnwasser:
Charlieplexing works by starting with all the pins set to INPUT. This makes them look disconnected as far as the LEDs are concerned. Then one pin is set OUTPUT/HIGH and one is set OUTPUT/LOW. The one LED that has the anode (+) end connected to the HIGH pin and cathode (-) end connected to the LOW pin lights up. No significant current will flow through any of the other LEDs so they remain off.

To draw an image on the 27 LEDs you repeatedly blink each of the desired LEDs. As long as you can get through the list of LEDs to light in less than about 1/60th of a second the blinks blur together and the output appears steady.

The theory I get, what has me confused is how to best store that much information in a way that makes sense, and how to iterate through it in a way that would product the desired result. The code that floats in my head when I think of this is a mess of loops, there had to be a better way.

The original code has arrays of 27 characters each character representing one of the 27 LEDs and containing 1 (on) or 0 (off). Each array represents one frame of an animation. Each frame is displayed 'runSpeed' (500) times before moving on to the next frame. Just draw your frames, turn them into 1's and 0's and insert them into the code.

The last array starts with a 2 to act as an END OF FRAMES marker. You can do that or you can use a frame count.

johnwasser:
The original code has arrays of 27 characters each character representing one of the 27 LEDs and containing 1 (on) or 0 (off). Each array represents one frame of an animation. Each frame is displayed 'runSpeed' (500) times before moving on to the next frame. Just draw your frames, turn them into 1's and 0's and insert them into the code.

The last array starts with a 2 to act as an END OF FRAMES marker. You can do that or you can use a frame count.

My original comment on not understanding how to store the animations was when I was working on trying to build this from scratch as I couldn't get this code to compile.

While I don't understand fully how this code work, it is easy enough to manipulate to get the output I want.

Thanks guys for the help, I figured it would be something simple that I was missing!