element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
7-Segment Display
  • Challenges & Projects
  • Project14
  • 7-Segment Display
  • More
  • Cancel
7-Segment Display
Blog Pi Pico with Clock Display - Showing a Countdown Time
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Events
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: ntewinkel
  • Date Created: 5 Jun 2022 2:30 AM Date Created
  • Views 18344 views
  • Likes 7 likes
  • Comments 2 comments
  • clock
  • 7segmentdisplaych
  • 7-segment
  • raspberry pi pico
  • 7-segment display
  • 7segmentdisplay
  • display
  • 7segmentdisplaysch
  • pi pico
Related
Recommended

Pi Pico with Clock Display - Showing a Countdown Time

ntewinkel
ntewinkel
5 Jun 2022

I've been fiddling around with a 7-segment clock display, which is really just a display that combines 4 different 7-segment displays into one neat little package. With an extra couple of dots thrown in for good measure.

In my previous post, I was able to show all of the digits from 0 to 9 on each clock position in order, and while that is very exciting and brings so many of us endless joy, it's not really very useful that way, and thus I continue on with my quest, to make it look more like an actual clock display.

However, showing an actual time requires displaying each position for a very short amount of time and repeating it constantly so that our persistence of vision allows us to see all 4 digits on at once.
I forget the name for this time-slicing kind of thing Thinking Help me out with a comment please!

So for this next phase I decided to turn it into a countdown timer, because I'm too lazy to make an actual clock that shows actual time because then I have to add buttons to set the time and deal with all of that kind of non-sense.

Instead, I hard-coded a start time, and it simply counts down the time until it hits zero, and then it just sits there at 0 when done.

Clock display showing time from Pi Pico

This was a lot more effort than I thought it would be, partly because I tried to use a Timer to refresh the display, which created problems - I later simplified the code by just running the display refresh in the "while true" never ending loop so that it can just use up whatever spare cycles are available. I think I might have been setting the display refresh timer to refresh too often, and/or maybe not leaving enough time to complete before the next round began, so that the Pi Pico was eventually not able to keep up.

The first part was easy though - counting time can be done by setting up a Timer that ticks on a regular schedule. In my case I set it to use a frequency of 2, so that the time-divider colon on the display can flash 2x per second. Plus since this timer counts seconds for its lowest division, that's plenty accurate. For this, look for timeTick() and startSecondsTicker(). You'll notice that MicroPython on the Pico has a handy "time" library with a function time() that gives us the number of seconds since the epoch. Don't ask me what that epoch is - for this project it's enough to have some fixed reference point to start counting from.

In my first iteration I just made that timer function toggle the division colon on and off, and that looked pretty cool. And it showed that the timer function was working. Very cool.
However, once I started time-slicing to show the 4 position digits, I noticed that the colon was a lot brighter than the 4 digits. I was able to fix that by giving the colon the same amount of time slice in the display loop as the rest of the digits. No more special treatment for you, time-bits-dividing-colon-LED-thing!

I ran into a fair number of syntax errors and the like while figuring this out. Python isn't my native language and so I end up typing silly things that only make sense in C and Swift and the like - that's one thing I don't love about using an interpreted language like Python - these issues only appear once you run the code.

To help debug, I slowed things down a bit. Here's a video of when I first got the digits showing up:

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Then speeding things up, it looks like this following video, which actually is a fairly nice clock display effect - it's a little bit dim but I suppose we could switch the 220R resistors for something with a lower value, but I'm not that fussy.
The video shows the digits glowing a bit funny, but I think that's interference with the timing of the camera on my phone.

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Here is the code I used to make it happen. It ultimately didn't add a whole lot more code compared to the previous step - mostly some time counting variables and lines, a buffer to hold the 4 display digits, some math to figure out hours, minutes, and seconds (int the showTime() function), and then there's the bits where it steps through and displays each digit in the correct display location - see displayRefresh for that bit of magic. Oh and I added a "blank" digit so that we don't get that awkward leading zero in the first position of the clock display.

#
# Clock display test
#

from machine import Pin, Timer
import time


