good afternoon, I am making a 7x10 led matrix in which I use a CD4017 to handle the 7 rows and 2 cascaded shift registers to handle the 10 columns. I first tried a programming to turn on my entire led matrix and it worked fine. Then, I tried to make a character appear statically and it worked fine. Next, I tried to make that character sweep from right to left and it worked fine. But, what I am having a hard time with is sweeping the message from right to left smoothly with a column of character to character spacing.
What I originally thought is that if I wanted to move a character from right to left, I have to shift the column values for all the rows by an appropriate amount (shift step) and once the character has been shifted enough, I start feeding the column values of the next character in the message for which, the formula that would create the right to left shift effect is: (current_char<scroll) | (next_char>>(8-shift_step)-scroll) But I don't get the expected result, the message scrolls from right to left but it doesn't do it with a column of separation between character and character and it doesn't do it in a fluid way either. In addition to that at the end of sweeping the message appears something strange that should not be there.
I recorded a video showing what I am saying: https://drive.google.com/file/d/1ebO5zassWY060mvWACPhcSLeOi5JmZAC/view
Code:
/*
char_data is a two dimensional constant array that holds the 5-bit column values
of individual rows for ASCII characters that are to be displayed on a 7x10 matrix.
*/
const byte char_data[95][7]={
{0, 0, 0, 0, 0, 0, 0}, // space
{0b100, 0b100, 0b100, 0b100, 0b100, 0, 0b100}, // !
{0b1010, 0b1010, 0b1010, 0, 0, 0, 0}, // "
{0b1010, 0b1010, 0b11111, 0b1010, 0b11111, 0b1010, 0b1010}, // #
{0b100, 0b1111, 0b10100, 0b1110, 0b101, 0b11110, 0b100}, // $
{0b11000, 0b11001, 0b10, 0b100, 0b1000, 0b10011, 0b11}, // %
{0b1000, 0b10100, 0b10100, 0b1000, 0b10101, 0b10010, 0b1101}, // &
{0b100, 0b100, 0b100, 0, 0, 0, 0}, // '
{0b100, 0b1000, 0b10000, 0b10000, 0b10000, 0b1000, 0b100}, // (
{0b100, 0b10, 0b1, 0b1, 0b1, 0b10, 0b100}, // )
{0b100, 0b10101, 0b1110, 0b100, 0b1110, 0b10101, 0b100}, // *
{0, 0b100, 0b100, 0b11111, 0b100, 0b100, 0}, // +
{0, 0, 0, 0, 0b100, 0b100, 0b1000}, // ,
{0, 0, 0, 0b11111, 0, 0, 0}, // -
{0, 0, 0, 0, 0, 0, 0b100}, // .
{0, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0}, // /
{0b1110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b1110}, // 0
{0b110, 0b1100, 0b100, 0b100, 0b100, 0b100, 0b1110}, // 1
{0b1110, 0b10001, 0b1, 0b110, 0b1000, 0b10000, 0b11111}, // 2
{0b11111, 0b1, 0b10, 0b110, 0b1, 0b10001, 0b1111}, // 3
{0b10, 0b110, 0b1010, 0b10010, 0b11111, 0b10, 0b10}, // 4
{0b11111, 0b10000, 0b11110, 0b1, 0b1, 0b10001, 0b1110}, // 5
{0b01110, 0b10001, 0b10000, 0b11110, 0b10001, 0b10001, 0b1110}, // 6
{0b11111, 0b1, 0b10, 0b100, 0b1000, 0b1000, 0b1000}, // 7
{0b01110, 0b10001, 0b10001, 0b1110, 0b10001, 0b10001, 0b1110}, // 8
{0b01110, 0b10001, 0b10001, 0b1111, 0b1, 0b10001, 0b1110}, // 9
{0, 0, 0b100, 0, 0b100, 0, 0}, // :
{0, 0, 0b100, 0, 0b100, 0b100, 0b1000}, // ;
{0b10, 0b100, 0b1000, 0b10000, 0b1000, 0b100, 0b10}, // <
{0, 0, 0b11111, 0, 0b11111, 0, 0}, // =
{0b1000, 0b100, 0b10, 0b1, 0b10, 0b100, 0b1000}, // >
{0b1110, 0b10001, 0b1, 0b10, 0b100, 0, 0b100}, // ?
{0b1110, 0b10001, 0b10111, 0b10101, 0b10110, 0b10000, 0b1111}, // @
{0b1110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // A
{0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b11110}, // B
{0b1110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001, 0b1110}, // C
{0b11110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b11110}, // D
{0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b11111}, // E
{0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b10000}, // F
{0b1110, 0b10001, 0b10000, 0b10111, 0b10101, 0b10001, 0b1110}, // G
{0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // H
{0b11111, 0b100, 0b100, 0b100, 0b100, 0b100, 0b11111}, // I
{0b1, 0b1, 0b1, 0b1, 0b1, 0b10001, 0b1110}, // J
{0b10001, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001, 0b10001}, // K
{0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111}, // L
{0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001, 0b10001}, // M
{0b10001, 0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001}, // N
{0b1110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1110}, // O
{0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000, 0b10000}, // P
{0b1110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10011, 0b1111}, // Q
{0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b10001}, // R
{0b1111, 0b10000, 0b10000, 0b1110, 0b1, 0b1, 0b11110}, // S
{0b11111, 0b100, 0b100, 0b100, 0b100, 0b100, 0b100}, // T
{0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1110}, // U
{0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1010, 0b100}, // V
{0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b11011, 0b10001}, // W
{0b10001, 0b10001, 0b1010, 0b100, 0b1010, 0b10001, 0b10001}, // X
{0b10001, 0b10001, 0b1010, 0b100, 0b100, 0b100, 0b100}, // Y
{0b11111, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b11111}, // Z
{0b1110, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1110}, // [
{0, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0}, // backward slash
{0b1110, 0b10, 0b10, 0b10, 0b10, 0b10, 0b1110}, // ]
{0, 0, 0b100, 0b1010, 0b10001, 0, 0}, // ^
{0, 0, 0, 0, 0, 0, 0b11111}, // _
{0b1000, 0b100, 0b10, 0, 0, 0, 0}, // `
{0, 0, 0b1110, 0b1, 0b1111, 0b10001, 0b1111}, // a
{0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110}, // b
{0, 0, 0b1110, 0b10001, 0b10000, 0b10001, 0b1110}, // c
{0b1, 0b1, 0b1, 0b1111, 0b10001, 0b10001, 0b1111}, // d
{0, 0, 0b1110, 0b10001, 0b11111, 0b10000, 0b1111}, // e
{0b1110, 0b1001, 0b11100, 0b1000, 0b1000, 0b1000, 0b1000}, // f
{0, 0, 0b1110, 0b10001, 0b1111, 0b1, 0b1110}, // g
{0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b10001}, // h
{0b100, 0, 0b100, 0b100, 0b100, 0b100, 0b1110}, // i
{0b1, 0, 0b11, 0b1, 0b1, 0b10001, 0b1110}, // j
{0b10000, 0b10000, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001}, // k
{0b1100, 0b100, 0b100, 0b100, 0b100, 0b100, 0b1110}, // l
{0, 0, 0b11110, 0b10101, 0b10101, 0b10101, 0b10101}, // m
{0, 0, 0b11110, 0b10001, 0b10001, 0b10001, 0b10001}, // n
{0, 0, 0b1110, 0b10001, 0b10001, 0b10001, 0b1110}, // o
{0, 0, 0b1111, 0b1001, 0b1110, 0b1000, 0b1000}, // p
{0, 0, 0b1111, 0b10001, 0b1111, 0b1, 0b1}, // q
{0, 0, 0b10111, 0b11000, 0b10000, 0b10000, 0b10000}, // r
{0, 0, 0b1111, 0b10000, 0b1110, 0b1, 0b11110}, // s
{0b100, 0b100, 0b1110, 0b100, 0b100, 0b100, 0b11}, // t
{0, 0, 0b10001, 0b10001, 0b10001, 0b10011, 0b1101}, // u
{0, 0, 0b10001, 0b10001, 0b10001, 0b1010, 0b100}, // v
{0, 0, 0b10001, 0b10001, 0b10101, 0b11111, 0b10101}, // w
{0, 0, 0b10001, 0b1010, 0b100, 0b1010, 0b10001}, // x
{0, 0, 0b10001, 0b10001, 0b1111, 0b1, 0b11110}, // y
{0, 0, 0b11111, 0b10, 0b100, 0b1000, 0b11111}, // z
{0b10, 0b100, 0b100, 0b1000, 0b100, 0b100, 0b10}, // {
{0b100, 0b100, 0b100, 0b100, 0b100, 0b100, 0b100}, // |
{0b1000, 0b100, 0b100, 0b10, 0b100, 0b100, 0b1000}, // }
{0, 0, 0, 0b1010, 0b10101, 0, 0} // ~
};
char message[] = "MATRIX LED 7X10 WITH ATMEGA328p";
int string_length = strlen(message);
byte shift_step = 1;
void setup(){
// PORTB as output.
// Pin 13: ClockRegister
// Pin 12: Latch
// Pin 11: Data
// Pin 10: Reset
// Pin 9: Clock4017
DDRB = 0b111111;
// Makes sure the 4017 value is 0.
PORTB |= (1 << PB2);
PORTB &= ~(1 << PB2);
Serial.begin(9600);
}
void send_data(uint16_t data){
uint16_t mask = 1, flag = 0;
for (byte i=0; i<10; i++){
flag = data & mask;
if (flag) PORTB |= (1 << PB3);
else PORTB &= ~(1 << PB3);
PORTB |= (1 << PB5);
PORTB &= ~(1 << PB5);
mask <<= 1;
}
PORTB |= (1 << PB4);
PORTB &= ~(1 << PB4);
}
void display_pattern(byte loops){
for (byte c=0; c<string_length; c++){ // For each character
for (byte scroll=0; scroll<10; scroll++){ // For each column.
for (byte t=0; t<loops; t++){ // The delay we get with loops.
for (byte z=0; z<7; z++){ // For each row.
// To obtain the position of the current character in the char_data array, subtract 32 from the ASCII value of the character itself.
byte index = message[c];
byte temp = char_data[index-32][z];
byte index_2 = message[c+1];
byte temp_2 = char_data[index_2-32][z];
send_data((temp<<scroll) | (temp_2>>(8-shift_step)-scroll));
delayMicroseconds(800);
// Clear the row so we can go on to the next row without smearing.
send_data(0);
// On to the next row.
PORTB |= (1 << PB1);
PORTB &= ~(1 << PB1);
}
// Select the first row.
PORTB |= (1 << PB2);
PORTB &= ~(1 << PB2);
}
}
}
}
void loop(){
display_pattern(10);
delay(100000);
}
I appreciate the help.
index_2
is accessing beyond the strlen(message) toward the end of the message.