Python Forum

Full Version: Binary Clock
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
So I started what I thought would be a pretty simple project, but through perseverance was able to turn it into something complicated.  It's rather long, 227 lines, and works with Python 3.4 and 3.6, on Windows 10 and OpenSuse 42.2 Linux.  You will need the third party libraries "colorama" and "cursor", both of which can be installed with "pip".  Right now, the display is in "cheater" mode, in that it shows the numbers, but if you're nerdy enough, you can change it to display any single character you want (within reason) (no, I did not try the unicode 'Pile of Poo').  I could only think of using a counter (default is 1 minute) and using "Control + C" to exit before the timer runs out.  I tried to make it as a gui, but, well I have no talent what so ever in that regard and it rapidly turned into a major cluster f--k, so a plain terminal is what you get  Angel

Any suggestions would be appreciated. Enjoy  Smile

200+ lines of code... You should put it on github or somewhere else as a file.  Smile

I don't feel it like a binary. No 0 1 sequence. But is a quite interesting idea. :D

I have another one. Or two. Hex clock. Percentage clock ( instead of hours, minutes and seconds percent from 24 hours as HH, percent from 60 minutes for MM and so on)

00%:90% for 00:54 as it is now. No seconds here
i like the % clock idea ... basically base 100

could just have a clock with a choosable number base
Can't promise you I didn't make any mistakes here, but something to think about in terms of reducing a lot of that redundant code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
import os
import time
import cursor
import colorama as cr
 

COLUMN_POSITIONS = (5, 8, 13, 16, 21, 24)
 

def get_cursor_locations(column):
    locations = {2**i : cr.Cursor.POS(column, 11-2*i) for i in range(5)}
    locations[0] = cr.Cursor.POS(column, 13)
    return locations


def render(display, digit, cursors):
    binary = bin(int(digit))[:1:-1]
    if not any(int(bit) for bit in binary):
        print("{}{}{}".format(display, cursors[0], 0))
    else:
        for i,bit in enumerate(binary):
            if int(bit):
                print("{}{}{}".format(display, cursors[2**i], 2**i))


def main():
    cursor.hide()
    try:
        for c in range(60):    # Currently set for 1 min. (1 hr = 3600, 24 hrs = 86400)
            os.system('cls' if os.name == 'nt' else 'clear')
 
            # Get current time: hours (24 hour clock), minutes, seconds) and put in a list
            t_now = [time.strftime("%H"), time.strftime("%M"), time.strftime("%S")]
            str_t = "".join(t_now)
 
            # Initialize and set some colors for colorama
            cr.init()
            off = cr.Back.BLACK
            on = cr.Fore.RED
 
            # Print Header
            tab = " " * 4
            print(off)
            print(on + tab + 'HRS' + tab + ' MIN' + tab + ' SEC' + "\n")
 
            # Run clock
            display = cr.Fore.RED
            for digit, column in zip(str_t, COLUMN_POSITIONS):
                render(display, digit, get_cursor_locations(column))
            
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n" * 8)
        print("Program stopped")
        print(cr.deinit())
        cursor.show()  # Show cursor again
        exit(0)
 
    print("\n" * 8)
    print(cr.deinit())
    cursor.show()    # Show cursor again

 
if __name__ == "__main__":
    main()
Sweet sassy molassey.  First, it runs fine. Second, I am in awe that you were able to reduce it to so few lines of code.  I will have to look at it more closely later today and see if I can follow along with what you did.  Just amazing.  Clap
Mucked around with it a bit more and tried to clean things up (also changed display to binary):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
import os
import time
import cursor
import colorama as cr
 

TAB = " " * 4
DISPLAY = cr.Style.BRIGHT + cr.Fore.RED
ON = cr.Style.BRIGHT + cr.Fore.GREEN
OFF = DISPLAY
COLUMN_POSITIONS = (5, 8, 13, 16, 21, 24)
 

def get_cursor_locations(column):
    locations = {2**i : cr.Cursor.POS(column, 9-2*i) for i in range(4)}
    locations[0] = cr.Cursor.POS(column, 11)
    return locations