# For my clock display, the common wire connects to VCC
#  -> Note that this means we have to turn a pin "off" to light the segment LED, and "on" to turn it off
#
# You can test the display by using a small 3.3v button battery (CR2032 seems cheap and plentiful)
# Hopefully the display you have will have a model number you can look up to find the pinout.

# Define the segment GPIO connections
# hook up the segments as per the defined constants below
# Use a current limiting resistor for each segment (you'll need 7!)
# The resistors are also necessary to keep a constant brightness on the display
SEG_A_PIN = 13
SEG_B_PIN = 19
SEG_C_PIN = 17
SEG_D_PIN = 16
SEG_E_PIN = 12  # oops, I put the display too close to the Pi Pico, so pin 15 is covered.
SEG_F_PIN = 14
SEG_G_PIN = 18

# The clock display has 4 digit positions
# I'm calling them positions, as it could be hr:mm or mm:ss
POSITION_1 = 10
POSITION_2 = 11
POSITION_3 = 20
POSITION_4 = 21

DIVIDER_COLON = 22

# Python allows us to define global variables anywhere all willy-nilly,
#   but for clarity lets define them here at the top like good little programmers
#   The type is here just for clarity too - Python allows us to change it at any time
DIGITS :[[Pin]] = []
BLANK_DIGIT : [Pin] = []
POSITIONS : [Pin] = []

# time.time() returns float number of seconds since epoch
MINUTE : float = 60
HOUR = MINUTE * 60
TOTAL_TIME = 3 * MINUTE

time_left = TOTAL_TIME
start_time : float = 0 # in seconds since epoch
colon_visible = False
display_buffer : [[Pin]] = [BLANK_DIGIT, BLANK_DIGIT, BLANK_DIGIT, BLANK_DIGIT]  # this will hold the 4 digits currently being displayed - the display needs continuous refreshing in order to work.


def setup():
    # Define each segment
    SEG_A = Pin(SEG_A_PIN, Pin.OUT)
    SEG_B = Pin(SEG_B_PIN, Pin.OUT)
    SEG_C = Pin(SEG_C_PIN, Pin.OUT)
    SEG_D = Pin(SEG_D_PIN, Pin.OUT)
    SEG_E = Pin(SEG_E_PIN, Pin.OUT)
    SEG_F = Pin(SEG_F_PIN, Pin.OUT)
    SEG_G = Pin(SEG_G_PIN, Pin.OUT)
    
    # Define which segments make up each digit
    DIGIT_0 = [SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F       ]
    DIGIT_1 = [       SEG_B, SEG_C                            ]
    DIGIT_2 = [SEG_A, SEG_B,        SEG_D, SEG_E,        SEG_G]
    DIGIT_3 = [SEG_A, SEG_B, SEG_C, SEG_D,               SEG_G]
    DIGIT_4 = [       SEG_B, SEG_C,               SEG_F, SEG_G]
    DIGIT_5 = [SEG_A,        SEG_C, SEG_D,        SEG_F, SEG_G]
    DIGIT_6 = [SEG_A,        SEG_C, SEG_D, SEG_E, SEG_F, SEG_G]
    DIGIT_7 = [SEG_A, SEG_B, SEG_C                            ]
    DIGIT_8 = [SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G]
    DIGIT_9 = [SEG_A, SEG_B, SEG_C, SEG_D,        SEG_F, SEG_G]
    
    # Note that we are not limited to decimal digits. We could continue to add A through F for hexadecimal
    
    POS_1 = Pin(POSITION_1, Pin.OUT)
    POS_2 = Pin(POSITION_2, Pin.OUT)
    POS_3 = Pin(POSITION_3, Pin.OUT)
    POS_4 = Pin(POSITION_4, Pin.OUT)

    global divider_colon
    divider_colon = Pin(DIVIDER_COLON, Pin.OUT)
    
    global DIGITS
    DIGITS = [DIGIT_0, DIGIT_1, DIGIT_2, DIGIT_3, DIGIT_4, DIGIT_5, DIGIT_6, DIGIT_7, DIGIT_8, DIGIT_9, BLANK_DIGIT]

    global POSITIONS
    POSITIONS = [POS_1, POS_2, POS_3, POS_4]
    
    displayOff()
    
    global start_time
    start_time = time.time()


