Charlieplexing code

I'm working on a project and I want to use two "wheels" of LEDs to create a sort of light show. I've successfully wired it up right and even figured out how to write the code in order to make a few different patterns. You can see a youtube video of what I have so far here:

My problem is that the code I'm using is very bulky. To do the two simple patterns you see in the video I use up 19286 bytes of memory. I still want to add a potentiometer to control the speed and a button, or several buttons, to change between patterns. I'm VERY new to the Arduino and programming so I'm sure I'm doing things the hard way. My problem is all the other charlieplexing code I've seen around the web is way above my head. It just doesn't make sense to me...

Here is part of the code for the patterns you see in the video. I'm not going to include the whole thing because I'm sure you'll get the idea pretty quickly.

int ledPin1 = 7;
int ledPin2 = 6;
int ledPin3 = 5;
int ledPin4 = 4;
int ledPin5 = 3;
int ledPin6 = 2;
int ledPinF = 8;
int ledPinE = 9;
int ledPinD = 10;
int ledPinC = 11;
int ledPinB = 12;
int ledPinA = 13;

void setup() {
}

void loop() {
  
  int a;
  for(a = 0;a < 14; a++ )
  {
    /* Bottom center LED 1*/
    pinMode(ledPin1, OUTPUT);
    pinMode(ledPin2, OUTPUT);
    pinMode(ledPin3, INPUT);
    pinMode(ledPin4, INPUT);
    pinMode(ledPin5, INPUT);
    pinMode(ledPin6, INPUT);
    pinMode(ledPinA, OUTPUT);
    pinMode(ledPinB, OUTPUT);
    pinMode(ledPinC, INPUT);
    pinMode(ledPinD, INPUT);
    pinMode(ledPinE, INPUT);
    pinMode(ledPinF, INPUT);
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, LOW);
    digitalWrite(ledPinA, HIGH);
    digitalWrite(ledPinB, LOW);
    delay(.5);
    
    /* Top center LED 16*/
    pinMode(ledPin1, INPUT);
    pinMode(ledPin2, INPUT);
    pinMode(ledPin3, OUTPUT);
    pinMode(ledPin4, INPUT);
    pinMode(ledPin5, OUTPUT);
    pinMode(ledPin6, INPUT);
    pinMode(ledPinA, INPUT);
    pinMode(ledPinB, INPUT);
    pinMode(ledPinC, OUTPUT);
    pinMode(ledPinD, INPUT);
    pinMode(ledPinE, OUTPUT);
    pinMode(ledPinF, INPUT);
    digitalWrite(ledPin5, HIGH);
    digitalWrite(ledPin3, LOW);
    digitalWrite(ledPinE, HIGH);
    digitalWrite(ledPinC, LOW);
    delay(.5);  
  
   /* LED 15*/
    pinMode(ledPin1, INPUT);
    pinMode(ledPin2, INPUT);
    pinMode(ledPin3, OUTPUT);
    pinMode(ledPin4, INPUT);
    pinMode(ledPin5, OUTPUT);
    pinMode(ledPin6, INPUT);
    pinMode(ledPinA, INPUT);
    pinMode(ledPinB, INPUT);
    pinMode(ledPinC, OUTPUT);
    pinMode(ledPinD, INPUT);
    pinMode(ledPinE, OUTPUT);
    pinMode(ledPinF, INPUT);
    digitalWrite(ledPin3, HIGH);
    digitalWrite(ledPin5, LOW);
    digitalWrite(ledPinC, HIGH);
    digitalWrite(ledPinE, LOW);
    delay(.5);
    
    /* LED 17*/
    pinMode(ledPin1, INPUT);
    pinMode(ledPin2, INPUT);
    pinMode(ledPin3, INPUT);
    pinMode(ledPin4, OUTPUT);
    pinMode(ledPin5, INPUT);
    pinMode(ledPin6, OUTPUT);
    pinMode(ledPinA, INPUT);
    pinMode(ledPinB, INPUT);
    pinMode(ledPinC, INPUT);
    pinMode(ledPinD, OUTPUT);
    pinMode(ledPinE, INPUT);
    pinMode(ledPinF, OUTPUT);
    digitalWrite(ledPin4, HIGH);
    digitalWrite(ledPin6, LOW);
    digitalWrite(ledPinD, HIGH);
    digitalWrite(ledPinF, LOW);
    delay(.5);
  }

Moderator edit: removed scrollathon. AWOL

Now I know I could set all pins to output in the void setup() { } and then set the pins I need to input in each "frame" but I don't know if that'll cut the size of the program down all that much. I tried setting all the pins to input in the void setup() {} so that I could set the pins I needed to output in each "frame" but that didn't work...

I looked at the tutorial for creating libraries. I was thinking about trying to creating a library of 60 functions that I could use to turn on and off each LED as needed but will that actually save me any memory?

There must be a better way to do this. Can anyone make a suggestion?

In the use of the potentiometer. Can you use a variable with delay()?

I tried to use:

int potPin = 2;
int ledDelay;

(then in the void loop)
ledDelay = analogRead(potPin);

(and later in the code)
delay(ledDelay);

I wasn't sure if it worked or not. It seemed to work at times and then didn't. I think my pot may not have been good. I'm not sure of the values of the pot that came with my Arduino experimenters kit. I tried buying a new one at Radio Shack but they didn't have much to choose from. I wound up with a 100K Ohm Linear taper pot at 250VDC, .25W. The pot does nothing now. I didn't realize the 250VDC until this very second when I checked the specs to write this post. I tried to find a 10k ohm or a 4.7k ohm pot that I've seen used in several Arduino circuits but I'm having trouble finding one... Is it my code or my pot? Or maybe both?

As I said I'm very new to all this so please forgive me if some of my questions seem obvious...

