[How To] Digital Alarm Clock with Matrix Led 4x8x8

I’ve done a lot of searching but haven’t found any tutorial about how to create a simple alarm digital clock with MAX7219 Matrix Led 4x8x8 (nice piece of hardware), all the tutorials I found are just for Arduino :cry:

So I decided to create my own one :wink: .

This is the complete and simple tutorial.

Total cost: about 60 Euro
Difficulty = easy
Time = 1 hour
Skills required = dummy > :rofl: >

Hardware requisites:

  • one 5V 3A power supply, or better two: one 5V 2A for “Raspberry + amplifier” and one 5V 1A for “Led matrix”.
  • Raspberry Pi1 512 or above
  • Raspbian Stretch Lite on 4 GB sd card (or bigger)
  • USB Wifi dongle - optional (for Pi1 and Pi2, not needed for Pi3)
  • RTC Module (DS3231 suggested)
  • MAX7219-LED-4x8x8-Matrix
  • 5V 2W mini audio amplifier (mono is OK)
  • 2W Mini speaker(s)
  • a plastic box
  • some wires (arduino jumper wires)

Max Mem usage: less than 100 Mbytes
Max CPU usage: less than 30% @ RP1 no overclock

Important Notes:
connect the Vcc pin of the Led Matrix directly to the 5V of the power supply, do not connect it to the Raspberry +5V pins.
All GND pins (‘ground’ or ‘-’) of Raspberry, Amplifier and MAX7219 Led matrix, need to be connected together (just one pin per board)
The audio amplifier gets +5V directly to the +5V (pin 2 or 4) of the raspberry


RTC installation

MAX7219 Led Matrix module

Pin-out description on the bottom side


Stereo mini audio amplifier

I decided to solder the audio wires from raspberry to the amp, but you can use the 3.5 audio connector as well.

Finished project :slight_smile:
note: in this picture the TIME is shifted to the right, I modified the code to better center it, also the leds bright is settable (see code comments)

You can also add scrolling text to the clock (there is a little startup demo in my code):

You might use Raspberry Zero, but you need a mini adapter like this, to have an audio connection output (HDMI to VGA/Audio):

Raspberry GPIO pin-outs (needed for connecting MAX7219-LED matrix)

  • Installation of RTC (real time clock module with backup battery):


  • MAX7219 Driver installation:


  • Matrix pin-outs connections to Raspberry:


  • My Digital Clock Python script:
sudo nano /root/clock.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2017-18 Richard Hull and contributors
# See LICENSE.rst for details.
# MAX7219-LED-4x8x8-Matrix digital clock By Lovisolo Pier Maurizio - Italy

import re
import time
import argparse
import locale
import datetime

# NOTE: change the following according to your locale setting

from luma.led_matrix.device import max7219
from luma.core.interface.serial import spi, noop
from luma.core.render import canvas
from luma.core.virtual import viewport
from luma.core.legacy import text, show_message
from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT
from itertools import repeat

def demo(n, block_orientation, rotate):
    # create device for linear preassembled 4x8x8 max7219 matrix
    serial = spi(port=0, device=0, gpio=noop())
    device = max7219(serial, cascaded=4, block_orientation=-90)
    print("Created device")
    # note: change device.contrast value (0xXX) to change leds brightness

    # start scrolling text demo - just once at startup
    msg = "DIGITAL CLOCK by Lovisolo Pier Maurizio - 2018"
    show_message(device, msg, fill="white", font=proportional(LCD_FONT), scroll_delay=0.05)

    # MAX7219 4x8x8 LED Matrix Clock
    for _ in repeat(None):
     msg = time.asctime()
     msg= time.strftime("%H%M")
     with canvas(device) as draw:
      text(draw, (1, 0), msg, fill="white")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='matrix_demo arguments',

    parser.add_argument('--cascaded', '-n', type=int, default=1, help='Number of cascaded MAX7219 LED matrices')
    parser.add_argument('--block-orientation', type=int, default=0, choices=[0, 90, -90], help='Corrects block orientation when wired vertically')
    parser.add_argument('--rotate', type=int, default=0, choices=[0, 1, 2, 3], help='Rotate display 0=0°, 1=90°, 2=180°, 3=270°')

    args = parser.parse_args()

        demo(args.cascaded, args.block_orientation, args.rotate)
    except KeyboardInterrupt:

Audio for alarm clock (MP3 player):

sudo apt-get install madplay

My crontab for alarm wakeup and “hour/ half hour” bell (you might use any MP3 audio you like):

crontab -e

insert the following:

# Big-Ben bell every hour from 09:00 to 22:00
00 09-22 * * * /usr/bin/madplay /root/westminster_classic.mp3
# haf hour bell 09:30 to 22:30
30 09-22 * * * /usr/bin/madplay /root/mezzora.mp3

