edge lab LIVE! starts Tuesday in Munich. Grab a workshop seat and take home the board you build on. Code FRIEND-HACKSTER saves 20%. () Learn more!
TeknoTrek
Published © GPL3+

HT16K33 4-Digit 16-Segment Display with Custom PCB

A custom-designed HT16K33-based 4-digit 16-segment display with I2C control, animations, and reusable firmware for embedded projects.

BeginnerProtip4 hours626
HT16K33 4-Digit 16-Segment Display with Custom PCB

Things used in this project

Hardware components

HT16K33 LED Driver (I2C)
×1
16-Segment LED Display
×4
Custom PCB (HT16K33 Display Board)
×1
Pin Headers / Connectors
×4
220R Resistors
×4

Software apps and online services

Arduino IDE
Arduino IDE
Adafruit_LEDBackpack Library
Adafruit_GFX Library
Wire (I2C) Library
Arduino NANO ESP32
Arduino NANO ESP32
KiCad
KiCad

Hand tools and fabrication machines

Soldering Iron
Multimeter
Flux and Solder Wire
USB Cable

Story

Read more

Schematics

HT16K33 4-Digit 16-Segment Display

Code

State Machine Animations

C/C++
/*
  TeknoTrek YouTube Channel
   Electronics  Arduino  PCB Design  LED Animations  Embedded Systems

  For more projects and short tutorials:

   YouTube: https://www.youtube.com/@TeknoTrek

   Subscribe to support the channel and stay updated!
*/



#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h>

Adafruit_AlphaNum4 display;

/* ===================== */
/* SEGMENT TANIMLARI     */
/* ===================== */
#define SEG_A  (1 << 0)
#define SEG_B  (1 << 1)
#define SEG_C  (1 << 2)
#define SEG_D  (1 << 3)
#define SEG_E  (1 << 4)
#define SEG_F  (1 << 5)
#define SEG_G  (1 << 6)
#define SEG_H  (1 << 7)
#define SEG_K  (1 << 8)
#define SEG_L  (1 << 9)
#define SEG_M  (1 << 10)
#define SEG_N  (1 << 11)
#define SEG_O  (1 << 12)
#define SEG_P  (1 << 13)
#define SEG_S  (1 << 15)

/* ===================== */
/* HARF TANIMLARI        */
/* ===================== */
uint16_t CHAR_T = SEG_A | SEG_B | SEG_L | SEG_O;
uint16_t CHAR_E = SEG_A | SEG_B | SEG_H | SEG_G | SEG_S | SEG_E | SEG_F;
uint16_t CHAR_K = SEG_H | SEG_G | SEG_S | SEG_M | SEG_P;
uint16_t CHAR_N = SEG_H | SEG_G | SEG_K | SEG_P | SEG_D | SEG_C;
uint16_t CHAR_O = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_H;
uint16_t CHAR_R = SEG_A | SEG_B | SEG_C | SEG_N | SEG_S | SEG_H | SEG_G | SEG_P;
uint16_t CHAR_SPACE = 0;

/* ===================== */
/* KAYAN METN           */
/* ===================== */
uint16_t text[] = {
  CHAR_T, CHAR_E, CHAR_K, CHAR_N, CHAR_O,
  CHAR_T, CHAR_R, CHAR_E, CHAR_K,
  CHAR_SPACE, CHAR_SPACE, CHAR_SPACE, CHAR_SPACE
};
#define TEXT_LEN (sizeof(text) / sizeof(text[0]))

/* ===================== */
/* STATE TANIMLARI       */
/* ===================== */
enum AnimationState {
  STATE_WAVE,
  STATE_MATRIX,
  STATE_FILL,
  STATE_PULSE,
  STATE_SCROLL   //  EN SON
};

AnimationState currentState = STATE_WAVE;
unsigned long stateStartTime = 0;
const unsigned long STATE_DURATION = 4000;

/* ===================== */
/* SETUP                 */
/* ===================== */
void setup() {
  Wire.begin();
  display.begin(0x70);
  display.clear();
  display.writeDisplay();
  randomSeed(analogRead(A0));
  stateStartTime = millis();
}

/* ===================== */
/* STATE GE          */
/* ===================== */
void nextState() {
  currentState = (AnimationState)((currentState + 1) % 5);
  stateStartTime = millis();
  display.clear();
}