def showPosition(position):
    positionsOff()
    position.on()

def displayDigit(digit):
    #start by turning off all the segments
    segmentsOff()
    
    for segment in digit:
        segment.off() # gpio "off" turns on the LED

def positionsOff():
    for pos in POSITIONS:
        pos.off()

def segmentsOff():
    for segment in DIGITS[8]:
        segment.on() # gpio "on" turns off the LED

def displayOff():
    # turn off all the digit positions
    positionsOff()
    # turn off all the segments
    segmentsOff()

def timeTick(timer):
    global time_left, start_time, TOTAL_TIME, colon_visible
    colon_visible =  not colon_visible
    current_time = time.time() # using the time() function will likely be more accurate than counting the ticks, plus we can mess with the tick frequency now.
    elapsed_time = current_time - start_time
    time_left : int = TOTAL_TIME - elapsed_time
    if time_left < 0 : time_left = 0
    showTime(time_left)

def startSecondsTicker():
    Timer().init(freq=2, mode=Timer.PERIODIC, callback=timeTick)
    
def displayRefresh():
    global display_buffer, POSITIONS, colon_visible, divider_colon
    
    led_on_time = 0.0025
    # too much on time will cause flickering - the display must keep each position lit up just long enough to repeat it again fast enough to fool the eye.
    
    for index, position in enumerate(POSITIONS) :
        showPosition(position) 
        displayDigit(display_buffer[index])
        time.sleep(led_on_time)
        # You can use a bigger delay here for debugging purposes, to make it easier to see the digits being shown in turn.
        
    displayOff() # otherwise it will linger on the last digit, making it brighter than the rest
    
    if colon_visible :
        divider_colon.off() # turns the LEDs on
    
    time.sleep(led_on_time)
    divider_colon.on()  # turns the LEDs off

def showTime(total_seconds):
    #print("show time total seconds = ", total_seconds)

    # convert seconds to hours, minutes, and seconds
    hours = total_seconds // 3600  # the // is "floor division" which avoids fractions
    leftover = total_seconds % 3600
    minutes = leftover // 60
    seconds = leftover % 60
    # print("time = ", hours, ":", minutes, ":", seconds)
    
    if hours > 0 :
        first_number = hours
        second_number = minutes
    else :
        first_number = minutes
        second_number = seconds
        
    global digits
    
    if hours > 99 :
        display_buffer[0] = DIGITS[8]
        display_buffer[1] = DIGITS[8]
        display_buffer[2] = DIGITS[8]
        display_buffer[3] = DIGITS[8]
    else :
        if first_number > 9 :
            display_buffer[0] = DIGITS[first_number // 10]
        else :
            display_buffer[0] = BLANK_DIGIT
        
        display_buffer[1] = DIGITS[first_number % 10]
        display_buffer[2] = DIGITS[second_number // 10]
        display_buffer[3] = DIGITS[second_number % 10]
        
    

# Start main code
setup()
startSecondsTicker()
showTime(TOTAL_TIME)

# Using a Timer to refresh the display seems to cause it to hang after a while
# but using this loop we can go nuts refreshing the display with all the spare clock cycles

while True:
    displayRefresh()
    

I wonder if there isn't already some sort of library available that handles clock displays like this?
Oh well, in any case it's an interesting journey and shows us the kind of cool engineering challenges that we might not think about otherwise.

Cheers,
-Nico

edit: In my next post, I help make the world a better place by bringing back memories of the 1980's

  • Sign in to reply

Top Comments

  • shabaz
    shabaz over 3 years ago +1
    Nice! Multiplexing : )
  • ntewinkel
    ntewinkel over 3 years ago in reply to shabaz

    THANK YOU shabaz !!!

    You wouldn't believe how much that was bugging me the whole time I was writing that blog post Laughing And it was annoyingly right there on the tip of my tongue, corner of my mind, the whole time!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 3 years ago

    Nice!

    Multiplexing : )

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube