Saturday, December 18, 2021

Arduino Uno - 4-Bit LED Digital Module - 3461BS - 5 pins - without library but can display whatever you want


Require components:

1x Arduino Uno

5x wires

1x 4-Bit LED Digital Module using 4-digit LED display model 3461BS


Link 256 states of 7 segment digit

https://zxcongducxz.000webhostapp.com/arduino/SevenSegmentLEDDisplay.html


Video:


Code:

// 4-Bit LED Digital Module with 2x 74HC595D-chip, there are 5 pins from top to bottom:
// VCC  : pin 5V; 
// SCLK : pin A0; 
// SRLK : pin A1; 
// DIO  : pin A3
// GND  : pin GND
#define PIN_SCLK A0 // serial clock, set LOW & HIGH after set PIN_DIO
#define PIN_RCLK A1 // register clock, set LOW & HIGH after write digit
#define PIN_DIO  A2 // set PIN_DIO set index bit from 0,1,2,3,4,5,6,7 = A,B,C,D,E,F,G,DP
const byte TOTAL_DIGITS = 4; // default is 4, you may need to change this value depends on amounts of digits on your module, i'm not sure will it work if changed, good luck ;))
const byte BYTES_0_TO_9[] = { // list of bytes to display from top to bottom, 1 byte = 8 bits, bit starts from right to left, from left to right are DotPoint,G,F,E,D,C,B,A
  B00111111, // 0
  B00000110, // 1
  B01011011, // 2
  B01001111, // 3
  B01100110, // 4 
  B01101101, // 5
  B01111101, // 6
  B00000111, // 7
  B01111111, // 8
  B01101111, // 9
};
const unsigned int POW_10[] = { // cache value for saving performance, https://www.arduino.cc/reference/en/language/functions/math/pow/
  1,        // pow(10, 0);
  10,       // pow(10, 1);
  100,      // pow(10, 2);
  1000,     // pow(10, 3);
  10000,    // pow(10, 4);
  100000,   // pow(10, 5);
  1000000,  // pow(10, 6);
  10000000, // pow(10, 7);
};
const byte BYTE_NEGATIVE = B01000000;
const byte BYTE_CELSIUS = B00111001;
const byte BYTE_FAHRENHEIT = B01110001;
const byte BYTE_DOT_POINT = B10000000;
const byte BYTE_VOLTAGE = B00111110;
const byte BYTE_AMPERE = B01110111;
const byte MIN_PERCENT = 0;
const byte MAX_PERCENT = 100;

void setup() {
  pinMode(PIN_SCLK, OUTPUT);
  pinMode(PIN_RCLK, OUTPUT);
  pinMode(PIN_DIO, OUTPUT);

  digitalWrite(PIN_SCLK, HIGH);
  digitalWrite(PIN_RCLK, HIGH);
  digitalWrite(PIN_DIO, HIGH);
}

void write(unsigned short durationbyte dataPGFEDCBA[]) {
  do {
    for(byte indexDigit = 0; indexDigit < TOTAL_DIGITS; indexDigit++) { // write each digits from most right to most left
      digitalWrite(PIN_RCLK, LOW);
      shiftOut(PIN_DIO, PIN_SCLK, MSBFIRST, ~dataPGFEDCBA[indexDigit]); // shift out byte display 8 bit display PGFEDCBA, because of we are using 4-digit common anode, need inverse bit by using "~" 
      shiftOut(PIN_DIO, PIN_SCLK, MSBFIRST, 1 << indexDigit); // shift out byte display 8 bit display digits
      // there is another way to set 16 bits, instead of shiftOut
      // is make 3 line of code for 16 times, just change isOn variable for each bit of bytePGFEDCBA & byteDigit from most left to most right ;))
      // digitalWrite(PIN_DIO, isOn); digitalWrite(PIN_DIO, isOn); digitalWrite(PIN_SCLK, HIGH);
      digitalWrite(PIN_RCLK, HIGH);
    }
  } while(duration-- > 0); // avoid case duration = 0--
}

void writeInt(unsigned short durationint number) { // 4 digit display from -999 to 9999, short is enough for 4 digit, but i wanted to support up to 8 digits, then i use int
  byte dataPGFEDCBA[TOTAL_DIGITS];
  
  byte totalDigit;  
  if(number >= 0) { // zero and positive numbers
    totalDigit = TOTAL_DIGITS; // show full digits
  } else { // negative numbers
    totalDigit = TOTAL_DIGITS - 1; // can not show full digits because of most left digit display negative symbol
    dataPGFEDCBA[totalDigit] = BYTE_NEGATIVE; // show negative symbol "-";
    number *= -1; // convert to positive number
  }
  for(byte indexDigit = 0; indexDigit < totalDigit; indexDigit++) {
    dataPGFEDCBA[indexDigit] = BYTES_0_TO_9[(unsigned short)(number / POW_10[indexDigit]) % 10];
  }
  
  write(duration, dataPGFEDCBA);
}

void writeFloat(unsigned short durationfloat number) { // 4 digit display from -99.9 to 999.9
  byte dataPGFEDCBA[TOTAL_DIGITS];
  
  byte totalDigit;  
  if(number >= 0) { // zero and positive numbers
    totalDigit = TOTAL_DIGITS; // show full digits
  } else { // negative numbers
    totalDigit = TOTAL_DIGITS - 1; // can not show full digits because of most left digit display negative symbol
    dataPGFEDCBA[totalDigit] = BYTE_NEGATIVE; // show negative symbol "-";
    number *= -1; // convert to positive number
  }
  dataPGFEDCBA[0] = BYTES_0_TO_9[(unsigned short)(number * 10) % 10]; // number after dot
  dataPGFEDCBA[1] = BYTES_0_TO_9[(unsigned short)(number) % 10] | BYTE_DOT_POINT;  // number before dot  
  for(byte indexDigit = 2; indexDigit < totalDigit; indexDigit++) {
    dataPGFEDCBA[indexDigit] = BYTES_0_TO_9[(unsigned short)(number / POW_10[indexDigit - 1]) % 10]; // remain numbers
  }
  
  write(duration, dataPGFEDCBA);
}

void writeIntUnit(unsigned short durationint numberbyte byteUnit) { // 4 digit display from -99 to 999, short is enough for 4 digit, but i wanted to support up to 8 digits, then i use int
  byte dataPGFEDCBA[TOTAL_DIGITS];
  dataPGFEDCBA[0] = byteUnit; // write unit
  
  byte totalDigit;  
  if(number >= 0) { // zero and positive numbers
    totalDigit = TOTAL_DIGITS; // show full digits
  } else { // negative numbers
    totalDigit = TOTAL_DIGITS - 1; // can not show full digits because of most left digit display negative symbol
    dataPGFEDCBA[totalDigit] = BYTE_NEGATIVE; // show negative symbol "-";
    number *= -1; // convert to positive number
  }
  for(byte indexDigit = 1; indexDigit < totalDigit; indexDigit++) {
    dataPGFEDCBA[indexDigit] = BYTES_0_TO_9[(unsigned short)(number / POW_10[indexDigit - 1]) % 10];
  }
  write(duration, dataPGFEDCBA);
}

void writeFloatUnit(unsigned short durationfloat numberbyte byteUnit) { // 4 digit display from -9.9 to 99.9
  byte dataPGFEDCBA[TOTAL_DIGITS];

  if(number >= 0) { // zero and positive numbers
    dataPGFEDCBA[3] = BYTES_0_TO_9[(unsigned short)(number / 10) % 10];
  } else { // negative numbers
    dataPGFEDCBA[3] = BYTE_NEGATIVE; // show negative symbol "-";
    number *= -1; // convert to positive number
  }
  dataPGFEDCBA[0] = byteUnit; // write symbol
  dataPGFEDCBA[1] = BYTES_0_TO_9[(unsigned short)(number * 10) % 10]; // number after dot
  dataPGFEDCBA[2] = BYTES_0_TO_9[(unsigned short)(number) % 10] | BYTE_DOT_POINT; // number before dot
  
  write(duration, dataPGFEDCBA);
}

void writeTime(unsigned short durationbyte hoursbyte minutes) {
  byte dataPGFEDCBA[TOTAL_DIGITS];
  
  dataPGFEDCBA[0] = BYTES_0_TO_9[minutes % 10];
  dataPGFEDCBA[1] = BYTES_0_TO_9[minutes / 10 % 10];
  dataPGFEDCBA[2] = BYTES_0_TO_9[hours % 10] | BYTE_DOT_POINT;
  dataPGFEDCBA[3] = BYTES_0_TO_9[hours / 10 % 10];
  
  write(duration, dataPGFEDCBA);
}

void writeText(unsigned short durationbyte data[]) { // length of data == TOTAL_DIGITS
  byte dataPGFEDCBA[TOTAL_DIGITS];
  for(byte indexDigit = 0; indexDigit < TOTAL_DIGITS; indexDigit++) {
    dataPGFEDCBA[indexDigit] = data[TOTAL_DIGITS - indexDigit - 1];
  }
  write(duration, dataPGFEDCBA);
}

void writePercent(unsigned short durationbyte data[], byte animationLengthbyte percent) { // support percent from 0 to 100
  byte dataPGFEDCBA[TOTAL_DIGITS];
  for(byte indexDigit = 0; indexDigit < TOTAL_DIGITS; indexDigit++) { // check all digits from most right to most left
    dataPGFEDCBA[indexDigit] = 0; // initialize value = 0, change later
    for(byte indexAnimation = 0; indexAnimation < animationLength; indexAnimation++) {
      byte percentCurrent = MAX_PERCENT * ((TOTAL_DIGITS - indexDigit) * animationLength - indexAnimation) / (TOTAL_DIGITS * animationLength);
      if(percentCurrent <= percent) { // is percent can be display
        dataPGFEDCBA[indexDigit] = data[indexAnimation];
        break
      }
    }
  }
  write(duration, dataPGFEDCBA);
}

void writeTextRunLeft(unsigned short delayMovebyte data[], unsigned short length) {
  for(unsigned short offset = 0; offset < length; offset++) {
    // slice
    byte dataPGFEDCBA[TOTAL_DIGITS];
    for(byte indexDigit = 0; indexDigit < TOTAL_DIGITS && indexDigit < length; indexDigit++) {
      dataPGFEDCBA[indexDigit] = data[(offset + indexDigit) % length];
    }
    writeText(delayMove, dataPGFEDCBA);
  }
}

void testInt() {
  for(int value = -999; value <= 9999; value++){
    writeInt(0, value);
  }
}

void testFloat() {
  for(float value = -99.9; value <= 999.9; value+=0.5){
    writeFloat(10, value);
  }
}

void testIntUnit() {
  for(int value = -99; value <= 999; value++){
    writeIntUnit(10, value, BYTE_CELSIUS);
  }
  for(int value = -99; value <= 999; value++){
    writeIntUnit(10, value, BYTE_FAHRENHEIT);
  }
  for(int value = -99; value <= 999; value++){
    writeIntUnit(10, value, BYTE_VOLTAGE);
  }
  for(int value = -99; value <= 999; value++){
    writeIntUnit(10, value, BYTE_AMPERE);
  }
}

void testFloatUnit() {
  for(float value = -9.9; value <= 99.9; value += 0.5){
    writeFloatUnit(20, value, BYTE_CELSIUS);
  }
  for(float value = -9.9; value <= 99.9; value += 0.5){
    writeFloatUnit(20, value, BYTE_FAHRENHEIT);
  }
  for(float value = -9.9; value <= 99.9; value += 0.5){
    writeFloatUnit(20, value, BYTE_VOLTAGE);
  }
  for(float value = -9.9; value <= 99.9; value += 0.5){
    writeFloatUnit(20, value, BYTE_AMPERE);
  }
}

