NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » LED Array Kit - Costum Solution (Not working)

November 06, 2016
by lnino
lnino's Avatar

Hey guys,

my LED Array kit has been in my drawer for a long while, but now I have decided to finish this Project.

I have been through the tutorial and had everything up and running on my breadboard. Then I thought I should create a custom PCB and put it in a nice Frame.

Now I have soldered my custom PCB and used the same Controller of the Breadboard. (Same Code as well) It is the running snake code for testing purpose.

This was running great on the breadboard. But now on the PCB all LEDs which are connected to PCx are making Problems.

In Detail the colums which are connected to PC0,PC1,PC2,PC3,PC4,PC5 have an issue. In more detail only the LEDs which the Anode leg.

The issue is that the LEDs are lighting for one second, then they get dark. LEDs on PDx are working fine.

I marked with red colour on the last photo which columns and LED leg are making Problems.

Any ideas why it acts like that?

LED Array PCB Schematic Back

November 07, 2016
by scootergarrett
scootergarrett's Avatar

I think I would need to see a picture (or a circuit diagram or both) and some code to help with this.

November 07, 2016
by lnino
lnino's Avatar

Oh of course you will get the code. I thought every Nerdkit member has also bought the LED Array kit. :-) So this is the official Nerdkit Code which I got when I bought the LED Array kit. I hope it is okay to post it here. Which Pictures do you mean? In my post is the Eagle-Schematic, Eagle-PCB, Front Foam and Back Foam. What else do you need?

Makefile:

GCCFLAGS=-g -Os -Wall -mmcu=atmega168 
LINKFLAGS=-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm
AVRDUDEFLAGS=-c avr109 -p m168 -b 115200 -P COM8
LINKOBJECTS=../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o

all:    ledarray-upload

ledarray.hex: ledarray.c
    make -C ../libnerdkits
    avr-gcc ${GCCFLAGS} ${LINKFLAGS} -o ledarray.o ledarray.c ${LINKOBJECTS}
    avr-objcopy -j .text -O ihex ledarray.o ledarray.hex

ledarray.ass:   ledarray.hex
    avr-objdump -S -d ledarray.o > ledarray.ass

ledarray-upload:    ledarray.hex
    avrdude ${AVRDUDEFLAGS} -U flash:w:ledarray.hex:a

Code:

// ledarray.c
// for NerdKits with ATmega168
// mrobbins@mit.edu

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/uart.h"

//#include "font.h"

// PIN DEFINITIONS:
//
// PB1-5 ROW DRIVERS (0-4)
// PC0-5,PD2-7: COLUMN DRIVERS (0-11)
#define F_CPU 14745600
#define ROWS 5
#define COLS 24

volatile uint8_t la_row, real_row;
volatile uint8_t la_data[COLS];

inline uint8_t ledarray_get(uint8_t i, uint8_t j) {
  if(i < ROWS && j < COLS) {
    if((la_data[j] & (1<<i)) != 0) {
      return 1;
    } else {
      return 0;
    }
  } else {
    return 0;
  }
}

inline void ledarray_set(uint8_t i, uint8_t j, uint8_t onoff) {
  if(i < ROWS && j < COLS) {
    if(onoff) {
      la_data[j] |= (1<<i);
    } else {
      la_data[j] &= ~(1<<i);
    }
  }
}

//sense variable indicates direction of LED: sense == 1 indicates COL wire must be
//hight for LED to turn on. sense == 0, COL wire must be low to turn LED on
inline void ledarray_set_columndriver(uint8_t j, uint8_t onoff, uint8_t sense) {
  // cols 0-5: PC0-5
  // cols 6-11: PD2-7
  if(j < 6) {
    if(onoff){ //led on
      DDRC |= (1 << (PC0 + j));
      if(sense) {
        PORTC |= (1 << (PC0 + j));
      } else {
        PORTC &= ~(1<< (PC0 + j));
      }
    } else { // led off, pins to high impedance
      DDRC &= ~(1 << (PC0 + j));
      PORTC &= ~(1 << (PC0 + j));
    }
  } else {
    if(onoff){ //led on
      DDRD |= (1 << (PD2 + (j-6)));
      if(sense) {
        PORTD |= (1 << (PD2 + (j-6)));
      } else {
        PORTD &= ~(1 << (PD2 + (j-6)));
      }
    } else { // led off, pins to high impedance
      DDRC &= ~(1 << (PC0 + j));
      DDRC &= ~(1 << (PC0 + j));
    }
  }
}

inline void ledarray_all_off() {
  // turn off all row drivers
  DDRB &= ~( (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5) );
  PORTB &= ~( (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5) );

  // turn off all column drivers
  DDRC &= ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) );
  PORTC &= ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) );
  DDRD &= ~( (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7) );
  PORTD &= ~( (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7) );  
}