# Wake up at 07:00 Mon to Fri
00 07 * * 1-5 /usr/bin/madplay /root/church.mp3

Digital Clock autostart at boot:

sudo nano /etc/rc.local

put the following just before “exit 0” line:

/usr/bin/python /root/clock.py &

I also connected a blue led directly to GPIO 22 without any resistor :open_mouth: ,
but I used this python script to reduce gpio output voltage by controlling the PWM duty cycle :wink:
and also to start pulsing the led (dim to brighten and viceversa).
You might use this led as a visible alarm for something.

NOTE: never connect red, orange, yellow or green LEDs directly to the GPIO without a series resistor!
You might directly connect a blue or a white led to the gpio since those leds have higher drop voltage (at your own risk).

# script to connect a "blue" or "white" led directly to gpio pin and control it
# never connect red, orange, yellow or green LED directly to the GPIO without a series resistor

import RPi.GPIO as GPIO # always needed with RPi.GPIO  
from time import sleep  # pull in the sleep function from time module  

GPIO.setmode(GPIO.BCM)  # choose BCM or BOARD numbering schemes. I use BCM  

GPIO.setup(22, GPIO.OUT)# set GPIO 22 as output for blue led  

white = GPIO.PWM(22, 100)    # create object white for PWM on port 22 at 100 Hertz  

white.start(0)              # start white or blue led on 0 percent duty cycle (off)  

# now the fun starts, we'll vary the duty cycle to   
# dim/brighten the led  

pause_time = 0.01           # you can change this to slow down/speed up  

    while True:
        for i in range(0,50):      # 50% to reduce max output voltage  
        for i in range(50,-1,-1):      # from 50% to zero in steps of -1  

except KeyboardInterrupt:
    white.stop()            # stop the white PWM output  
    GPIO.cleanup()          # clean up GPIO on CTRL+C exit

How to determine the right resistor value for different types of led:

notes and translation:
volt caduta = led drop voltage
infrarosso = infrared
valori standard resistenze = standard resistor values in ohm (x10, x100, x1000, etc.)
all the colors are self-explanatory :wink:
Raspberry GPIO output voltage is 3.3V
the drop resistor has to be connected in series to one of the two terminals of the led (better to the catode +)
LED catode (+) is the longer terminal

Nice project thanks for posting to this forum.


Really great :sunglasses:.

I tend to hate my alarm clock some mornings and do not tread it very well. Perhaps a fully safe made baby helps to enjoy the start into the day, when you’re forced to see what you have created and think about what you could do next :smiley:.

/etc/rc.local is not by default enabled (or even exists) on all systems any more. It seems to be seen deprecated for some reason: https://stackoverflow.com/a/44801337

However, since DietPi anyway needs to run some oneshots on startup, we added an alternative: /var/lib/dietpi/postboot.d/

  • Place any script inside and it will be executed at the end of startup sequence.

Just an update:

I noticed that connecting the +Vcc of the mini audio amplifier to the 3.3V pin instead of the 5V pin of Raspberry, the high frequency digital noise is much less audible, probably because Raspberry has the 3.3V line more filtered and stabilized than the 5V.

By looking at the data sheet I found that this little amp can work with power supply voltage from DC 2.5 to 5.5V

Just an improvement:

Let the raspberry say current date and time:

  1. install picotts, offline text to speech:
sudo apt-get install libttspico-utils
  1. create the code:
sudo nano /root/time.sh

insert the following:

# Clock says in English: date, day of the week and hour
data=$(date +%d%B)
pico2wave -l en-GB -w /tmp/data.wav "<volume level='55'><pitch level='105'> today is the"$data
data1=$(date +%A)
pico2wave -l en-GB -w /tmp/data1.wav "<volume level='55'><pitch level='105'>"$data1
ora=$(date +"%H:%M")
cadena=$(echo $ora | sed 's/\:00/and zero/g')
pico2wave -l en-GB -w /tmp/ora.wav "<volume level='55'><pitch level='105'>the current time is"$cadena"minutes"
aplay -r 8000 -t wav -c 2 -f S16_LE -D plughw:0,0 /tmp/data.wav
aplay -r 8000 -t wav -c 2 -f S16_LE -D plughw:0,0 /tmp/data1.wav
aplay -r 8000 -t wav -c 2 -f S16_LE -D plughw:0,0 /tmp/ora.wav
  1. give the right permisions to the script
sudo chmod 755 /root/time.sh
  1. launch the script:
/bin/sh /root/time.sh

Note: Picotts supported languages : ‘en-US’, ‘en-GB’, ‘de-DE’, ‘es-ES’, ‘fr-FR’, ‘it-IT’.
On some Raspbian release, this package is missing but you can just copy the arm deb package from debian.