void testTime() {
  for(byte hour = 0; hour < 24; hour++) {
    for(byte minute = 0; minute < 60; minute++){
      writeTime(10, hour, minute);
    }
  }
}

void testProgress() {
  byte durationPercent = 20;
  
  byte percent = 0;
  byte dataPGFEDCBA1[] = {B00110110, B00110000};
  do { writePercent(durationPercent, dataPGFEDCBA1, sizeof(dataPGFEDCBA1), percent); } while(++percent <= MAX_PERCENT); // fade in
  do { writePercent(durationPercent, dataPGFEDCBA1, sizeof(dataPGFEDCBA1), percent); } while(percent-- > 0); // fade out

  percent = 0;
  byte dataPGFEDCBA2[] = {B00110110, B00110010, B00110000, B00100000};
  do { writePercent(durationPercent, dataPGFEDCBA2, sizeof(dataPGFEDCBA2), percent); } while(++percent <= MAX_PERCENT); // fade in
  do { writePercent(durationPercent, dataPGFEDCBA2, sizeof(dataPGFEDCBA2), percent); } while(percent-- > 0); // fade out

  percent = 0;
  byte dataPGFEDCBA3[] = {B01001001,B01000001,B00000001};
  do { writePercent(durationPercent, dataPGFEDCBA3, sizeof(dataPGFEDCBA3), percent); } while(++percent <= MAX_PERCENT); // fade in
  do { writePercent(durationPercent, dataPGFEDCBA3, sizeof(dataPGFEDCBA3), percent); } while(percent-- > 0); // fade out
}

void testText() {
  byte dataPGFEDCBA[] = {
    B01110011, // P
    B00110000, // l, I (left)
    B11011100, // a
    B01101110, // Y, y
  };  
  writeText(1000, dataPGFEDCBA);
}

void testRunningText() {
  byte dataPGFEDCBA[] = {
    B01110110, // H
    B01111001, // E
    B00110110, // ll
    B01011100, // o
    B00000000, // (space)
    B00111110, // U,V
    B00111110, // U,V
    B01011100, // o
    B01010000, // r
    B00110000, // l, I (left)
    B01011110, // d
    B00000000, // (space)
  };
  writeTextRunLeft(1000, dataPGFEDCBA, sizeof(dataPGFEDCBA));
}

void loop() 
{
  testInt();
  testFloat();
  testIntUnit();
  testFloatUnit();
  testTime();
  testProgress();
  testText();
  testRunningText();
}

If my code can not be used, you may need to use other libraries on the internet:

https://github.com/monotok/FourBitDisplay

https://github.com/0xF6/TM74

https://github.com/avishorp/TM1637

https://github.com/DeanIsMe/SevSeg

https://github.com/Erriez/ErriezRobotDyn4DigitDisplay

https://github.com/bremme/arduino-tm1637


Tuesday, December 14, 2021

Arduino Uno - Traffic Light LED Red/Yellow/Green



 Require components:

1x Arduino Uno

1x Traffic Light

4x red/black/yellow/green wires


Video:


Code:

const byte PIN_GREEN = 11;
const byte PIN_YELLOW = 10;
const byte PIN_RED = 9;

void setup() {
  pinMode(PIN_GREEN, OUTPUT);
  pinMode(PIN_YELLOW, OUTPUT);
  pinMode(PIN_RED, OUTPUT);
  Serial.begin(9600);
}

void setColor(byte redbyte yellowbyte green) {
  Serial.print("setColor(");
  Serial.print(red);
  Serial.print(", ");
  Serial.print(yellow);
  Serial.print(", ");
  Serial.print(green);
  Serial.println(") ");
  analogWrite(PIN_RED, red);
  analogWrite(PIN_YELLOW, yellow);
  analogWrite(PIN_GREEN, green);
}

void show1LED() {
  Serial.println("show1LED()");
  setColor(25500); delay(1000); // red
  setColor(02550); delay(1000); // yellow
  setColor(00255); delay(1000); // green
}