SIGNAL(SIG_OVERFLOW0) {
  // turn off old row driver
  DDRB &= ~(1 << (PB1 + real_row));
  PORTB &= ~(1 << (PB1 + real_row));
  ledarray_all_off();

  // increment row number
  if(++la_row == 2*ROWS)
    la_row = 0;

  // set column drivers appropriately
  uint8_t j;
  if(la_row%2 == 0) {
    // even la_row number: fill even columns
    real_row = la_row / 2;
    for(j=0; j<COLS/2; j++) {
      ledarray_set_columndriver(j, ledarray_get(real_row, 2*j), 1);
    }
    // activate row driver SINK
    PORTB &= ~(1 << (PB1 + real_row));
    DDRB |= (1 << (PB1 + real_row));
  } else {
    // odd la_row number: fill odd columns
    real_row = (la_row-1)/2;
    for(j=0; j<COLS/2; j++) {
      ledarray_set_columndriver(j, ledarray_get(real_row, 2*j + 1), 0);
    }
    // activate row driver SOURCE
    PORTB |= (1 << (PB1 + real_row));
    DDRB |= (1 << (PB1 + real_row));
  }  
}

void ledarray_init() {
  // Timer0 CK/64 (900Hz)
  TCCR0B = (1<<CS01) | (1<<CS00);
  TIMSK0 = (1<<TOIE0);

  // outputs (set row drivers high for off)
  DDRC &= ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) );
  DDRD &= ~( (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7) );
  DDRB &= ~( (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5) );
}

void ledarray_left_shift() {
  // shift everything one position left
  uint8_t i, j;
  for(i=0; i<ROWS; i++) {
    for(j=0; j<COLS-1; j++) {
      ledarray_set(i,j, ledarray_get(i, j+1));
    }
  }
}

void ledarray_blank() {
  uint8_t i, j;
  for(i=0; i<ROWS; i++) {
    for(j=0; j<COLS; j++) {
      ledarray_set(i,j,0);
    }
  }
}

void ledarray_testpattern() {
  uint8_t i, j;
  ledarray_blank();

  for(i=0;i<ROWS;i++) {
    for(j=0;j<COLS;j++) {
      ledarray_set(i,j, 1 - ledarray_get(i,j));
      delay_ms(30);
    }
  }

  for(i=0;i<ROWS;i++) {
    for(j=0;j<COLS;j++) {
      ledarray_set(i,j, 1 - ledarray_get(i,j));
      delay_ms(30);
    }
  }
}

int main() {
  ledarray_init();

  // activate interrupts
  sei();

  // init serial port
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

  while(1) {
    ledarray_testpattern();
  }
  return 0;
}
November 09, 2016
by sask55
sask55's Avatar

It appears from you pictures and description that the LED on the C port are lighting up with one off the LED polarities but not the other. I think that is an indication that the pins on the C port are either not being energized when they should or possibly not sinking any current when they should. Without knowing the orientation of the LEDs on the display board I cannot determine which set of LEDs is not working.

This is a bit of a wild guess on my part but I would start by grounding Pin 22 on the micro. It appears to be not connected to anything on your PC board. Grounding that pin cannot cause any issues and there may be a possibility that the pins on the C port used that ground to sink current. On the data sheet that I have it is not clear what that pin 22 GND may be responsible for.

This does not explain why they are on for a second then go out but I would eliminate the possibility that the pins have no internal GND connection to sink current.

November 09, 2016
by sask55
sask55's Avatar

Following the recommended practice in the data sheet (Pin 20) AVCC should be connected to the VCC supply even if you are not using the ADC. I would solder a couple of pieces of wire between pins on the back of your PC board to see if there is any change in the operation of the setup.

Let use know if you find a solution.

Darryl

November 15, 2016
by Ralphxyz
Ralphxyz's Avatar

lnino, nice to see you. sorry I just viewed your post.

If you have not got this straighten out I would restore your breadboard setup which you said you had working!

Possible/hopefully you will see the error if it works.

I would go by the Nerdkit instructions, do not reference any of your work.

Hi Darryl and scootergarrett nice to see you also. I have been doing some posting over at Rick's forum.

Ralph

November 15, 2016
by lnino
lnino's Avatar

Thank you so much guys. Today I had the time to try your suggestions with my solder iron. The only differences between the breadboard and my PCB was the missing VREF, AVCC and AGND. I soldered some wires at the back of the PCB and now it works like charm. :-)

Thanks for sask55 for pointing out the mistake. Now I can go forward building the frame. :-) I will keep you updated about the progress.

November 15, 2016
by sask55
sask55's Avatar

Your welcome

I think your PC board could likely come in handy for any project that may have a permanent or semi permanent set up. It would be a relatively simple change to include the connections to the AVCC AGND on the Eagle PCB board schematic. Since you now have a unused wire connection terminal on the PC board now I would also make use of it for one more possible micro pin connection maybe pin 21 (Vref) would be handy. By making these changes to the schematic if you ever have more boards printed the new boards could have potential for any long term use type projects without having to solder any wires on the back.

Glad to here things are working

Darryl

Post a Reply

Please log in to post a reply.

Did you know that many systems in nature can be described by a first order response? Learn more...