/* ===================== */
/* LOOP                  */
/* ===================== */
void loop() {
  if (millis() - stateStartTime > STATE_DURATION) {
    nextState();
  }

  switch (currentState) {
    case STATE_WAVE:   animWave();   break;
    case STATE_MATRIX: animMatrix(); break;
    case STATE_FILL:   animFill();   break;
    case STATE_PULSE:  animPulse();  break;
    case STATE_SCROLL: scrollText(); break;
  }
}

/* ===================== */
/* ANMASYONLAR          */
/* ===================== */

//  Wave
void animWave() {
  static uint8_t d = 0, b = 0;
  display.clear();
  display.writeDigitRaw(d, (1 << b));
  display.writeDisplay();

  b++;
  if (b >= 16) { b = 0; d = (d + 1) % 4; }
  delay(30);
}

//  Matrix
void animMatrix() {
  display.clear();
  for (int d = 0; d < 4; d++) {
    display.writeDigitRaw(d, random(0x0000, 0xFFFF));
  }
  display.writeDisplay();
  delay(80);
}

//  Dolma
void animFill() {
  static uint16_t frame = 0;
  frame = (frame << 1) | 1;
  if (frame == 0xFFFF) frame = 0;

  for (int d = 0; d < 4; d++) {
    display.writeDigitRaw(d, frame);
  }
  display.writeDisplay();
  delay(120);
}

//  Pulse
void animPulse() {
  static bool on = false;
  on = !on;

  for (int d = 0; d < 4; d++) {
    display.writeDigitRaw(d, on ? 0xFFFF : 0x0000);
  }
  display.writeDisplay();
  delay(200);
}

//  Kayan "teknoTrek" (SON ANMASYON)
void scrollText() {
  static int pos = 0;

  display.clear();
  display.writeDigitRaw(0, text[pos]);
  display.writeDigitRaw(1, text[pos + 1]);
  display.writeDigitRaw(2, text[pos + 2]);
  display.writeDigitRaw(3, text[pos + 3]);
  display.writeDisplay();

  pos++;
  if (pos > TEXT_LEN - 4) pos = 0;
  delay(300);
}

Flower Animation

C/C++
/*
  TeknoTrek YouTube Channel
   Electronics  Arduino  PCB Design  LED Animations  Embedded Systems

  For more projects and short tutorials:
   YouTube: https://www.youtube.com/@TeknoTrek

   Subscribe to support the channel and stay updated!
*/


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h>

Adafruit_AlphaNum4 display;

/******** SEGMENT TANIMLARI ********/
#define SEG_A (1 << 0)
#define SEG_B (1 << 1)
#define SEG_C (1 << 2)
#define SEG_D (1 << 3)
#define SEG_E (1 << 4)
#define SEG_F (1 << 5)
#define SEG_G (1 << 6)
#define SEG_H (1 << 7)
#define SEG_K (1 << 8)
#define SEG_L (1 << 9)
#define SEG_M (1 << 10)
#define SEG_N (1 << 11)
#define SEG_O (1 << 12)
#define SEG_P (1 << 13)
#define SEG_R (1 << 14)
#define SEG_S (1 << 15)

/******** HALKA TANIMLARI ********/
uint16_t innerRing[] = {
  SEG_K, SEG_L, SEG_M, SEG_N,
  SEG_P, SEG_O, SEG_R, SEG_S
};

uint16_t outerRing[] = {
  SEG_A, SEG_B, SEG_C, SEG_D,
  SEG_E, SEG_F, SEG_G, SEG_H
};

#define INNER_LEN 8
#define OUTER_LEN 8

/******** ZAMANLAMALAR ********/
#define STEP_TIME   140
#define DIGIT_WAVE  180
#define HOLD_TIME   500
#define CLEAR_TIME  300

/******** STATE MACHINE ********/
enum State {
  FLOWER_INNER,
  FLOWER_OUTER,
  HOLD_FULL,
  CLEAR_ALL
};

State currentState = FLOWER_INNER;

uint32_t lastTick = 0;
int digitIndex = 0;
int stepIndex  = 0;

uint16_t digitState[4] = {0, 0, 0, 0};

void setup() {
  Wire.begin();
  display.begin(0x70);
  display.clear();
  display.writeDisplay();
}