def render(digit, cursors):
    binary = "{:0<4}".format(bin(digit)[:1:-1])
    for i,bit in enumerate(binary):
        color = ON if int(bit) else OFF
        print("{}{}{}".format(color, cursors[2**i], bit))


def startup():
    cursor.hide()
    cr.init()
    

def cleanup(message):
    print(DISPLAY + "\n" * 8)
    print(message)
    cursor.show()
    cr.deinit()


def run(seconds):
    for _ in range(seconds):
        os.system('cls' if os.name == 'nt' else 'clear')
        time_digits = map(int, time.strftime("%H%M%S"))
        print(TAB.join([DISPLAY, "HRS", " MIN", " SEC"]))
        for digit, column in zip(time_digits, COLUMN_POSITIONS):
            render(digit, get_cursor_locations(column))
        time.sleep(1)

    
def main():
    startup()
    seconds_to_run = 500
    try:
        run(seconds_to_run)
        cleanup("{} second timer expired.".format(seconds_to_run))
    except KeyboardInterrupt:
        cleanup("Program stopped.")

 
if __name__ == "__main__":
    main()
Anyway, not trying to steal your thunder; just having a bit of fun.
Nice. And pretty holiday colors  Smile  .  The one thing I notice is the lack of row 5 (0), so midnight 00:00:00 won't show up.

Quote:Anyway, not trying to steal your thunder; just having a bit of fun.

Steal all the thunder you want; you get some fun and I get some educating, it's all good  Dance
(Dec-31-2016, 10:17 PM)sparkz_alot Wrote: [ -> ]The one thing I notice is the lack of row 5 (0), so midnight 00:00:00 won't show up.
Midnight should work just fine.  It will be all zeros.  

Anyway, latest version.  Flickering fixed; update speed increased so we don't miss some seconds (as could happen before); deciseconds added; some overall simplifications:  
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import time
import cursor
import colorama as cr

from datetime import datetime


TAB = " " * 4
UPDATE_SPEED = 1 / 60.0
DISPLAY = cr.Style.BRIGHT + cr.Fore.RED
ON = cr.Style.BRIGHT + cr.Fore.GREEN
OFF = DISPLAY
COLUMN_POSITIONS = (5, 7, 13, 15, 21, 23, 29)
START_ROW = 3


def get_cursor_locations(column):
   return [cr.Cursor.POS(column, START_ROW+2*i) for i in range(4)]


def render(digit, cursors):
   binary = bin(digit)[2:].zfill(4)
   for bit, cursor in zip(binary, cursors):
       color = ON if int(bit) else OFF
       print("{}{}{}".format(color, cursor, bit))


def startup():
   cursor.hide()
   cr.init()


def cleanup(message):
   print(DISPLAY + "\n" * 8)
   print(message)
   cursor.show()
   cr.deinit()


def run(seconds):
   print(TAB.join([DISPLAY, "HRS", " MIN", " SEC"]))
   start_time = time.clock()
   while time.clock() - start_time < seconds:
       time_digits = map(int, datetime.now().strftime("%H%M%S%f"))      
       for digit, column in zip(time_digits, COLUMN_POSITIONS):
           render(digit, get_cursor_locations(column))
       time.sleep(UPDATE_SPEED)


def main():
   startup()
   seconds_to_run = 60
   try:
       run(seconds_to_run)
       cleanup("{} second timer expired.".format(seconds_to_run))
   except KeyboardInterrupt:
       cleanup("Program stopped.")

 
if __name__ == "__main__":
   main()
turn the volume up, there be thunder emanating from the board!
Fantastic and I like the way the flicker is completely gone.

I did make 2 minor changes (my turn to apologize  Angel ) . 

First, I added the 'clear screen' to your 'startup' function:

def startup():
    os.system('cls' if os.name == 'nt' else 'clear')
    cursor.hide()
    cr.init()
and second, I added "DS" to the new deci-second column:

    print(TAB.join([DISPLAY, "HRS", " MIN", " SEC", " DS"]))
Great to see how you turned my clunker into a Rolls Royce.  :-D
Pages: 1 2