Can you run an LED with analog pins?

Hi
I am creating a matrix of 160 LED running with Charlieplexing. With digital pins I can run a limited amount of LED (137 LED)

I would like to know if I can use the analog inputs as digital inputs so I can run more LED's. I know arduino has a built in Analog to digital converter, however I can't turn an LED connecting it to a analog pin.

I am sure it's a very simple question and if any of you have an example or an advice, I would really appreciate it.

thanks

Analog inputs 0 - 5 can be used as digital pins 14 - 19.

Can you charlieplex so many LEDs? I would think the duty cycle of each LED would be too short.

Thank you. I am using Port Manipulation to run the LED's. I need to make a very simple array where one LED turns on and the previous turns off, then the next one turns on and the previous off (something like a shooting star or a knight rider). With Port Manipulation I've been able to clean my code however I have never tested it with more than 20 LED's.

I had no idea I would have problems with the duty cycle (I don't know what a duty cycle is and can't find a good explananation on the arduino.cc site) Sorry I'm really starting with arduino and code!!!

Today I received this code which might be helpful. It's a little hard to understand but as soon as I make it work I will post my results. It seems that with this code I won't need to charlieplex and I would be able to run all LED's in two pins. IS THIS RIGHT?

unsigned char cathodes[72] = {1,2,0,2,3,4,5,6, ...};
unsigned char anodes[72] = {0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,...};

void light_cp_led(unsigned char N)
{
static unsigned char last_n;
pinMode(cathodes[last_n], INPUT); // turn off previous LED
pinMode(anodes[last_n], INPUT); // on both ends
pinMode(cathodes[n], OUTPUT); // turn on new LED cathode
digitalWrite(cathodes[n], LOW);
pinMode(anodes[n], OUTPUT); // turn on new LED annode
digitalWrite(anodes[n], HIGH);
}

Thank you. I am using Port Manipulation to run the LED's. I need to make a very simple array where one LED turns on and the previous turns off, then the next one turns on and the previous off (something like a shooting star or a knight rider). With Port Manipulation I've been able to clean my code however I have never tested it with more than 20 LED's.

The way charlieplexing works, you can't really control 2 LEDs on at the same time, you're limited to 1 at a time. If you try and turn on 2, you get some group coming on depending on just how you set up your array. The way to get arround this is to store in memory which LEDs should be on and cycle through them very fast with only one on at a time. If you only go through the "on" LEDs, then it will take longer with more LEDs on, so each LED is on for less time out of each second. To keep the brightness consistent, you keep the delay even if each LED is off.

So for n LEDs, each one can be on at most 1/n of the time. But if you're limiting yourself to a few LEDs on at time, you don't need to worry about duty cycle, you can have each on for 1/10th of the time for example, which will be just fine no matter how many LEDs you use.

Analog inputs 0 - 5 can be used as digital pins 14 - 19.

HI

I need help making my analog pins work. WHen I use port manipulation, it works fine, however when I am not using port manipulation it does not work. What I want to do is a "Knight Rider" using PIN 3 as HIGH and PIN 7-19 as LOW. My code works fine until pin 13 and when it goes to the analog pins, it won't work....

here is the code:

#define x07x B10000000 //D 0-7 , B 8-13, C 0-5A DDR (i/o) , PORT (H/L)
#define x06x B01000000
#define x05x B00100000
#define x04x B00010000
#define x03x B00001000
#define x02x B00000100
#define x01x B00000010
#define x00x B00000001