Thanks.

I'm not going to include the whole thing because I'm sure you'll get the idea pretty quickly.

Maybe arrays would make your code smaller.
Posting it using the # icon on the post editor's toolbar would make it easier to read.

Use arrays, and try using direct port manipulation for the pin direction and the state. If you use two of the arduino's almost-complete ports, you will be able to accomplish what you do in 16 lines in 4 lines. http://www.arduino.cc/en/Hacking/PinMapping and Arduino Reference - Arduino Reference will be very useful

And also, great work! That looks really great and is impressive, especially for being new to the arduino.

Good luck

wow, this looks like a really fun project. I'm really confused by your code.

how may led do you have?
how are the leds set up?
why are you setting the pins to inputs? edit: wasn't thinking.

I think my code for another project won't be two hard to adapt to this situation

http://www.silvercg.com/2011/02/09/arduino-winamp-vu-meter/

but it has it's limitations. I'll let this project boil in my brain for a little bit because I'm not sure what you could do.

for right now I would put the potentiometer off to the side while you get the basic functionality down.. I sure you will need to rewrite everything and i would also suggest learning how to use millis instead of delay. this will make things easier with the potentiometer later.

ok i've never charlieplexed before... I have now added it to my list.

but how i would attack this is the same way as in the like a posted above.

I would do two arrays, one for input or output, and the other for which led to turn on.
I'm sure there may be an better way by just saying which led should be on, and based on the location of the led set this output or input.

int pins = {1,1,1,0,1,1,0,1,1}; // 1 is on and 0 is off
for (int a = 0; a < 9; a++){
if (pins[a] == 1){
set pin of a to input 
}
else {
this pin of a to output
}

repeat the same process for the leds. then make sure to sync them with the output/input settings correctly.

like i said I haven't done any charlieplexing before, so I'm just giving my two cents on how I would attack this. I'm sure there may be a better way.

I'm interested to see what others come up with.

cheers,
Dave.

@Bilbo Thanks :slight_smile: I'll work on port manipulation. The bitmath stuff is starting to hurt my head though :-}

@SilverCG What I have here is two groups of 30 charliplexed LEDS. The first group consists of pins 2 - 7 and the second are pins 8 - 13. I didn't give you the whole programs because I'm writing everything out long hand, so to speak, so the code is a bit lengthy. What this:

    /* Bottom center LED 1*/
    pinMode(ledPin1, OUTPUT);
    pinMode(ledPin2, OUTPUT);
    pinMode(ledPin3, INPUT);
    pinMode(ledPin4, INPUT);
    pinMode(ledPin5, INPUT);
    pinMode(ledPin6, INPUT);
    pinMode(ledPinA, OUTPUT);
    pinMode(ledPinB, OUTPUT);
    pinMode(ledPinC, INPUT);
    pinMode(ledPinD, INPUT);
    pinMode(ledPinE, INPUT);
    pinMode(ledPinF, INPUT);
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, LOW);
    digitalWrite(ledPinA, HIGH);
    digitalWrite(ledPinB, LOW);

basically does is set the pins I need to light up the LEDs to output and all the rest to input. Then the next block of code resets all the pins to the inputs and outputs I need to light the next LED. The pins that are numbered, in the digitalWrite statements, are for the wheel on the right. The digitalWrite statements that are lettered are for the wheel on the left.

This code does work, it's just kind of bulky. I'd like to get several patterns into this as well as be able to vary speed and direction of those patterns.

ya, i've been researching it for the past hour and understand what your saying now... I'm actually digging through my parts bin trying to figure out how many led's I have so i can build a 9x9...

like i said I haven't charlieplexed before, only multiplexed. so charlieplexing will be my project for the week.

however I'm really not looking forward to soldering 81 led's :stuck_out_tongue_closed_eyes:

All that soldering can be tedious. Believe me I know.

A tip to make your life easier. Have a battery and a resistor on hand to test each connection after you make it. If you accidentally solder an LED in the wrong way or connect it up to the wrong pins it is a HUGE pain to try and track down the mistake after the whole thing is soldered up.

Check each set of LEDs after you've hooked them up. Also try and hook them up in some kind of logical order. It makes figuring out a mistake easier as well. Then again if you're going to do a cube (something that I want to try as well) it might be different...

Check out this tutorial:

There's even some code examples at the end. After reading some of the suggestions here some of the code they wrote makes a little more sense to me but it's still way over my head. If their code makes sense to you or anyone else I'd love a more detailed explanation of it!

He bread boarded his example though and it's nothing but a mess of wires to me. I can't even figure out how you'd set up a charlieplex matrix with 20 LEDs on such a small breadboard. After trying to figure that out I can see why he wasn't so keen on charlieplexing...

I don't know if you can see from my video or not but to make it easier to set up I just drilled holes in a board and strung wires across the holes. Six wires for six pins. Then I just soldered the LEDs in place where they needed to be. Basically I recreated this:

There are also some charliplexed cube tutorials for the Arduino on http://www.instructables.com/ I haven't done more than glance at them though so I can't tell you how good they are...

Have you seen the animations in this cube? Night Works 3d LED CUBE - YouTube

AWESOME! I can't imagine the nightmare it must be to program though... Still awfully cool!

So, Ardor, how is your Charlieplexing project coming along?

I have to admit that it's kind of stalled out at the moment. I can't get the code to work like I want, I'm getting leds that light up when I don't want and I've still yet to figure out how to code some features that I want...

I put the whole thing on hold for now. I may come back to it later though...

delay(.5) does not pause for 500us

I'm working on Charlieplexing 42 LEDs on 7 pins. I may start another thread, though.

I think using direct PortManipulation is going to be key, along with a different way that I've redrawn the circuit.