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 » Upgrade to Atmega328p

January 18, 2010
by ton_mit
ton_mit's Avatar

I got the nerdkit and the led array about a month ago. I breezed through the initial build and all the projects. The led array was a bit tricky but, with the help of the forum I figured it out.

I recently upgraded to the ATmega328p chip. After following the nano guide to a to a T, I was able to flash the chip with no error codes.........but, now the led array doesn't work. It stays blank. I thought mabey it was in the wiring and checked it thoroughly everything looked right. So I put the ATmega168 back in and the led array worked perfectly.....now I'm stuck! Any help would be greatly appreciated? ton_mit

January 18, 2010
by mongo
mongo's Avatar

I recently purchased a couple myself. Haven't had the time to try them out but will post what I get when I do.

January 19, 2010
by Rick_S
Rick_S's Avatar

I'm assuming you purchased the 328p from the NK guys right?? I've used several 328p's and haven't run across this one yet.

The only thing I could think of is this. I created a separate code folder for the 328p programs. This way I could make sure I didn't inadvertently send the hex file for a 168 to the 328. To do this, after I created a copy of the code folder, I made sure the *.o and *.hex files had been deleted from the folder. I then changed the target in both GCCFLAGS and AVRDUDEFLAGS in the makefile. Then I would run make (I usually do this within Programmers notepad).

If .o and .hex files aren't deleted from the folder, make won't re-make them and then avrdude will transfer the hex for the 168 to the 328 and it won't work.

That's what I did with success.

YMMV

Rick

January 19, 2010
by ton_mit
ton_mit's Avatar

yes, purchased 2 328p's from NK. I followed the nano guide to the letter and also created a new folder for the 328p.....Exactly what do I have to do in the libnerdkits folder? I tried to delete the .o files but get errors when thying to compile. I am using Programers Notepad.

January 19, 2010
by Rick_S
Rick_S's Avatar

There's a file called io_328p.h that needs to be added to the libnerdkits folder and you have to add the #include "../libnerdkits/io_328p.h" to your program to compile for the 328. Then if you delete the *.o and *.hex files you should be able to re-compile without error.

If you don't place that file there AND add the include to your program you will get compile errors.

Rick

January 19, 2010
by ton_mit
ton_mit's Avatar

Now I get an error that says:
"ledarray.c:94: warning: 'SIG_OVERFLOWO' appears to be a misspelled signal handler"

I tried the unaltered code from "ledarray_test".....with the exception of the changes that you recomended: "There's a file called io_328p.h that needs to be added to the libnerdkits folder and you have to add the #include "../libnerdkits/io_328p.h" to your program to compile for the 328. Then if you delete the .o and .hex files you should be able to re-compile without error."

I even deleted all the ".o" files in the ../libnerdkits folder and ran make all for the libnerdkits to recompile the .o files.

still getting the sig error.....any suggestions? thnx ton_mit

January 19, 2010
by ton_mit
ton_mit's Avatar

here is the program....

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

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/io_328p.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;
}
January 19, 2010
by N3Roaster
N3Roaster's Avatar

I seem to recall reading that the SIG_* style was depreciated and it's possible that you're using a version of avr-libc that no longer has them. I don't have the LED array kit or a 328p so I might be entirely off base here, but it looks like you want that function to be called in response to an overflow on timer 0. It might be as simple as switching to the non-depreciated form. Try replacing

SIGNAL(SIG_OVERFLOW0) {

with

ISR(TIMER0_OVF_vect) {
January 20, 2010
by Rick_S
Rick_S's Avatar

You may be onto something N3Roaster. I forgot that I changed that interrupt statement early on. While I think the SIGNAL will still work for some mcu's it won't for all and since the 328p is newer, it may be one that it doesn't work on.

I think you're almost there. BTW, if you want to add a few more effects, I posted a few I had made in some other threads. There are links to the threads in newsletter#8.

Rick

January 20, 2010
by ton_mit
ton_mit's Avatar

"I seem to recall reading that the SIG_* style was depreciated and it's possible that you're using a version of avr-libc that no longer has them. I don't have the LED array kit or a 328p so I might be entirely off base here, but it looks like you want that function to be called in response to an overflow on timer 0. It might be as simple as switching to the non-depreciated form. Try replacing

SIGNAL(SIG_OVERFLOW0) { with

ISR(TIMER0_OVF_vect) {"

thank you and much acolades to N3Roaster!!!!!!! works like a charm!

January 20, 2010
by ton_mit
ton_mit's Avatar

also thank you to Rick_S.....I noticed you help alot on this forum.

Post a Reply

Please log in to post a reply.

Did you know that you can control multiple LEDs from one microcontroller output? Learn more...