LED Charlieplex problem

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have 12 LEDs that are Charlieplexed that I want to control through some buttons. When a button is pressed. I want to toggle the state of the corresponding LED. I will need several LEDs to "appear" as if they are on at the same time. I can get the lights to light one at a time, I can't get several to look like they are on at the same time. I tried the tutorial at http://www.instructables.com/id/Creating-a-charlieplexed-LED-grid-to-run-on-ATTiny/?ALLSTEPS and converted it to my program but isn't working. I know the button routine works correctly because I can toggle the light if just set the DDR and port in the if statements. I have looked through this and just can't figure it out. Any idea where my conversion went wrong or a better method?

/************************************************************************/
/*                                                                      */
/*                      Debouncing 8 Keys    */
/*   Sampling 4 Times    */
/*                                                                      */
/*              Author: Peter Dannegger                                 */
/*                                                                      */
/************************************************************************/

#include <util/atomic.h>  // need "--std=c99"
#include <util/delay.h>

typedef unsigned char u8;
typedef signed short s16;

#define XTAL  8e6  // 8MHz

#define KEY_PIN1 PIND  //Define Key info
#define KEY_PIN2 PINB
#define KEY_PORT PORTD
#define KEY_DDR  DDRD
#define KEY0  0
#define KEY1  1
#define KEY2  2
#define KEY3  3
#define KEY4  4
#define KEY5  5
#define KEY6  6
#define KEY7  7
#define KEY8  8
#define KEY9  9
#define KEY10  10
#define KEY11  11
#define KEY12  12
#define KEY_INPUT ((PINB<<8) | PIND)

#define LINE_A 0 //Will be PortC Pin0
#define LINE_B 1 //Will be PortC Pin1
#define LINE_C 2 //Will be PortC Pin2
#define LINE_D 3 //Will be PortC Pin3


uint16_t key_state;    // debounced and inverted key state:
        // bit = 1: key pressed
uint16_t key_press;    // key press detect


//DDRC direction config for each LED (1 = output)
const char led_dir[12] = {
 ( 1<<LINE_A | 1<<LINE_D ), //LED 0
 ( 1<<LINE_A | 1<<LINE_C ), //LED 1
 ( 1<<LINE_A | 1<<LINE_B ), //LED 2
 ( 1<<LINE_B | 1<<LINE_D ), //LED 3
 ( 1<<LINE_B | 1<<LINE_C ), //LED 4
 ( 1<<LINE_B | 1<<LINE_A ), //LED 5
 ( 1<<LINE_C | 1<<LINE_D ), //LED 6
 ( 1<<LINE_C | 1<<LINE_B ), //LED 7
 ( 1<<LINE_C | 1<<LINE_A ), //LED 8
 ( 1<<LINE_D | 1<<LINE_C ), //LED 9
 ( 1<<LINE_D | 1<<LINE_B ), //LED 10
 ( 1<<LINE_D | 1<<LINE_A ) //LED 11
};
//PORTBc output config for each LED (1 = High, 0 = Low)
const char led_out[12] = {
 ( 1<<LINE_A ), //LED 0
 ( 1<<LINE_A ), //LED 1
 ( 1<<LINE_A ), //LED 2
 
 ( 1<<LINE_B ), //LED 3
 ( 1<<LINE_B ), //LED 4
 ( 1<<LINE_B ), //LED 5
 
 ( 1<<LINE_C ), //LED 6
 ( 1<<LINE_C ), //LED 7
 ( 1<<LINE_C), //LED 8
 
 ( 1<<LINE_D ), //LED 9
 ( 1<<LINE_D ), //LED 10
 ( 1<<LINE_D ) //LED 11
};
char led_grid[12] = {
 000,000,000,
 000,000,000,
 000,000,000,
 000,000,000
};
 
void light_led(char);
void leds_off();
void draw_frame(void);

ISR( TIMER0_COMPA_vect )  // every 10ms
{
 static uint16_t ct0 = 0xFF, ct1 = 0xFF; // 8 * 2bit counters
 volatile uint16_t i;

 i =KEY_INPUT;    // read keys (low active)
 i ^= key_state;   // key changed ?
 ct0 = ~( ct0 & i );   // reset or count ct0
 ct1 = ct0 ^ (ct1 & i);  // reset or count ct1
 i &= ct0 & ct1;   // count until roll over ?
 key_state ^= i;   // then toggle debounced state
 key_press |= key_state & i;  // 0->1: key press detect
}


uint16_t get_key_press( uint16_t key_mask )
{
 ATOMIC_BLOCK(ATOMIC_FORCEON){  // read and clear atomic !
  key_mask &= key_press;  // read key(s)
  key_press ^= key_mask;  // clear key(s)
 }
 return key_mask;
}


