March 28, 2012
by amartinez
|
Hello everyone. I've been playing with the LED Array kit. I got all the lights working and tested them with the ledarray_test files. All lights work great.
I have a few questions on the project, it seems to be blinking instead of scrolling (HELLO) on me and it seems a bit slow when I use the ledarray_template files.
I have to read the pdf file again but as I was fooling with the program I found a problem with it. If you change the time from 1000 ms to 10ms by the font_display commands at around line 245 the chip stops working alltogether. I couldn't get the chip to work again. I had to replace it.
If any of you guys have an extra 168, try this. I changed every delay to 10 from 1000. Why? I don't know, just fooling around, I didn't think it would be a problem. OOPS!
My hookup is a bit different. I'm using AVR DUDE's make.exe file to create the hex file. Once I see that there are no errors (except the connectivity error) I take the hex file and push it to the chip using the AVR Dragon via ISP. Yes, some wires have to come off while it's programming because LED lights connected to what should be ISP ports don't allow ISP programming. But that's the way I chose to do it.
Let me know if this happens to you. The code asks a lot out of the chip, lots of math. Maybe I overloaded the circuits inside???? I've seen these chips blow up when you divide by 0. Sounds like a small firecracker. |
March 30, 2012
by amartinez
|
I'm up to page 40 where it says "Remove the test pattern from your main loop, and instead write a message letter by letter to your LED array." I'm assuming this is the template directory's ledarray.c file. If so, I need some help.
I read the PDF file several times up until the UART portion. I'm working with the ledarray.c program in the template subdirectory. I'm trying to do a simple scrolling message starting from the right.
The code below gives me the word MOSFET on the array but blinks slowly, probably because there is still some code in it that calls for the test pattern, but I remarked both test pattern routines out and I just don't see any reference to the test pattern, so how could this be giving me a test pattern after printing the word MOSFET on the LED array without scrolling? I am trying to wrap my head around this problem.
All of the header files import properly. No errors. The HEX file compiles nicely.
// ledarray.c
// for NerdKits with ATmega168
// mrobbins@mit.edu
#include "../avr/include/stdio.h"
#include "../avr/include/avr/io.h"
#include "../avr/include/avr/interrupt.h"
#include "../avr/include/avr/pgmspace.h"
#include "../avr/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);
}
}
}
*/
void font_get(char match, char *buf) {
// copies the character "match" into the buffer
uint8_t i;
PGM_P p;
for(i=0; i<FONT_SIZE; i++) {
memcpy_P(&p, &font[i], sizeof(PGM_P));
if(memcmp_P(&match, p,1)==0) {
memcpy_P(buf, p, 7);
return;
}
}
// NO MATCH?
font_get('?', buf);
}
uint8_t font_width(char c) {
char buf[7];
buf[1] = 0;
font_get(c, buf);
return buf[1];
}
void font_display(char c, uint8_t offset) {
char buf[7];
font_get(c, buf);
uint8_t width = buf[1];
uint8_t i, j;
for(i=0; i<ROWS; i++) {
for(j=0; j<width; j++) {
if((offset + j) < COLS) {
if( (buf[2+j] & (1<<i)) != 0) {
ledarray_set(i,offset + j,1);
} else {
ledarray_set(i,offset + j,0);
}
}
}
}
// blank the next column to the right
for(i=0; i<ROWS; i++) {
ledarray_set(i, offset+width, 0);
}
}
/*
void do_testpattern() {
// mode 1: test pattern
int8_t offset=0;
while(1) {
// break out?
if(uart_char_is_waiting()) break;
// test pattern
ledarray_testpattern();
// break out?
if(uart_char_is_waiting()) break;
// test letters
ledarray_blank();
offset=0;
font_display('H', offset); offset += font_width('H')+1; delay_ms(1000);
font_display('E', offset); offset += font_width('E')+1; delay_ms(1000);
font_display('L', offset); offset += font_width('L')+1; delay_ms(1000);
font_display('L', offset); offset += font_width('L')+1; delay_ms(1000);
font_display('O', offset); offset += font_width('O')+1; delay_ms(1000);
// break out?
if(uart_char_is_waiting()) break;
}
}
*/
void do_scrolling_display() {
ledarray_blank();
int8_t offset = 0, next_offset = 0;
uint8_t is_started = 0;
char x=' ';
while(1) {
if(is_started) {
delay_ms(125);
ledarray_left_shift();
if(next_offset > 0) {
offset -= 1;
next_offset -= 1;
} else {
is_started = 0;
}
font_display(x, offset);
} else {
offset = COLS-1;
}
// if we can now accept a new character, tell the computer
if(next_offset == COLS)
uart_write('n');
while(uart_char_is_waiting()) {
if(is_started)
offset = next_offset;
x = uart_read();
if(x=='a') {
ledarray_blank();
return;
}
font_display(x, offset);
next_offset = offset + font_width(x)+1;
is_started = 1;
// if we can now accept a new character, tell the computer
if(next_offset <= COLS)
uart_write('n');
}
}
}
void do_simple_display() {
ledarray_blank();
uint8_t offset = 0;
char x = ' ';
while(1){
x = uart_read();
if(x == 'z'){
ledarray_blank();
offset = 0;
} else {
//render the charater we just got
font_display(x,offset);
//adjust the offset for the next character
offset += font_width(x)+1;
}
}
}
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;
*/
// mode 1: test pattern
// do_testpattern();
// test letters
ledarray_blank();
uint8_t offset=0;
font_display('M', offset); offset += font_width('M')+1; delay_ms(1000);
font_display('O', offset); offset += font_width('O')+1; delay_ms(1000);
font_display('S', offset); offset += font_width('S')+1; delay_ms(1000);
font_display('F', offset); offset += font_width('F')+1; delay_ms(1000);
font_display('E', offset); offset += font_width('E')+1; delay_ms(1000);
font_display('T', offset); offset += font_width('T')+1; delay_ms(1000);
uint8_t i,j;
for(i=0;i<ROWS;i++) {
for(j=0;j<COLS;j++) {
ledarray_set(i,j, 1);
delay_ms(30);
}
}
while(1) {
// do_simple_display();
do_scrolling_display();
}
return 0;
}
|