Require components:
- 1x Arduino Uno
- 8x 1000ohm Resistor
- 2x SN74HC595N
- Wires
Tools help you change code show LEDs:
https://zxcongducxz.000webhostapp.com/arduino/LEDMatrix8x8.html
Video:
1. Code test all LEDs from top to bottom, from left to right:
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte TOTAL_ROWS = sizeof(BIT_ROWS); // total row pins
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
const byte TOTAL_COLUMNS = sizeof(BIT_COLUMNS); // total column pins
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
unsigned short markColumn(byte indexColumnOn) { // column is cathod, set indexColumnOn value to 0 to LED on, other columns value to 1 to LED off
unsigned short dataColumn = 0;
for(byte indexColumn = 0; indexColumn < TOTAL_COLUMNS; indexColumn++) {
if(indexColumn != indexColumnOn) { // set all toher cathod column value to 1 (LED off)
dataColumn |= 1 << BIT_COLUMNS[indexColumn];
}
}
return dataColumn;
}
unsigned short markRow(byte indexRowOn) { // row is anode, set current row value to 1 to LED on, other rows value to 0 to LED off
unsigned short dataRow = 0;
return dataRow | (1 << BIT_ROWS[indexRowOn]);
}
void loop() { // turn on 1 LED, from left to right, from top to bottom
for(byte indexRow = 0; indexRow < TOTAL_ROWS; indexRow++) { // each row from top to bottom
unsigned short dataRow = markRow(indexRow);
for(byte indexColumn = 0; indexColumn < TOTAL_COLUMNS; indexColumn++) { // each column from left to right
unsigned short dataColumn = markColumn(indexColumn);
unsigned short dataLED = dataRow | dataColumn; // combine column & row
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(100); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
}
}
}
2. Code test all rows:
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte TOTAL_ROWS = sizeof(BIT_ROWS); // total row pins
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
const byte TOTAL_COLUMNS = sizeof(BIT_COLUMNS); // total column pins
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
void loop() {
for(byte indexRow = 0; indexRow < TOTAL_ROWS; indexRow++) { // each row from top to bottom
// there are 16 bits, turn on current row by set row value to 1, all columns values to 0
unsigned short dataLED = 0 | (1 << BIT_ROWS[indexRow]);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(500); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
}
}
Code test all columns:
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte TOTAL_ROWS = sizeof(BIT_ROWS); // total row pins
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
const byte TOTAL_COLUMNS = sizeof(BIT_COLUMNS); // total column pins
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
void loop() {
for(byte indexColumn = 0; indexColumn < TOTAL_COLUMNS; indexColumn++) { // each row from top to bottom
// there are 16 bits used for 16 pins.
// all index bit of rows are on = 8 bits (row anode value = 1)
// 1 index bit of column are on (column anode value = 0), 7 other columns are off (value = 1)
// so there is 1 bit value = 0, all bits are 16 = decimal: 65535, xor current index column let it's value to 0;
unsigned short dataLED = 65535 ^ (1 << BIT_COLUMNS[indexColumn]);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(500); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
}
}
3. Code display human animation 8x8:
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
unsigned short DURATION_COLUMN = 2; // value too high make you see LED blink, should <=3 is OK
unsigned short DURATION_FRAME = 500;
byte ANIMATION1_DATA[] = {
16,144,87,61,87,144,16,0,8,144,87,61,87,144,8,0,0,152,87,61,87,152,0,0,8,136,87,61,87,136,8,0,4,136,87,61,87,136,4,0,0,140,87,61,87,140,0,0,
0,140,87,61,87,140,0,0,4,136,87,61,87,136,4,0,8,136,87,61,87,136,8,0,0,152,87,61,87,152,0,0,8,144,87,61,87,144,8,0,16,144,87,61,87,144,16,0,
};
byte indexColumnDisplaying = 0; // store current index column for avoid column on the right display less than column on the left
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
unsigned short convertByteColumnTo16Bit(byte byteColumn, byte indexColumnTurnOn) {
unsigned short dataLED = 0;
// row is anode, set indexBit of row value to 1 to LED on, value 0 to LED off
for (byte indexBit = 0; indexBit < 8; indexBit++) {
bool isOn = byteColumn & (1 << indexBit);
if (isOn) {
dataLED |= 1 << BIT_ROWS[indexBit];
}
}
// column is cathod, set column value to 0 to LED on, value 1 to LED off, code below mark all other columns off
for(byte indexColumn = 0; indexColumn < sizeof(BIT_COLUMNS); indexColumn++){
bool isOn = indexColumn == indexColumnTurnOn;
if (!isOn) {
dataLED |= 1 << BIT_COLUMNS[indexColumn];
}
}
return dataLED;
}
void display8x8(byte bytesAnimation[], int offsetColumn, unsigned short durationFrame) {
while(durationFrame >= DURATION_COLUMN) {
byte byteDisplay = bytesAnimation[offsetColumn + indexColumnDisplaying];
unsigned short dataLED = convertByteColumnTo16Bit(byteDisplay, indexColumnDisplaying);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(DURATION_COLUMN); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
durationFrame -= DURATION_COLUMN;
indexColumnDisplaying = (indexColumnDisplaying + 1) % sizeof(BIT_COLUMNS);
}
}
void animationDisplayFrameByFrame(unsigned short durationFrame, byte bytesAnimation[], size_t totalColumns) {
for(byte offsetColumn = 0; offsetColumn < totalColumns; offsetColumn+=sizeof(BIT_COLUMNS)) {
display8x8(bytesAnimation, offsetColumn, durationFrame);
}
}
void loop() {
animationDisplayFrameByFrame(DURATION_FRAME, ANIMATION1_DATA, sizeof(ANIMATION1_DATA));
}
4. Code run animation text from left to right
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
unsigned short DURATION_COLUMN = 2; // value too high make you see LED blink, should <=3 is OK
unsigned short DURATION_FRAME = 100;
byte ANIMATION1_DATA[] = {
62,81,73,69,62,0,68,66,127,64,64,0,98,81,73,73,70,0,34,65,73,73,54,0,24,20,18,127,16,0,39,69,69,69,57,0,62,73,73,73,50,0,1,113,9,5,3,0,54,73,73,73,54,0,38,73,73,73,62
};
byte indexColumnDisplaying = 0; // store current index column for avoid column on the right display less than column on the left
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
unsigned short convertByteColumnTo16Bit(byte byteColumn, byte indexColumnTurnOn) {
unsigned short dataLED = 0;
// row is anode, set indexBit of row value to 1 to LED on, value 0 to LED off
for (byte indexBit = 0; indexBit < 8; indexBit++) {
bool isOn = byteColumn & (1 << indexBit);
if (isOn) {
dataLED |= 1 << BIT_ROWS[indexBit];
}
}
// column is cathod, set column value to 0 to LED on, value 1 to LED off, code below mark all other columns off
for(byte indexColumn = 0; indexColumn < sizeof(BIT_COLUMNS); indexColumn++){
bool isOn = indexColumn == indexColumnTurnOn;
if (!isOn) {
dataLED |= 1 << BIT_COLUMNS[indexColumn];
}
}
return dataLED;
}
void display8x8(byte bytesAnimation[], size_t totalColumns, int offsetColumn, unsigned short durationFrame) {
while(durationFrame >= DURATION_COLUMN) {
byte byteDisplay = bytesAnimation[(offsetColumn + indexColumnDisplaying) % totalColumns];
unsigned short dataLED = convertByteColumnTo16Bit(byteDisplay, indexColumnDisplaying);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(DURATION_COLUMN); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
durationFrame -= DURATION_COLUMN;
indexColumnDisplaying = (indexColumnDisplaying + 1) % sizeof(BIT_COLUMNS);
}
}
void animationLeftToRight(unsigned short durationFrame, byte bytesAnimation[], size_t totalColumns) {
for(byte offsetColumn = 0; offsetColumn < totalColumns; offsetColumn++) {
display8x8(bytesAnimation, totalColumns, offsetColumn, durationFrame);
}
}
void loop() {
animationLeftToRight(DURATION_FRAME, ANIMATION1_DATA, sizeof(ANIMATION1_DATA));
}
5. Code run animation text from right to left
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
unsigned short DURATION_COLUMN = 2; // value too high make you see LED blink, should <=3 is OK
unsigned short DURATION_FRAME = 100;
byte ANIMATION1_DATA[] = {
62,81,73,69,62,0,68,66,127,64,64,0,98,81,73,73,70,0,34,65,73,73,54,0,24,20,18,127,16,0,39,69,69,69,57,0,62,73,73,73,50,0,1,113,9,5,3,0,54,73,73,73,54,0,38,73,73,73,62
};
byte indexColumnDisplaying = 0; // store current index column for avoid column on the right display less than column on the left
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
unsigned short convertByteColumnTo16Bit(byte byteColumn, byte indexColumnTurnOn) {
unsigned short dataLED = 0;
// row is anode, set indexBit of row value to 1 to LED on, value 0 to LED off
for (byte indexBit = 0; indexBit < 8; indexBit++) {
bool isOn = byteColumn & (1 << indexBit);
if (isOn) {
dataLED |= 1 << BIT_ROWS[indexBit];
}
}
// column is cathod, set column value to 0 to LED on, value 1 to LED off, code below mark all other columns off
for(byte indexColumn = 0; indexColumn < sizeof(BIT_COLUMNS); indexColumn++){
bool isOn = indexColumn == indexColumnTurnOn;
if (!isOn) {
dataLED |= 1 << BIT_COLUMNS[indexColumn];
}
}
return dataLED;
}
void display8x8(byte bytesAnimation[], size_t totalColumns, int offsetColumn, unsigned short durationFrame) {
while(durationFrame >= DURATION_COLUMN) {
byte byteDisplay = bytesAnimation[(totalColumns - offsetColumn + indexColumnDisplaying) % totalColumns];
unsigned short dataLED = convertByteColumnTo16Bit(byteDisplay, indexColumnDisplaying);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(DURATION_COLUMN); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
durationFrame -= DURATION_COLUMN;
indexColumnDisplaying = (indexColumnDisplaying + 1) % sizeof(BIT_COLUMNS);
}
}
void animationLeftToRight(unsigned short durationFrame, byte bytesAnimation[], size_t totalColumns) {
for(byte offsetColumn = 0; offsetColumn < totalColumns; offsetColumn++) {
display8x8(bytesAnimation, totalColumns, offsetColumn, durationFrame);
}
}
void loop() {
animationLeftToRight(DURATION_FRAME, ANIMATION1_DATA, sizeof(ANIMATION1_DATA));
}
6. Code animation clock 2 lines:
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = { 8, 13, 7, 11, 0, 6, 1, 4 }; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = { 12, 2, 3, 9, 5, 10, 14, 15 }; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
const unsigned short DURATION_COLUMN = 2; // value too high make you see LED blink, should <=3 is OK
const unsigned short DURATION_MINUTE = 50; // default is 1000ms * 60s = 60 000ms, value current testing
const unsigned short TOTAL_MINUTES = 12 * 60; // total minutes in
const unsigned short START_MINUTES = 0; // value of minutes when start project, range from 0 to TOTAL_MINUTES
byte HOURS[12][8] = {
{0, 0, 0, 0, 12, 0, 0, 0},
{0, 0, 0, 0, 8, 4, 0, 0},
{0, 0, 0, 0, 8, 8, 0, 0},
{0, 0, 0, 0, 16, 16, 0, 0},
{0, 0, 0, 0, 16, 32, 0, 0},
{0, 0, 0, 0, 48, 0, 0, 0},
{0, 0, 0, 48, 0, 0, 0, 0},
{0, 0, 32, 16, 0, 0, 0, 0},
{0, 0, 16, 16, 0, 0, 0, 0},
{0, 0, 8, 8, 0, 0, 0, 0},
{0, 0, 4, 8, 0, 0, 0, 0},
{0, 0, 0, 12, 0, 0, 0, 0}
};
byte MINUTES[60][8] = {
{0, 0, 0, 0, 15, 0, 0, 0},
{0, 0, 0, 0, 14, 1, 0, 0},
{0, 0, 0, 0, 12, 3, 0, 0},
{0, 0, 0, 0, 8, 7, 0, 0},
{0, 0, 0, 0, 8, 6, 1, 0},
{0, 0, 0, 0, 8, 4, 3, 0},
{0, 0, 0, 0, 8, 4, 2, 1},
{0, 0, 0, 0, 8, 4, 2, 2},
{0, 0, 0, 0, 8, 4, 4, 2},
{0, 0, 0, 0, 8, 4, 4, 4},
{0, 0, 0, 0, 8, 8, 4, 4},
{0, 0, 0, 0, 8, 8, 8, 4},
{0, 0, 0, 0, 8, 8, 8, 8},
{0, 0, 0, 0, 16, 16, 8, 8},
{0, 0, 0, 0, 16, 16, 16, 8},
{0, 0, 0, 0, 16, 16, 16, 16},
{0, 0, 0, 0, 16, 16, 16, 32},
{0, 0, 0, 0, 16, 16, 32, 32},
{0, 0, 0, 0, 16, 32, 32, 32},
{0, 0, 0, 0, 16, 32, 32, 64},
{0, 0, 0, 0, 16, 32, 64, 64},
{0, 0, 0, 0, 16, 32, 64, 128},
{0, 0, 0, 0, 16, 32, 192, 0},
{0, 0, 0, 0, 16, 96, 128, 0},
{0, 0, 0, 0, 16, 224, 0, 0},
{0, 0, 0, 0, 48, 192, 0, 0},
{0, 0, 0, 0, 112, 128, 0, 0},
{0, 0, 0, 0, 240, 0, 0, 0},
{0, 0, 0, 48, 192, 0, 0, 0},
{0, 0, 0, 112, 128, 0, 0, 0},
{0, 0, 0, 240, 0, 0, 0, 0},
{0, 0, 128, 112, 0, 0, 0, 0},
{0, 0, 192, 48, 0, 0, 0, 0},
{0, 0, 224, 16, 0, 0, 0, 0},
{0, 128, 96, 16, 0, 0, 0, 0},
{0, 192, 32, 16, 0, 0, 0, 0},
{128, 64, 32, 16, 0, 0, 0, 0},
{64, 64, 32, 16, 0, 0, 0, 0},
{64, 32, 32, 16, 0, 0, 0, 0},
{32, 32, 32, 16, 0, 0, 0, 0},
{32, 32, 16, 16, 0, 0, 0, 0},
{32, 16, 16, 16, 0, 0, 0, 0},
{16, 16, 16, 16, 0, 0, 0, 0},
{16, 16, 8, 8, 0, 0, 0, 0},
{16, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{4, 8, 8, 8, 0, 0, 0, 0},
{4, 4, 8, 8, 0, 0, 0, 0},
{4, 4, 4, 8, 0, 0, 0, 0},
{2, 4, 4, 8, 0, 0, 0, 0},
{2, 2, 4, 8, 0, 0, 0, 0},
{1, 2, 4, 8, 0, 0, 0, 0},
{0, 3, 4, 8, 0, 0, 0, 0},
{0, 1, 6, 8, 0, 0, 0, 0},
{0, 0, 7, 8, 0, 0, 0, 0},
{0, 0, 3, 12, 0, 0, 0, 0},
{0, 0, 1, 14, 0, 0, 0, 0},
{0, 0, 0, 15, 0, 0, 0, 0},
{0, 0, 0, 3, 12, 0, 0, 0},
{0, 0, 0, 1, 14, 0, 0, 0}
};
byte indexColumnDisplaying = 0; // store current index column for avoid column on the right display less than column on the left
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
Serial.begin(9600);
}
unsigned short convertByteColumnTo16Bit(byte byteColumn, byte indexColumnTurnOn) {
unsigned short dataLED = 0;
// row is anode, set indexBit of row value to 1 to LED on, value 0 to LED off
for (byte indexBit = 0; indexBit < 8; indexBit++) {
bool isOn = byteColumn & (1 << indexBit);
if (isOn) {
dataLED |= 1 << BIT_ROWS[indexBit];
}
}
// column is cathod, set column value to 0 to LED on, value 1 to LED off, code below mark all other columns off
for (byte indexColumn = 0; indexColumn < sizeof(BIT_COLUMNS); indexColumn++) {
bool isOn = indexColumn == indexColumnTurnOn;
if (!isOn) {
dataLED |= 1 << BIT_COLUMNS[indexColumn];
}
}
return dataLED;
}
void display8x8(byte bytesDisplay[]) {
unsigned short duration = DURATION_MINUTE;
while (duration >= DURATION_COLUMN) {
byte byteDisplay = bytesDisplay[indexColumnDisplaying];
unsigned short dataLED = convertByteColumnTo16Bit(byteDisplay, indexColumnDisplaying);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(DURATION_COLUMN); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
duration -= DURATION_COLUMN;
indexColumnDisplaying = (indexColumnDisplaying + 1) % sizeof(BIT_COLUMNS);
}
}
void drawClock(unsigned short totalMinutes) {
Serial.print("totalMinutes=");
Serial.print(totalMinutes);
byte indexHour = totalMinutes / 60;
byte indexMinute = totalMinutes % 60;
Serial.print(", indexHour=");
Serial.print(indexHour);
Serial.print(", indexMinute=");
Serial.print(indexMinute);
byte bytesDisplay[sizeof(BIT_COLUMNS)];
for(byte indexColumn=0; indexColumn < sizeof(BIT_COLUMNS); indexColumn++){
bytesDisplay[indexColumn] = HOURS[indexHour][indexColumn] | MINUTES[indexMinute][indexColumn]; // combine data from HOURS & MINUTES
}
display8x8(bytesDisplay);
Serial.println(" ");
unsigned short nextMinute = (totalMinutes+1) % TOTAL_MINUTES;
drawClock(nextMinute);
}
void loop() {
drawClock(START_MINUTES);
}
replace value below to display hour as dot
byte HOURS[12][8] = {
{0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 2},
{0, 0, 0, 0, 0, 0, 0, 16},
{0, 0, 0, 0, 0, 0, 0, 64},
{0, 0, 0, 0, 0, 0, 128, 0},
{0, 0, 0, 128, 0, 0, 0, 0},
{0, 128, 0, 0, 0, 0, 0, 0},
{64, 0, 0, 0, 0, 0, 0, 0},
{16, 0, 0, 0, 0, 0, 0, 0},
{2, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0}
};
replace value below to change clock display text
byte HOURS[24][8] = {
{15, 9, 15, 0, 15, 9, 15, 0},
{15, 9, 15, 0, 9, 15, 8, 0},
{15, 9, 15, 0, 13, 11, 11, 0},
{15, 9, 15, 0, 9, 11, 15, 0},
{15, 9, 15, 0, 3, 2, 15, 0},
{15, 9, 15, 0, 11, 11, 13, 0},
{15, 9, 15, 0, 15, 10, 14, 0},
{15, 9, 15, 0, 1, 1, 15, 0},
{15, 9, 15, 0, 14, 11, 15, 0},
{15, 9, 15, 0, 7, 5, 15, 0},
{9, 15, 8, 0, 15, 9, 15, 0},
{9, 15, 8, 0, 9, 15, 8, 0},
{9, 15, 8, 0, 13, 11, 11, 0},
{9, 15, 8, 0, 9, 11, 15, 0},
{9, 15, 8, 0, 3, 2, 15, 0},
{9, 15, 8, 0, 11, 11, 13, 0},
{9, 15, 8, 0, 15, 10, 14, 0},
{9, 15, 8, 0, 1, 1, 15, 0},
{9, 15, 8, 0, 14, 11, 15, 0},
{9, 15, 8, 0, 7, 5, 15, 0},
{13, 11, 11, 0, 15, 9, 15, 0},
{13, 11, 11, 0, 9, 15, 8, 0},
{13, 11, 11, 0, 13, 11, 11, 0},
{13, 11, 11, 0, 9, 11, 15, 0}
};
byte MINUTES[60][8] = {
{0, 240, 144, 240, 0, 240, 144, 240},
{0, 240, 144, 240, 0, 144, 240, 128},
{0, 240, 144, 240, 0, 208, 176, 176},
{0, 240, 144, 240, 0, 144, 176, 240},
{0, 240, 144, 240, 0, 48, 32, 240},
{0, 240, 144, 240, 0, 176, 176, 208},
{0, 240, 144, 240, 0, 240, 160, 224},
{0, 240, 144, 240, 0, 16, 16, 240},
{0, 240, 144, 240, 0, 224, 176, 240},
{0, 240, 144, 240, 0, 112, 80, 240},
{0, 144, 240, 128, 0, 240, 144, 240},
{0, 144, 240, 128, 0, 144, 240, 128},
{0, 144, 240, 128, 0, 208, 176, 176},
{0, 144, 240, 128, 0, 144, 176, 240},
{0, 144, 240, 128, 0, 48, 32, 240},
{0, 144, 240, 128, 0, 176, 176, 208},
{0, 144, 240, 128, 0, 240, 160, 224},
{0, 144, 240, 128, 0, 16, 16, 240},
{0, 144, 240, 128, 0, 224, 176, 240},
{0, 144, 240, 128, 0, 112, 80, 240},
{0, 208, 176, 176, 0, 240, 144, 240},
{0, 208, 176, 176, 0, 144, 240, 128},
{0, 208, 176, 176, 0, 208, 176, 176},
{0, 208, 176, 176, 0, 144, 176, 240},
{0, 208, 176, 176, 0, 48, 32, 240},
{0, 208, 176, 176, 0, 176, 176, 208},
{0, 208, 176, 176, 0, 240, 160, 224},
{0, 208, 176, 176, 0, 16, 16, 240},
{0, 208, 176, 176, 0, 224, 176, 240},
{0, 208, 176, 176, 0, 112, 80, 240},
{0, 144, 176, 240, 0, 240, 144, 240},
{0, 144, 176, 240, 0, 144, 240, 128},
{0, 144, 176, 240, 0, 208, 176, 176},
{0, 144, 176, 240, 0, 144, 176, 240},
{0, 144, 176, 240, 0, 48, 32, 240},
{0, 144, 176, 240, 0, 176, 176, 208},
{0, 144, 176, 240, 0, 240, 160, 224},
{0, 144, 176, 240, 0, 16, 16, 240},
{0, 144, 176, 240, 0, 224, 176, 240},
{0, 144, 176, 240, 0, 112, 80, 240},
{0, 48, 32, 240, 0, 240, 144, 240},
{0, 48, 32, 240, 0, 144, 240, 128},
{0, 48, 32, 240, 0, 208, 176, 176},
{0, 48, 32, 240, 0, 144, 176, 240},
{0, 48, 32, 240, 0, 48, 32, 240},
{0, 48, 32, 240, 0, 176, 176, 208},
{0, 48, 32, 240, 0, 240, 160, 224},
{0, 48, 32, 240, 0, 16, 16, 240},
{0, 48, 32, 240, 0, 224, 176, 240},
{0, 48, 32, 240, 0, 112, 80, 240},
{0, 176, 176, 208, 0, 240, 144, 240},
{0, 176, 176, 208, 0, 144, 240, 128},
{0, 176, 176, 208, 0, 208, 176, 176},
{0, 176, 176, 208, 0, 144, 176, 240},
{0, 176, 176, 208, 0, 48, 32, 240},
{0, 176, 176, 208, 0, 176, 176, 208},
{0, 176, 176, 208, 0, 240, 160, 224},
{0, 176, 176, 208, 0, 16, 16, 240},
{0, 176, 176, 208, 0, 224, 176, 240},
{0, 176, 176, 208, 0, 112, 80, 240}
};
7. last animation:
const byte BIT_ORDER = MSBFIRST; // Most Significant Bit First = 1
const byte PIN_LATCH_ST_CP = 8; // Pin connected to ST_CP of 74HC595
const byte PIN_DATA_DS = 11; // Pin connected to DS of 74HC595. The pin on which to output each bit. Allowed data types: int. Should be ~ pin.
const byte PIN_CLOCK_SHCP = 12; // Pin connected to SH_CP of 74HC595. The pin to toggle once the PIN_DATA_DS has been set to the correct value. Allowed data types: int.
const byte BIT_ROWS[] = {8, 13, 7, 11, 0, 6, 1, 4}; // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {12, 2, 3, 9, 5, 10, 14, 15}; // index column bits: C1/Q3, Q1/C2, C3, C4, C5, C6, C7, C8; index value start from 0, -1 each pin
unsigned short DURATION_COLUMN = 2; // value too high make you see LED blink, should <=3 is OK
unsigned short DURATION_FRAME = 500;
byte ANIMATION1_DATA[] = {
0,0,0,63,0,0,0,0,0,0,30,33,30,0,0,0,0,30,33,33,33,30,0,0,12,18,33,33,33,18,12,0,0,30,33,33,33,30,0,0,0,0,30,33,30,0,0,0,0,0,0,63,0,0,0,0,
0,0,0,24,24,0,0,0,0,0,24,36,36,24,0,0,0,24,36,66,66,36,24,0,24,36,66,129,129,66,36,24,36,66,129,0,0,129,66,36,66,129,0,0,0,0,129,66,129,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,129,66,129,0,0,0,0,129,66,36,66,129,0,0,129,66,36,24,36,66,129,129,66,36,24,0,24,36,66,66,36,24,0,0,0,24,36,36,24,0,0,0,0,0,24,24,0,0,0 ,
255,129,129,129,129,129,129,255,0,126,66,66,66,66,126,0,0,0,60,36,36,60,0,0,0,0,0,24,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,0,60,36,36,60,0,0,0,126,66,66,66,66,126,0,255,129,129,129,129,129,129,255
};
byte indexColumnDisplaying = 0; // store current index column for avoid column on the right display less than column on the left
void setup() {
pinMode(PIN_LATCH_ST_CP, OUTPUT);
pinMode(PIN_DATA_DS, OUTPUT);
pinMode(PIN_CLOCK_SHCP, OUTPUT);
}
unsigned short convertByteColumnTo16Bit(byte byteColumn, byte indexColumnTurnOn) {
unsigned short dataLED = 0;
// row is anode, set indexBit of row value to 1 to LED on, value 0 to LED off
for (byte indexBit = 0; indexBit < 8; indexBit++) {
bool isOn = byteColumn & (1 << indexBit);
if (isOn) {
dataLED |= 1 << BIT_ROWS[indexBit];
}
}
// column is cathod, set column value to 0 to LED on, value 1 to LED off, code below mark all other columns off
for(byte indexColumn = 0; indexColumn < sizeof(BIT_COLUMNS); indexColumn++){
bool isOn = indexColumn == indexColumnTurnOn;
if (!isOn) {
dataLED |= 1 << BIT_COLUMNS[indexColumn];
}
}
return dataLED;
}
void display8x8(byte bytesAnimation[], int offsetColumn, unsigned short durationFrame) {
while(durationFrame >= DURATION_COLUMN) {
byte byteDisplay = bytesAnimation[offsetColumn + indexColumnDisplaying];
unsigned short dataLED = convertByteColumnTo16Bit(byteDisplay, indexColumnDisplaying);
digitalWrite(PIN_LATCH_ST_CP, LOW); // ground PIN_LATCH_ST_CP and hold low for as long as you are transmitting
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED >> 8); // shift out highbyte, it's U2 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
shiftOut(PIN_DATA_DS, PIN_CLOCK_SHCP, BIT_ORDER, dataLED); // shift out lowbyte, it's U1 in proteus, doc: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/
digitalWrite(PIN_LATCH_ST_CP, HIGH); // return the latch pin high to signal chip that it no longer needs to listen for information
delay(DURATION_COLUMN); // delay(ms), doc: https://www.arduino.cc/reference/en/language/functions/time/delay/
durationFrame -= DURATION_COLUMN;
indexColumnDisplaying = (indexColumnDisplaying + 1) % sizeof(BIT_COLUMNS);
}
}
void animationDisplayFrameByFrame(unsigned short durationFrame, byte bytesAnimation[], size_t totalColumns) {
for(byte offsetColumn = 0; offsetColumn < totalColumns; offsetColumn+=sizeof(BIT_COLUMNS)) {
display8x8(bytesAnimation, offsetColumn, durationFrame);
}
}
void loop() {
animationDisplayFrameByFrame(DURATION_FRAME, ANIMATION1_DATA, sizeof(ANIMATION1_DATA));
}
No comments:
Post a Comment