4.4 LED Dot Matrix

The LED matrix is a low-resolution dot-matrix display that uses an array of light-emitting diodes (LEDs) as pixels to create patterned displays. These matrices are bright enough to be visible even in outdoor sunlight and are commonly seen in stores, billboards, signs, and variable message displays (such as those on public transit vehicles).

The LED matrix used in this kit is an 8x8 dot matrix with 16 pins. The anodes of the LEDs are connected in rows, while the cathodes are connected in columns (at the circuit level). This configuration allows control over the 64 individual LEDs.

To light up the first LED, you need to provide a high level to Row 1 and a low level to Column 1. To light up the second LED, you would provide a high level to Row 1 and a low level to Column 2, and so on. By controlling the current through each pair of rows and columns, each LED can be individually controlled to display characters or images.

Component List

  • Raspberry Pi Pico W x1

  • MicroUSB cable x1

  • 830 Tie-Points Breadboard x1

  • LED Dot Matrix x1

  • 74HC595 x2

  • Jumper Wire Several

Component knowledge

LED Dot Matrix

The 8x8 dot matrix is controlled by two 74HC595 chips: one for the rows and one for the columns. These two chips share pins G18 to G20, which significantly reduces the number of I/O ports required on the Pico W board.

To display a pattern, the Pico W outputs a 16-bit binary number. The first 8 bits are sent to the 74HC595 controlling the rows, while the last 8 bits are sent to the 74HC595 controlling the columns.

The Q7’ pin is a series output pin, which can be connected to the DS pin of another 74HC595 to daisy-chain multiple 74HC595 chips together.

Connect

Build the circuit. Since the wiring is complicated, let’s make it step by step.

Step 1: First, insert the Pico W, the LED dot matrix and two 74HC595 chips into breadboard. Connect the 3.3V and GND of the Pico W to holes on the two sides of the board, then hook up pin16 and 10 of the two 74HC595 chips to VCC, pin 13 and pin 8 to GND.

../_images/4.4-1.png

Step 2: Connect pin 11 of the two 74HC595 together, and then to GP20; then pin 12 of the two chips, and to GP19; next, pin 14 of the 74HC595 on the left side to GP18 and pin 9 to pin 14 of the second 74HC595.

../_images/4.4-2.png

Step 3: The 74HC595 on the right side is to control columns of the LED dot matrix. See the table below for the mapping. Therefore, Q0-Q7 pins of the 74HC595 are mapped with pin 13, 3, 4, 10, 6, 11, 15, and 16 respectively.

../_images/4.4-3.png

Step 4: Now connect the ROWs of the LED dot matrix. The 74HC595 on the left controls ROW of the LED dot matrix. See the table below for the mapping. We can see, Q0-Q7 of the 74HC595 on the left are mapped with pin 9, 14, 8, 12, 1, 7, 2, and 5 respectively.

../_images/4.4-4.png

Code

Note

  • Open the 4.4_led_dot_matrix.ino file under the path of Ultimate-Starter-Kit-for-Pico-W\Arduino\1.Project or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.

  • Or copy this code into Arduino IDE.

  • Don’t forget to select the board(Raspberry Pi Pico) and the correct port before clicking the Upload button.

Click “Run current script”, you will see a x graphic displayed on the 8x8 dot matrix.

The following is the program code:

// Define pins
const int SDI_PIN = 18;   // Data input
const int RCLK_PIN = 19;  // Storage register clock
const int SRCLK_PIN = 20; // Shift register clock

// Define pattern arrays
const byte hi_pattern[] = {
    0xFF, // 11111111
    0xAD, // 10101101
    0xAD, // 10101101
    0xA1, // 10100001
    0xAD, // 10101101
    0xAD, // 10101101
    0xFF, // 11111111
    0xFF  // 11111111
};

const byte music_note[] = {
    0xFF, // 11111111
    0xFF, // 11110111
    0xF1, // 11110001
    0xF3, // 11110011
    0xF7, // 11110111
    0xF7, // 11110111
    0xF7, // 11110111
    0xFF  // 11111111
};

const byte smile[] = {
    0xFF, // 11111111
    0xFF, // 11111111
    0xC3, // 11000011
    0xBD, // 10111101
    0xFF, // 11111111
    0x93, // 10010011
    0x93, // 10010011
    0xFF  // 11111111
};

const byte arrow_right[] = {0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF};
const byte arrow_left[] = {0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF};

void setup() {
  pinMode(SDI_PIN, OUTPUT);
  pinMode(RCLK_PIN, OUTPUT);
  pinMode(SRCLK_PIN, OUTPUT);
}

// Send data to 74HC595
void hc595_in(byte dat) {
  for (int bit = 7; bit >= 0; bit--) {
    digitalWrite(SRCLK_PIN, LOW);
    digitalWrite(SDI_PIN, (dat >> bit) & 0x01);
    digitalWrite(SRCLK_PIN, HIGH);
  }
}

// Output data to storage register
void hc595_out() {
  digitalWrite(RCLK_PIN, HIGH);
  digitalWrite(RCLK_PIN, LOW);
}

// Display pattern
void display_pattern(const byte pattern[], unsigned long duration_ms) {
  unsigned long start_time = millis();
  while (millis() - start_time < duration_ms) {
    for (int i = 0; i < 8; i++) {
      hc595_in(pattern[i]);
      hc595_in(0x80 >> i);
      hc595_out();
      delayMicroseconds(500);
    }
  }
}

// Scroll pattern to the left
void scroll_pattern_left(byte result[], const byte pattern[]) {
  for (int i = 0; i < 8; i++) {
    result[i] = ((pattern[i] << 1) | (pattern[i] >> 7)) & 0xFF;
  }
}

// Scroll pattern to the right
void scroll_pattern_right(byte result[], const byte pattern[]) {
  for (int i = 0; i < 8; i++) {
    result[i] = ((pattern[i] >> 1) | (pattern[i] << 7)) & 0xFF;
  }
}

// Scroll animation
void scroll_animation(const byte pattern[], char direction, int steps, int step_delay) {
  byte current[8];
  memcpy(current, pattern, 8);

  for (int step = 0; step < steps; step++) {
    display_pattern(current, step_delay);
    byte temp[8];
    if (direction == 'l') {
      scroll_pattern_left(temp, current);
    } else {
      scroll_pattern_right(temp, current);
    }
    memcpy(current, temp, 8);
  }
}

void loop() {
  // Display "HI" pattern
  display_pattern(hi_pattern, 1500);

  // Display music note pattern and scroll
  display_pattern(music_note, 1000);
  scroll_animation(music_note, 'l', 8, 150);
  scroll_animation(music_note, 'r', 8, 150);

  // Display smiley face
  display_pattern(smile, 1500);

  // Display arrow animation
  for (int i = 0; i < 2; i++) {
    display_pattern(arrow_right, 400);
    display_pattern(arrow_left, 400);
  }
}

Phenomenon