void show2LEDs() {
  Serial.println("show2LEDs()");
  setColor(2552550); delay(1000); // red & yellow
  setColor(0255255); delay(1000); // yellow & green
  setColor(2550255); delay(1000); // red & green
}

void show3LEDs() {
  Serial.println("show3LEDs()");
  setColor(000); delay(1000);       // turn off
  setColor(255255255); delay(1000); // turn on all colors
  setColor(000); delay(1000);       // turn off
}

void fadeColor(byte redbyte yellowbyte green) {
  Serial.print("fadeColor(");
  Serial.print(red);
  Serial.print(", ");
  Serial.print(yellow);
  Serial.print(", ");
  Serial.println(green);

  byte total = 8; // should mod for 256 = 0;
  for(byte current = 0; current <= total; current++) { // fade in
    byte r = red / total * current ;
    byte y = yellow / total * current;
    byte g = green / total * current;
    setColor(r, y, g);
    delay(100);    
  }

  for(byte current = total - 1; current > 0; current--) { // fade out
    red = red / total * current;
    yellow = yellow / total * current;
    green = green / total * current;
    setColor(red, yellow, green);
    delay(100);
  }

  setColor(000);
  delay(100);
}

void fade1LED() {
  Serial.println("fade1LED()");
  fadeColor(25500); delay(1000); // red
  fadeColor(02550); delay(1000); // yellow
  fadeColor(00255); delay(1000); // green
}

void fade2LEDs() {
  Serial.println("fade2LEDs()");
  fadeColor(2552550); delay(1000); // red & yellow
  fadeColor(0255255); delay(1000); // yellow & green
  fadeColor(2550255); delay(1000); // red & green
}

void fade3LEDs() {
  Serial.println("fade3LEDs()");
  fadeColor(000); delay(1000);       // turn off
  fadeColor(255255255); delay(1000); // turn on all colors
  fadeColor(000); delay(1000);       // turn off
}

void showAllColors() {
  Serial.println("showAllColors()");
  byte increasement = 32; // should mod for 256 = 0, ex: 1, 2, 4, 6, 8, 16, 32, 64, 128, 256
  for(short red = 0; red <= 256; red += increasement) {
    for(short yellow = 0; yellow <= 256; yellow += increasement) {
      for(short green = 0; green <= 256; green += increasement) {          
        setColor(min(255, red), min(255, yellow), min(255, green));
        delay(100);
      }
    }
  }
}

void loop() {
  show1LED();
  show2LEDs();
  show3LEDs();
  
  fade1LED();
  fade2LEDs();
  fade3LEDs();
  
  showAllColors();
}



Monday, December 13, 2021

Arduino Uno - HW-481 CNT5 (Ky034) - 7-Colour flash module

 


Require components for test 3.3V:

1x Arduino Uno

1x red wire

1x black wire

1x HW-481 CNT5

Code effect 1:

const byte PIN_OUTPUT = 11;

void setup() {
  pinMode(PIN_OUTPUT, OUTPUT);
  digitalWrite(PIN_OUTPUT, HIGH);
}

void loop() {}



Require components for test pin:

1x Arduino Uno

2x red wire

2x black wire

1x HW-481 CNT5

Code effect 2:

const byte PIN_OUTPUT = 11; // the PWM pin the LED is attached to
byte brightness = 0;         // how bright the LED is
int fadeAmount = 5;         // how many points to fade the LED by

void setup() {
  pinMode(PIN_OUTPUT, OUTPUT); // declare pin output
}

void loop() {
  analogWrite(PIN_OUTPUT, brightness);  // set the brightness of pin
  brightness = brightness + fadeAmount;  // change the brightness for next time through the loop
  if (brightness <= 0 || brightness >= 255) { // reverse the direction of the fading at the ends of the fade
    fadeAmount = -fadeAmount;
  }
  delay(30);  // wait for 30 milliseconds to see the dimming effect
}


Code effect 3:

const byte PIN_OUTPUT = 11; // the PWM pin the LED is attached to
const byte FADE_AMOUNT = 5; // how many points to fade the LED by
const byte DELAY_DIMMING_EFFECT = 30; // milisecond
const unsigned short DELAY_FLASH_EFFECT = 10000; // milisecond
const unsigned short DELAY_END_ANIMATION = 3000; // milisecond