int main( void )
{
 TCCR0A = 1<<WGM01;   // T0 Mode 2: CTC
 TCCR0B |= (1 << CS02)|(1 << CS00); // clock divider 1024
 OCR0A = 77;    // Approximately 10 ms
 TIMSK0 = 1<<OCIE0A;   // enable T0 interrupt
 

 KEY_DDR = 0x00;    // input
 KEY_PORT = 0xFF;   // pullups on
 DDRB =0x00;     //input second port
 PORTB = 0xFF;    //pullups on
 
 key_state = ((PIND<<8) | PINB); // no action on keypress during reset
 

 sei();

 for(;;){
  draw_frame();     // main loop
  if( get_key_press( 1<<KEY0 )){
 
   if ( led_grid[0]==0){  // LED Off....toggle on
    led_grid[0]=100;
    
   }
   else{     //LED On...toggle off
    led_grid[0]=0;   
   }
   
  }
  if( get_key_press( 1<<KEY1 )){
   
   if ( led_grid[0]==0){
    led_grid[1] =100;
   }
   else{
    led_grid[1]=0;
   }
   
  }
 }
}

void light_led(char led_num) { //led_num must be from 0 to 11
 DDRB = led_dir[led_num];
 PORTB = led_out[led_num];
}

void leds_off() {
 DDRB = 0;
 PORTB = 0;
}
void draw_frame(void){
 char led, bright_val, b;
 for ( led=0; led<=12; led++ ) {
  //software PWM
  bright_val = led_grid[led];
  for( b=0 ; b < bright_val ; b+=4 ) { light_led(led); } //delay while on
  for( b=bright_val ; b<100 ; b+=4 ) { leds_off(); } //delay while off
 }
}

Thanks for your help!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That article was for a Tiny85, which I do not think you are using since you have all those buttons.

 

I would look for a better example that uses rows and columns to run the LED's

 

JMO

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How would the number of buttons affect anything? Any suggestions for a better method? This was the best one I could find...Or at least that I could understand.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

http://www.embedds.com/using-thr...

 

THat one caught my eye first.  Try Google like I did and wade through the pool of examples is the best thing.

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't see any example of code there...the problem is in the code and not the wiring. I have tested the wiring and I can get one LED to light through code, I just can't get the "flash" routine to work. I have googled quite a bit and tried a few different code samples but I couldn't get any of them to work. I didn't want to just post that I can't get it to work and not post one of the methods I have tried to at least have a starting point for someone to help with.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dusteater wrote:
I will need several LEDs to "appear" as if they are on at the same time
Quote:

The "appear" in quotes there suggests that you do realise that, in general, charlieplexing means that you can't have several LEDs on at the same time - yes?

 

So you are going to have to have some sort of time sequencing to switch between the LEDs at such a speed that they appear to be on simultaneously.

 

Quote:
isn't working

 

Is uninformative.

 

http://www.catb.org/esr/faqs/sma...

 

What, exactly, does happen?

 

What debugging have you done?

 

Do you have an oscilloscope to see what's going on? If not, why not slow the timing right down so that you can see it with the naked eye?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From the code, at most 2 LEDs could be on "at once".

Try a constant led_grid before trying to modify it on the fly.

Also, despite the tutorial, LEd display is not normally done in the main loop.

 

Edit:

If the code works as it would seem to,

holding down both keys would rapidly toggle LEDs 0 and 1.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

Last Edited: Sun. Jan 18, 2015 - 08:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dusteater wrote:

I didn't see any example of code there...

 

Yes, because some websites are simply plagarisers. The original article and source code are here.

 

http://www.edn.com/design/system...

 

Cheers,

 

Ross

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok so I spent some time trying to figure out what might be wrong. I decided to test each part separately and expand each section. So I put the code for setting the DDR and PORTs in the get_key_press test. I got that working and then I moved the DDR and PORT setting to the draw_frame function and then debugged it and discovered that the program never stepped into the light_led function. in the immediate window, I tried to call the function and got an error-Call to unknown function:light_led.  I am going to move things around to see if I can get it working, but in the meantime, can you tell me why it wasn't calling the function?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dusteater wrote:
Ok so I spent some time trying to figure out what might be wrong. I decided to test each part separately and expand each section. So I put the code for setting the DDR and PORTs in the get_key_press test. I got that working and then I moved the DDR and PORT setting to the draw_frame function and then debugged it and discovered that the program never stepped into the light_led function. in the immediate window, I tried to call the function and got an error-Call to unknown function:light_led.  I am going to move things around to see if I can get it working, but in the meantime, can you tell me why it wasn't calling the function?
No.

Look at the .lss file to find out whether there is a light_function.

I don't know why it might be missing.

 

Your code formatting is a bit sloppy.

That makes it hard to be certain that things are nested the way one thinks they are.

 

Also, for testing LED code, I'd get rid of the key code altogether.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your help and advice. I was able to get it working!