void loop() {
  uint32_t now = millis();

  switch (currentState) {

    /********   HALKA ********/
    case FLOWER_INNER:
      if (now - lastTick >= STEP_TIME) {
        lastTick = now;

        if (stepIndex < INNER_LEN) {
          digitState[digitIndex] |= innerRing[stepIndex];
          display.writeDigitRaw(digitIndex, digitState[digitIndex]);
          display.writeDisplay();
          stepIndex++;
        } else {
          stepIndex = 0;
          digitIndex++;
          if (digitIndex >= 4) {
            digitIndex = 0;
            currentState = FLOWER_OUTER;
          }
          lastTick += DIGIT_WAVE;
        }
      }
      break;

    /********  DI HALKA ********/
    case FLOWER_OUTER:
      if (now - lastTick >= STEP_TIME) {
        lastTick = now;

        if (stepIndex < OUTER_LEN) {
          digitState[digitIndex] |= outerRing[stepIndex];
          display.writeDigitRaw(digitIndex, digitState[digitIndex]);
          display.writeDisplay();
          stepIndex++;
        } else {
          stepIndex = 0;
          digitIndex++;
          if (digitIndex >= 4) {
            digitIndex = 0;
            currentState = HOLD_FULL;
            lastTick = now;
          }
          lastTick += DIGIT_WAVE;
        }
      }
      break;

    /********  TAM DOLU BEKLE ********/
    case HOLD_FULL:
      if (now - lastTick >= HOLD_TIME) {
        currentState = CLEAR_ALL;
        lastTick = now;
      }
      break;

    /********  TEMZLE ********/
    case CLEAR_ALL:
      if (now - lastTick >= CLEAR_TIME) {
        for (int i = 0; i < 4; i++) digitState[i] = 0;
        display.clear();
        display.writeDisplay();
        currentState = FLOWER_INNER;
        digitIndex = 0;
        stepIndex = 0;
        lastTick = now;
      }
      break;
  }
}

Leading Zero Secret Countre

C/C++
/*
  TeknoTrek YouTube Channel
   Electronics  Arduino  PCB Design  LED Animations  Embedded Systems

  For more projects and short tutorials:
   YouTube: https://www.youtube.com/@TeknoTrek

   Subscribe to support the channel and stay updated!
*/


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h>

Adafruit_AlphaNum4 display;

/* ================= SEGMENT TANIMLARI ================= */
#define SEG_A (1 << 0)
#define SEG_B (1 << 1)
#define SEG_C (1 << 2)
#define SEG_D (1 << 3)
#define SEG_E (1 << 4)
#define SEG_F (1 << 5)
#define SEG_G (1 << 6)
#define SEG_H (1 << 7)
#define SEG_K (1 << 8)
#define SEG_L (1 << 9)
#define SEG_M (1 << 10)
#define SEG_N (1 << 11)
#define SEG_O (1 << 12)
#define SEG_P (1 << 13)
#define SEG_R (1 << 14)
#define SEG_S (1 << 15)

/* ================= RAKAMLAR =================
   3 rakam dzeltilmitir (G OFF, E ON)
*/
uint16_t digits[10] = {
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_H,        // 0
  SEG_C | SEG_D,                                                        // 1
  SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G | SEG_N | SEG_S,        // 2
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_N | SEG_S,        // 3
  SEG_C | SEG_D | SEG_H | SEG_N | SEG_S,                                // 4
  SEG_A | SEG_B | SEG_D | SEG_E | SEG_F | SEG_H | SEG_N | SEG_S,        // 5
  SEG_A | SEG_B | SEG_D | SEG_E | SEG_F | SEG_G | SEG_H | SEG_N | SEG_S,// 6
  SEG_A | SEG_B | SEG_M | SEG_O,                                        // 7
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_H |
  SEG_N | SEG_S,                                                        // 8
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_H |
  SEG_N | SEG_S                                                         // 9
};

void setup() {
  Wire.begin();
  display.begin(0x70);
  display.clear();
  display.writeDisplay();
}

void loop() {
  static uint16_t count = 0;

  display.clear();

  uint8_t d0 = (count / 1000) % 10;
  uint8_t d1 = (count / 100)  % 10;
  uint8_t d2 = (count / 10)   % 10;
  uint8_t d3 = count % 10;

  bool started = false;

  if (d0 != 0) {
    display.writeDigitRaw(0, digits[d0]);
    started = true;
  }

  if (started || d1 != 0) {
    display.writeDigitRaw(1, digits[d1]);
    started = true;
  }

  if (started || d2 != 0) {
    display.writeDigitRaw(2, digits[d2]);
    started = true;
  }

  // Son digit her zaman yazlr
  display.writeDigitRaw(3, digits[d3]);

  display.writeDisplay();

  count++;
  if (count > 9999) count = 0;

  delay(100);
}

Credits

TeknoTrek
1 project • 0 followers
YouTube electronics creator sharing DIY circuits, PCB designs, Arduino projects, and hands-on engineering tutorials.

Comments