void setup() {
  pinMode(PIN_OUTPUT, OUTPUT); // declare pin output
}

void loop() {
  for(short brightness = 0; brightness <= 255; brightness += FADE_AMOUNT) {
    analogWrite(PIN_OUTPUT, brightness);  // set fade in
    delay(DELAY_DIMMING_EFFECT);
  }
  
  delay(DELAY_FLASH_EFFECT); // default flash effect

  for(short brightness = 255 - FADE_AMOUNT; brightness >= 0; brightness -= FADE_AMOUNT) {
    analogWrite(PIN_OUTPUT, brightness);  // set fade out
    delay(DELAY_DIMMING_EFFECT);
  }

  delay(DELAY_END_ANIMATION); // turn off
}

Video:








Sunday, December 12, 2021

LED RGB Common cathode - HW-479 2037 (Ky016)


 Require components:

1x Arduino Uno

4x wires

1x LED RGB HW-479 (K016)


Video:


Code test 1:

int redpin = 11;
int greenpin = 10;
int bluepin = 9;

int val;

void setup() {
  pinMode(redpin, OUTPUT);
  pinMode(bluepin, OUTPUT);
  pinMode(greenpin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  for(val = 255; val > 0; val--)
  {
    analogWrite(11, val);
    analogWrite(10255 - val);
    analogWrite(9128 - val);

    Serial.println(val, DEC);
    delay(5); 
  }
  for(val = 0; val < 255; val++)
  {
    analogWrite(11, val);
    analogWrite(10255 - val);
    analogWrite(9128 - val);
    
    Serial.println(val, DEC);
    delay(5); 
  }
}

Code switch basic colors:

const byte PIN_RED = 11;
const byte PIN_GREEN = 10;
const byte PIN_BLUE = 9;

const byte COLOR_RED[] = {255,0,0};
const byte COLOR_LIME[] = {0,255,0};
const byte COLOR_BLUE[] = {0,0,255};
const byte COLOR_WHITE[] = {255,255,255};
const byte COLOR_YELLOW[] = {255,255,0};
const byte COLOR_CYAN[] = {0,255,255};
const byte COLOR_MAGENTA[] = {255,0,255};
const byte COLOR_SILVER[] = {192,192,192};
const byte COLOR_GRAY[] = {128,128,128};
const byte COLOR_MAROON[] = {128,0,0};
const byte COLOR_OLIVE[] = {128,128,0};
const byte COLOR_GREEN[] = {0,128,0};
const byte COLOR_PURPLE[] = {128,0,128};
const byte COLOR_TEAL[] = {0,128,128};
const byte COLOR_NAVY[] = {0,0,128};

const unsigned short DURATION_COLOR = 1000;

void setup() {
  pinMode(PIN_RED, OUTPUT);
  pinMode(PIN_GREEN, OUTPUT);
  pinMode(PIN_BLUE, OUTPUT);
}

void setColor(byte colors[]) {
  analogWrite(PIN_RED, colors[0]);
  analogWrite(PIN_GREEN, colors[1]);
  analogWrite(PIN_BLUE, colors[2]);
}

void loop() {
  setColor(COLOR_RED); delay(DURATION_COLOR);
  setColor(COLOR_LIME); delay(DURATION_COLOR);
  setColor(COLOR_BLUE); delay(DURATION_COLOR);
  setColor(COLOR_WHITE); delay(DURATION_COLOR);
  setColor(COLOR_YELLOW); delay(DURATION_COLOR);
  setColor(COLOR_MAGENTA); delay(DURATION_COLOR);
  setColor(COLOR_SILVER); delay(DURATION_COLOR);
  setColor(COLOR_GRAY); delay(DURATION_COLOR);
  setColor(COLOR_MAROON); delay(DURATION_COLOR);
  setColor(COLOR_OLIVE); delay(DURATION_COLOR);
  setColor(COLOR_GREEN); delay(DURATION_COLOR);
  setColor(COLOR_PURPLE); delay(DURATION_COLOR);
  setColor(COLOR_TEAL); delay(DURATION_COLOR);
  setColor(COLOR_NAVY); delay(DURATION_COLOR);
}


Color switch multi colors

const byte PIN_RED = 11;
const byte PIN_GREEN = 10;
const byte PIN_BLUE = 9;

const byte AMOUNT_INCREASE = 32;  // min=1ms, but 255*255*255 = 16,581,375ms = 276 minutes, values should be 8, 16, 32, 64, 128
const unsigned short DURATION_COLOR = 100;  // min=1ms, delay next color

void setup() {
  pinMode(PIN_RED, OUTPUT);
  pinMode(PIN_GREEN, OUTPUT);
  pinMode(PIN_BLUE, OUTPUT);
  Serial.begin(9600);
}

void setColor(byte redbyte greenbyte blue) {
  analogWrite(PIN_RED, red);
  analogWrite(PIN_GREEN, green);
  analogWrite(PIN_BLUE, blue);
  Serial.print(red);
  Serial.print(":");
  Serial.print(green);
  Serial.print(":");
  Serial.println(blue);
}

void loop() {
  byte red = 0;
  byte green = 0;
  byte blue = 0;

  for(byte red = 0; red <= 255; red = min(255, red + AMOUNT_INCREASE)){
    for(byte green = 0; green <= 255; green = min(255, green + AMOUNT_INCREASE)){
      for(byte blue = 0; blue <= 255; blue = min(255, blue + AMOUNT_INCREASE)){
        setColor(red, green, blue);
        delay(DURATION_COLOR);

        if(blue == 255break;
      }
      if(green == 255break;
    }
    if(red == 255break;
  }
}


Photoresistors - The Photoconductive Cell - LDR - PGM5506 - Arduino Uno

 Require components:

1x PGM5506 

4x wires

1x LED 5mm

1x Resistor 10k

1x Resistor 200ohm




Code test:
void setup() {
  Serial.begin(9600);
}

void loop() {
  int value = analogRead(A0);
  Serial.println("Analog value : ");
  Serial.println(value);
  delay(200);
}

Code turn on LED when PGM5506 in low light:
const int PIN_LED = 9;
const int LIGHT_MIN = 350; // you may change this value to 0, depends on your environment
const int LIGHT_MAX = 750; // you may change this value to 1024, depends on your environment

void setup(){}

void loop() {
  int valueRead = analogRead(A0); // analogWrite values from 0 to 255, https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
  byte valueWrite = 0;  // analogRead values go from 0 to 1023, https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/
  if(valueRead <= LIGHT_MIN) {
    valueWrite = 255;
  } else if(valueRead >= LIGHT_MAX) {
    valueWrite = 0;
  } else {
    valueWrite = map(valueRead, LIGHT_MIN, LIGHT_MAX, 2550);
  }
  analogWrite(PIN_LED, valueWrite);
  delay(100);
}






Sunday, December 5, 2021

LED Matrix 8x8

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[] = {8137110614};           // 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[] = {122395101415};      // 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[] = {8137110614};           // 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[] = {122395101415};      // 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[] = {8137110614};           // 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[] = {122395101415};      // 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[] = {8137110614};           // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {122395101415};      // 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 byteColumnbyte 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 offsetColumnunsigned 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 durationFramebyte 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[] = {8137110614};           // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {122395101415};      // 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 byteColumnbyte 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 totalColumnsint offsetColumnunsigned 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 durationFramebyte 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[] = {8137110614};           // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {122395101415};      // 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 byteColumnbyte 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 totalColumnsint offsetColumnunsigned 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 durationFramebyte 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[] = { 8137110614 };       // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = { 122395101415 };  // 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] = {
  {000012000},
  {00008400},
  {00008800},
  {0000161600},
  {0000163200},
  {000048000},
  {000480000},
  {0032160000},
  {0016160000},
  {00880000},
  {00480000},
  {000120000}
};
byte MINUTES[60][8] = {
  {000015000},
  {000014100},
  {000012300},
  {00008700},
  {00008610},
  {00008430},
  {00008421},
  {00008422},
  {00008442},
  {00008444},
  {00008844},
  {00008884},
  {00008888},
  {0000161688},
  {00001616168},
  {000016161616},
  {000016161632},
  {000016163232},
  {000016323232},
  {000016323264},
  {000016326464},
  {0000163264128},
  {000016321920},
  {000016961280},
  {00001622400},
  {00004819200},
  {000011212800},
  {0000240000},
  {00048192000},
  {000112128000},
  {0002400000},
  {001281120000},
  {00192480000},
  {00224160000},
  {012896160000},
  {019232160000},
  {1286432160000},
  {646432160000},
  {643232160000},
  {323232160000},
  {323216160000},
  {321616160000},
  {161616160000},
  {1616880000},
  {168880000},
  {88880000},
  {48880000},
  {44880000},
  {44480000},
  {24480000},
  {22480000},
  {12480000},
  {03480000},
  {01680000},
  {00780000},
  {003120000},
  {001140000},
  {000150000},
  {000312000},
  {000114000}
};
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 byteColumnbyte 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] = {
  {00001000},
  {00000010},
  {00000002},
  {000000016},
  {000000064},
  {0000001280},
  {0001280000},
  {0128000000},
  {640000000},
  {160000000},
  {20000000},
  {01000000}
};


replace value below to change clock display text

byte HOURS[24][8] = {
  {159150159150},
  {15915091580},
  {1591501311110},
  {159150911150},
  {15915032150},
  {1591501111130},
  {1591501510140},
  {15915011150},
  {1591501411150},
  {15915075150},
  {91580159150},
  {9158091580},
  {915801311110},
  {91580911150},
  {9158032150},
  {915801111130},
  {915801510140},
  {9158011150},
  {915801411150},
  {9158075150},
  {1311110159150},
  {131111091580},
  {13111101311110},
  {1311110911150}
};
byte MINUTES[60][8] = {
  {02401442400240144240},
  {02401442400144240128},
  {02401442400208176176},
  {02401442400144176240},
  {024014424004832240},
  {02401442400176176208},
  {02401442400240160224},
  {024014424001616240},
  {02401442400224176240},
  {0240144240011280240},
  {01442401280240144240},
  {01442401280144240128},
  {01442401280208176176},
  {01442401280144176240},
  {014424012804832240},
  {01442401280176176208},
  {01442401280240160224},
  {014424012801616240},
  {01442401280224176240},
  {0144240128011280240},
  {02081761760240144240},
  {02081761760144240128},
  {02081761760208176176},
  {02081761760144176240},
  {020817617604832240},
  {02081761760176176208},
  {02081761760240160224},
  {020817617601616240},
  {02081761760224176240},
  {0208176176011280240},
  {01441762400240144240},
  {01441762400144240128},
  {01441762400208176176},
  {01441762400144176240},
  {014417624004832240},
  {01441762400176176208},
  {01441762400240160224},
  {014417624001616240},
  {01441762400224176240},
  {0144176240011280240},
  {048322400240144240},
  {048322400144240128},
  {048322400208176176},
  {048322400144176240},
  {0483224004832240},
  {048322400176176208},
  {048322400240160224},
  {0483224001616240},
  {048322400224176240},
  {04832240011280240},
  {01761762080240144240},
  {01761762080144240128},
  {01761762080208176176},
  {01761762080144176240},
  {017617620804832240},
  {01761762080176176208},
  {01761762080240160224},
  {017617620801616240},
  {01761762080224176240},
  {0176176208011280240}
};


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[] = {8137110614};           // index row bit: R1/Q0, R2, R3, R4, R5, R6, R7, R8; index value start from 0, -1 each pin
const byte BIT_COLUMNS[] = {122395101415};      // 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 byteColumnbyte 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 offsetColumnunsigned 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 durationFramebyte 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));
}