int pinArray[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
int count = 0;
int timer = 50;
int timer2 = 13;

void setup(){
}

void loop() {

PORTD = x03x;
DDRD = x03x;

for (count=5;count<17;count++) {
pinMode(pinArray[count], OUTPUT);
delay(timer2);
pinMode(pinArray[count], OUTPUT);
delay(timer2);
pinMode(pinArray[count], INPUT);
delay(timer2);
}

I don't understand what your code is doing, nor do I ever see you set the output values for port C pins (this is the port that has the analog inputs on it).

I don't understand what your code is doing, nor do I ever see you set the output values for port C pins (this is the port that has the analog inputs on it).

I'm sorry about that, and sorry for my english too, I'm from Chile. This is my first experience with code and arduino. I'm starting from 0; My code works fine. I made it simpler and hopefully it will be easier to understand. This code is part of a bigger code to make a Knight Rider with 144 LED's. There MUST be easier ways but I am a beginner and it's hard for me already trying to fix my own code. My only problem right now is that I cannot turn ON the LED's connected to the analog Pins.

Just to put this code in context, I am running 144 leds with charlieplexing. The way I am doing this is setting one pin (ex: digital pin 2) as OUTPUT/HIGH and go through all the others to OUTPUT/LOW.
Then I go to the next pin (ex: digital pin 3) as OUPUT/HIGH and go through all the others, one by one from INPUT to OUTPUT/LOW.

It goes through all the pins turning them on and inmediately off, like the Knight Rider example.

All LED and charlieplexed.

I haven't set the values of the C pins because I don't know how to do this. I tried though. What I dont understand is why my code works from pin 7-13 and it doesnt from analog pin 0-5, if they are suppose to behave as digital too...

this is the code as clean as I could make it:

//I have an array of LED's. All anodes are connected to PIN3 and cathodes are connected to PIN7-19//

int pinArray[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; //an array from pin 7 to 19, stolen from "knight Rider" example
int count = 0;
int timer = 50;

void setup(){
}

void loop() {

PORTD = B00001000; //same as before, pin 3 HIGH and OUTPUT
DDRD = B00001000;

for (count=0;count<13;count++) { //I got this from the "kinght Rider 3 example. a for statement that turns
pinMode(pinArray[count], OUTPUT); // from INPUT to OUTPUT every pin from 7 to 19
delay(timer);
pinMode(pinArray[count], OUTPUT);
delay(timer);
pinMode(pinArray[count], INPUT); // and then turns them INPUT
delay(timer);
}

}

I guess you could try putting

PORTC = 0;

in your setup() function and see if that fixes the problem. If not, maybe pinMode() isn't designed to work on the analog pins, in which case just use the DDRC register to change the mode of the port C pins from input to output. Bit 0 of DDRC controls the output state of analog input 0, bit 1 controls the output state of analog input 1, etc. When the bit is a 1, the pin is an output. When the bit is a 0, the pin is an input.

  • Ben

... maybe pinMode() isn't designed to work on the analog pins

pinMode does work on the analog pins as pins 14-19, at least it did for me in a somewhat different applicaton

I guess you could try putting

PORTC = 0;

in your setup() function and see if that fixes the problem.

I tried that already, but you have to set the pins to 0 or 1 (example PORTC C= B111111111; and DDRC; B111111111;
If I do this, I can't determine the settings of the pins (HIGH or LOW, INPUT or OUTPUT) on my for statement, as I did with pins 8-13. they just stay HIGH.

Is there any statement that would look like this?:

analogPin 0-5 = digitalWrite

You literally tried:

PORTC = 0;

?

You literally tried:

PORTC = 0;

?

I literally did PORTC = 0;

It sounds like this could be a problem with the wiring rather than the code. Double check that all the pins and the ground to the leds you are testing are wired ok. Try temporarily swapping the wires going to analog pins 0-5 with the ones going to pins 8-13. If the analog pins start working then it was a wiring problem.

I hope that helps get you going, good luck !

I've been doing that since last night, I've checked all the wiring (actually I'm just using two led's for testing purposes. One led is connected to pin 2 (which is HIGH) and one to pin 8 (LOW) and one to analog pin 2 (or pin 16) (LOW) and pin 2 won't work. I've changed the pins, the wires, the led's, the breadboard, everything...

By the way, I'm using an atmega8 on a Arduino NG.

Logically it shoud work, but it doesnt. I've been doing it for long enough so it can't be a wiring problem.
And if I state for example that an analog pin 2 is HIGH/OUTPUT with port register (PORTC = B00000100, DDRC = B00000100) and use another pin as ground, it will work no problem, but if I make a for statement where my pinArray is int pinArray ={14, 15, 16, 17, 18, 19}, it will not work. However if my pinArray is pinArray = {8, 9, 10, 11, 12}, it will work with no problem.

My for statement looks like this:

for (count=0;count<6;count++) {
pinMode(pinArray[count], OUTPUT);
delay(timer2);
pinMode(pinArray[count], OUTPUT);
delay(timer2);
pinMode(pinArray[count], INPUT);
delay(timer2);
}

and it works fine (It's a copy from Knight rider example) with pins 8-13, not with analog pins 0-5

strange

Have you tested a simple sketch that just flashes leds, something like this:

int pinArray[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};   
int count = 0;                                              
                          
 
void setup(){   
}  
                                              
void loop() { 
                                           
   for (count=5;count<17;count++) {                        
   pinMode(pinArray[count], OUTPUT);                        
   digitalWrite(pinArray[count],HIGH);
   delay(500);                                           
   digitalWrite(pinArray[count],LOW);
   delay(500);  
   pinMode(pinArray[count], INPUT); 
   delay(500); 
  } 
}

If that works as expected , it may narrow down the things that could be going wrong

Have you tested a simple sketch that just flashes leds, something like this:

int pinArray[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};   

int count = 0;

void setup(){  
}  
                                             
void loop() {
                                         
  for (count=5;count<17;count++) {                        
  pinMode(pinArray[count], OUTPUT);                        
  digitalWrite(pinArray[count],HIGH);
  delay(500);                                          
  digitalWrite(pinArray[count],LOW);
  delay(500);  
  pinMode(pinArray[count], INPUT);
  delay(500);
 }
}




If that works as expected , it may narrow down the things that could be going wrong

It didn't work. I changed your "for" statement so it goes through all the pins: for (count=0;count<17;count++), and it works fine on all pins from 0 to 13 but it will not work for the analog pins.

Is my arduino (Arduino NG, Atmega8) not working right? I doubt it. Because when I use port registers, it works all fine.

I will really appreciate if someone could try on their own arduino this simple task.

I ran the code with count going from 0 to 17 and leds 2 - 19 all flashed on my board. I tested on a freeduino board with an ATmega168 chip

I got a new chip and finally made my code work. It is very simple and I can charlieplex up to 306 LED's. I only have a main problem, which is memory space to store the pinArrays (see code below).

PROGMEM sounds like an option, but I haven't been able to make it work, and the other option would be an algorithm... Any suggestions

This is the code. To make it simpler, in this code I only use 4 pins (pin1-4). If you want to use all the pins (pin 1 to pin 19) then both pinArrays are huge and wont fit in my arduino. Any ideas on how to bring this to PROGMEM (yes, I read many times the PROGMEM page on arduino.cc) or to create an algorithm?)

this is the code

int pinArrayh[] = {02,03,04,01,03,04,01,02,04,01,02,03}; //pins high
int pinArrayl[] = {01,01,01,02,02,02,03,03,03,04,04,04}; //pins low
int count = 0;
int timer = 300;

void setup(){
}

void loop() {

for (count=0;count<12;count++) {
pinMode(pinArrayh[count], OUTPUT);
pinMode(pinArrayl[count], OUTPUT);
digitalWrite(pinArrayh[count],HIGH);
digitalWrite(pinArrayl[count],LOW);
delay(timer);
pinMode(pinArrayh[count], INPUT);
pinMode(pinArrayl[count], INPUT);
delay(timer);
}
}

It could be a good occasion to try this: Integrated Circuits - Memory :smiley:

Otherwise, if you wanna try to work with what you got, you can try this:
1 - if you want to cut mem usage by 2 right away, use char instead of int.
2 - you can use an easy algorithm, if you observe the pattern a bit more attentively.

for your 4 pin example, you have:
(ledN ranging from 0 to 11)

// (ledN ranging from 0 to 11) 
pinL = ledN/3+1
tmp = ledN % 3 + 1
if (tmp < pinL) {
   pinH =  tmp
}else{
  pinH =  tmp + 1
}

I guess, if you use the same kind of wiring for 18 pins, you get:

// (ledN ranging from 0 to 305) 
pinL = ledN/17 + 1
tmp = ledN % 17 + 1
if (tmp < pinL) {
   pinH =  tmp
}else{
  pinH =  tmp + 1
}

I suspect tho, that manually wiring 306 leds for charliplexing is gonna be quite a pain in the ass.
I would have rather multiplexed them using shift registers and preassembled 8x8 led matrices.
I've a friend who actually manually built a 16x16 led array and I can tell that after placing and soldering 200 of those, he wasn't that excited about the project anymore.
But if you still do it, that would be cool, I fully support you!