Saturday, September 23, 2017

Chalieplexing 2

This is the seond tutorial on Charlieplexing.
In the first story, which you can find by clicking here, I told you why Charlieplexing is such a wonderfull technique and how to do the wiring.

This chapter is going to delve deeper into the software.

So let us first look again at the wiring. Here is the setup for using 5 pins to adress 20 leds.



I am using an Attiny85 here because an Arduino would be overkill. You can however substitute the Attiny85 with an Arduino as the code stays the same. Only thing you will have to do is to substitute the right pinnumbers in the program.

The previous story told you how to adress a single led. Lets resume that here.

We start with putting all pins of the Arduino (or Tiny) in 3-state mode to make sure no leds are on:

int led1 = 0; // pen PWM0
int led2 = 1; // pen PWM1
int led3 = 2; // pen ADC1
int led4 = 3; // pen ADC3
int led5 = 4; // pen ADC2
pinMode(led1, INPUT)
pinMode(led2, INPUT);
pinMode(led3, INPUT);pinMode(led4, INPUT);
pinMode(led5, INPUT);


Now to put on led number 13 you adress it as follows:

pinMode (led2, OUTPUT);
digitalWrite (led2, HIGH);
pinMode (led5, OUTPUT);
digitalWrite (led5, LOW);


This way we can adress all leds individually. However it takes a lot of coding (as you saw in the previous story) and that is prone to errors. So we need to find an easier way.

Best thing to do is to put all led wiring in an array. Then we just need to access the array index to have all data present. Sounds more difficult as it is.

Lets start with defining an array with 20 entries, one for each led, and 2 elements per entry for each pin per led. So the array would look like this:

const int ledpins[20][2] ={
  // this array contains the pins per led
  // edit the pin numbers to your own wiring
  {1,0},
  {0,1},
  {2,0},
  {0,2},
  {3,0},
  {0,3},
  {4,0},
  {0,4},
  {2,1},
  {1,2},
  {3,1},
  {1,3} ,
  {4,1},
  {1,4},
  {3,2},
  {2,3},
  {4,2},
  {2,4},
  {4,3},
  {3,4}
};


So how does this work. Lets start easy. Led number 1 is attached to pins 1 and 0 just like it is punt in the array:

{1,0}. Led number two is wired the other way round and you can find that in the array to: {0,1}. Well let us now look at led number 12. In the wiring schematic you can see it is attached to Arduino pin number 1 and pin number 3. And that is exactly what you will find in the array entrance number 12 being {1,3}.
Lets take another example. Led number 17 is attached to pins 4 and 2 just like array entrance number 17 describes

{4,2}

That is easy isn't it. The array just describes how the pins are wired.

In your code always start with putting all leds off:

void alloff()
// this puts all leds off
{
  for(int i = 0; i < 5; i++)
  {
    pinMode (pins[i], INPUT);
  }
}


That is easy. Just like in the previous story. We set all pins in the INPUT mode so they are in tri-state which turns all leds off.

Next step is to make a function that turns a certain led ON.

void ledon(int lednr)
// choose a led from the array on put it ON
{

  pinMode (ledpins[lednr][0], OUTPUT);
  digitalWrite (ledpins[lednr][0], HIGH);

  pinMode (ledpins[lednr][1], OUTPUT);
  digitalWrite (ledpins[lednr][1], LOW);
  delay(slowdown2);

}


That's all that is to it.

Now if you want to put LED 13 ON for a certain amount of time (determined by the variable slowdown2)you just have to use the next code:

ledon(13);
alloff();


Now lets make a loop in which we put all leds (one by one) on

  for(k=0; k<10; k++)
    {
    ledon(k);
    delay(1000);
    alloff();
     }


The complete code would look like this:

// Charlieplexing on an Attiny 85
// Code by Luc Volders 2014

int pins[] = {0,1,2,3,4};
int i;
int j;
int k;
int slowdown2 = 2; // this delay should have a lower value when using less leds.
                              // for example 4 when using 12 leds
long int start=0;
long int eind=0;

const int ledpins[20][2] ={
  // this array contains the pins per led
  // edit the pin numbers to your own wiring
  {1,0},
  {0,1},
  {2,0},
  {0,2},
  {3,0},
  {0,3},
  {4,0},
  {0,4},
  {2,1},
  {1,2},
  {3,1},
  {1,3} ,
  {4,1},
  {1,4},
  {3,2},
  {2,3},
  {4,2},
  {2,4},
  {4,3},
  {3,4}
};

void setup()
{
  // start with putiing all leds off
  alloff();
}

void loop()
{

  for(k=0; k<10; k++)
    {
    ledon(k);
    delay(1000);
    alloff();
    }
}

void alloff()
// this shuts down all leds
{
  for(int i = 0; i < 5; i++)
  {
    pinMode (pins[i], INPUT);
  }
}

void ledon(int lednr)
// choose a led from the array on put it ON
{

  pinMode (ledpins[lednr][0], OUTPUT);
  digitalWrite (ledpins[lednr][0], HIGH);

  pinMode (ledpins[lednr][1], OUTPUT);
  digitalWrite (ledpins[lednr][1], LOW);
  delay(slowdown2);

}



And this makes programming the individual leds a lot easier and a lot less prone to errors.

I describe here the version for 20 leds but it can easily be adapted to 12 leds by just using pin numbers 0 to 3 and limiting the array to 12 items. That would give you an extra pin for attaching a button or sensor.

Nice all this theory. But what can you do with this.
The next episode shows you how to make a Larson scanner.

So till next time
have fun

Luc Volders