Advertisement
TonyGo

Ben's Clock v16

Feb 10th, 2025
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.75 KB | None | 0 0
  1. # Ben's Clock v16 for PRESTO  ===================== NOT WORKING ==============
  2. # Change colours via buttons - Press X to start
  3. # Author: Tony Goodhew - 30th Jan 2025 - Tonygo2 on Pimoroni Forum
  4.  
  5. # Requirements: PRESTO with Qw/ST Pad fitted and library installed
  6. # Uses Vector fonts on hour elements
  7.  
  8. # Press Y to set time and A to return and RUN on
  9. # L and R switch between Hours and Minutes
  10. # Press U and D to change value
  11. # RED is active value GREEN is inactive
  12. # 5 Minute positions emphasised
  13. # Uses Epoch time - OK until 2038
  14. # Ajusted to Ben's Roll-over sequence
  15. # Pad + and - turn visible numbers ON and OFF
  16.  
  17. # X to start change colour section
  18. # U and D to cycle through colours
  19. # B to return to running clock
  20. # Will probably need to reset time
  21.  
  22. # ========== To Do List =======
  23. # Remove Jump Flag line 369 approx to stop time jumps
  24.  
  25.  
  26. import gc
  27. import time
  28. from machine import I2C, Pin
  29. import math
  30. from qwstpad import QwSTPad
  31. from presto import Presto
  32. from picovector import ANTIALIAS_FAST, PicoVector, Polygon, Transform
  33.  
  34. # Setup for the Presto display
  35. presto = Presto(full_res=True)
  36. display = presto.display
  37. touch = presto.touch # Activate touch
  38. i2c = I2C(id=0,scl=Pin(41), sda=Pin(40)) # PRESTO
  39.  
  40. # Connect single default I2C address QwSTPad
  41. try:
  42.     qwstpad = QwSTPad(i2c, 0x21)
  43. except OSError:
  44.     print("QwSTPad: Not Connected ... Exiting")
  45.     raise SystemExit
  46.  
  47. # Turn of LED on qw/stpad
  48. qwstpad.set_leds(0)
  49.  
  50. WIDTH, HEIGHT = display.get_bounds()
  51. #WIDTH = 200
  52. #HEIGHT = WIDTH
  53. display.set_font("bitmap8") # Change the font
  54.  
  55. # Create some colours - not all used at the moment
  56. RED = display.create_pen(255,0,0)
  57. PINK = display.create_pen(250, 125, 180)
  58. PINK2 = display.create_pen(247,21,157)
  59. ORANGE = display.create_pen(245, 165, 4)
  60. CLEMENTINE = display.create_pen(255,89,0)
  61. YELLOW = display.create_pen(255, 255, 0)
  62. GREEN = display.create_pen(0,255,0)
  63. GREEN2 = display.create_pen(71, 225, 32)
  64. CYAN = display.create_pen(0,255,255)
  65. MAGENTA = display.create_pen(255,0,255)
  66. BLUE = display.create_pen(20,0,255)
  67. WHITE = display.create_pen(255, 255, 255)
  68. GREY = display.create_pen(75, 75, 75)
  69. DKGREY = display.create_pen(20,20,35)
  70. BLACK = display.create_pen(0, 0, 0)
  71.  
  72. colours = [BLUE,RED,PINK,PINK2,ORANGE,CLEMENTINE,YELLOW,GREEN,GREEN2,CYAN,MAGENTA]
  73. col_leng = len(colours)
  74.  
  75. # Pico Vector setup section
  76. vector = PicoVector(display)
  77. vector.set_antialiasing(ANTIALIAS_FAST)
  78. t = Transform()
  79.  
  80. vector.set_font("Roboto-Medium.af", 54)
  81. vector.set_font_letter_spacing(100)
  82. vector.set_font_word_spacing(100)
  83. vector.set_transform(t)
  84.  
  85. vector.set_font_size(20)
  86.  
  87. # A few procedures to be used later
  88.  
  89. def clean(): # Clear the screen to Black
  90.     display.set_pen(BLACK)
  91.     display.clear()
  92.  
  93. def face(hours,mins,secs,hcol,mcol,scol):   # This one majority of the work
  94.  
  95.     cx = int(WIDTH /2)  # Centre of clock
  96.     cy = int(HEIGHT /2)
  97.     l = cy -1             # Max radius
  98.  
  99.     r1 = int(l * 0.62)
  100.     r2 = int(l * 0.58)   # minutes
  101.     r3 = int(l * 0.44)
  102.     r4 = int(l * 0.41)   # hours
  103.     r5 = int(l * 0.05)
  104.    
  105.     # SECONDS
  106.     limit = secs * 6 + 1
  107.     stop = 360
  108.     if secs == 0:   # Ben's adjustment
  109.         limit = 999
  110.         stop = 366
  111.     for angle in range(0,stop,6):
  112.         display.set_pen(minor)            
  113.         if (angle < limit) and (angle > 0):
  114.             display.set_pen(scol)
  115.                
  116.         if thin :
  117.             # Thin
  118.             yy = -int(round(l * math.cos(math.radians(angle))))
  119.             xx = int(round(l * math.sin(math.radians(angle))))    
  120.             display.line(cx,cy,cx+xx,cy+yy)
  121.         else:
  122.             # Thick
  123.             yyp = -int(round(l * math.cos(math.radians(angle+st))))
  124.             xxp = int(round(l * math.sin(math.radians(angle+st))))
  125.             yym = -int(round(l * math.cos(math.radians(angle-st))))
  126.             xxm = int(round(l * math.sin(math.radians(angle-st))))
  127.             display.triangle(cx,cy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  128.            
  129.         if (secs == 0) and secspecial: # Special case
  130.             display.set_pen(major)
  131.             angle = 0
  132.             if thin :
  133.                 # Thin
  134.                 yy = -int(round(l * math.cos(math.radians(angle))))
  135.                 xx = int(round(l * math.sin(math.radians(angle))))    
  136.                 display.line(cx,cy,cx+xx,cy+yy)
  137.             else:
  138.                 # Thick
  139.                 yyp = -int(round(l * math.cos(math.radians(angle+st))))
  140.                 xxp = int(round(l * math.sin(math.radians(angle+st))))
  141.                 yym = -int(round(l * math.cos(math.radians(angle-st))))
  142.                 xxm = int(round(l * math.sin(math.radians(angle-st))))
  143.                 display.triangle(cx,cy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  144.                    
  145.     display.set_pen(BLACK)
  146.     display.circle(cx,cy,r1)
  147.  
  148.     # MINUTES
  149.     l = r2
  150.     limit = mins * 6 + 1
  151.     stop = 360
  152.     if mins == 0 and (secs == 0):   # Ben's adjustment
  153.         limit = 999
  154.         stop = 366
  155.  
  156.     for angle in range(0,stop,6):
  157.         display.set_pen(minor)
  158.         if (angle < limit) and (angle > 0):
  159.             display.set_pen(mcol)
  160.         if thin:
  161.             # Thin
  162.             yy = -int(round(l * math.cos(math.radians(angle))))
  163.             xx = int(round(l * math.sin(math.radians(angle))))
  164.             display.line(cx,cy,cx+xx,cy+yy)
  165.         else:
  166.             # Thick
  167.             yyp = -int(round(l * math.cos(math.radians(angle+mt))))
  168.             xxp = int(round(l * math.sin(math.radians(angle+mt))))
  169.             yym = -int(round(l * math.cos(math.radians(angle-mt))))
  170.             xxm = int(round(l * math.sin(math.radians(angle-mt))))
  171.             display.triangle(cx,cy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  172.        
  173.         # Needed if you consider zero minutes need to be shown
  174.         if (mins == 0) and minspecial and (secs == 0): # Special case
  175.             display.set_pen(major)
  176.             angle = 0
  177.             if thin:
  178.                 # Thin
  179.                 yy = -int(round(l * math.cos(math.radians(angle))))
  180.                 xx = int(round(l * math.sin(math.radians(angle))))
  181.                 display.line(cx,cy,cx+xx,cy+yy)
  182.             else:
  183.                 # Thick
  184.                 yyp = -int(round(l * math.cos(math.radians(angle+mt))))
  185.                 xxp = int(round(l * math.sin(math.radians(angle+mt))))
  186.                 yym = -int(round(l * math.cos(math.radians(angle-mt))))
  187.                 xxm = int(round(l * math.sin(math.radians(angle-mt))))
  188.                 display.triangle(cx,cy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  189.        
  190.     display.set_pen(BLACK)
  191.     display.circle(cx,cy,r3)
  192.  
  193.     # HOURS
  194.     l = r5
  195.     lh = r4
  196.     ht = 12
  197.     display.set_pen(hcol)
  198.     for h in range(1,13,1):
  199.         angle = h * 30
  200.         display.set_pen(minor)
  201.         if h <= hours:
  202.             display.set_pen(major)
  203.        
  204.         yy = -int(round(l * math.cos(math.radians(angle))))
  205.         xx = int(round(l * math.sin(math.radians(angle))))
  206.        
  207.         yyp = -int(round(lh * math.cos(math.radians(angle+ht))))
  208.         xxp = int(round(lh * math.sin(math.radians(angle+ht))))
  209.         yym = -int(round(lh * math.cos(math.radians(angle-ht))))
  210.         xxm = int(round(lh * math.sin(math.radians(angle-ht))))
  211.         display.triangle(cx+xx,cy+yy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  212.  
  213.     if numbers:  # TESTING and Learning "+" and "-" control on qwstpad
  214.         display.set_pen(YELLOW)
  215.         display.text("M: "+str(mins),5,5,90,3)
  216.         display.text("S: "+str(secs),420,5,90,3)
  217.         display.text("H: "+str(hours),5,50,100,3)
  218.         display.set_pen(DKGREY)
  219.         ''' # Using Crude font
  220.        display.text("9",155,235,50,4)
  221.        display.text("3",320,235,50,4)
  222.        display.text("6",238,310,50,4)
  223.        display.text("12",235,155,50,4)
  224.        '''
  225.         # Using vector font
  226.         vector.set_font_size(40)
  227. #        display.set_pen(RED)  # for testing
  228.         vector.text("9", 149,253)  # ("Text", x,y)
  229.         vector.text("3",313,253)
  230.         vector.text("6",232,330)
  231.         vector.set_font_size(32)
  232.         vector.text("12",223,171)
  233.                
  234.     presto.update()
  235.    
  236. # ============= SET TIME SECTION =================================
  237.  
  238. def show_vals(cur,val):
  239.     for i in range(2):
  240.         xx = 20 + i * 60
  241.         display.set_pen(RED)
  242.         if cur == i:
  243.             display.set_pen(YELLOW)
  244.         display.text(str(val[i]),xx,400,200,3)
  245.  
  246. def show_mins(m,c):
  247.     cx = int(WIDTH /2)  # Centre of clock
  248.     cy = int(HEIGHT /2)
  249.     l = cy              # Max radius
  250.  
  251.     r1 = int(l * 0.62)
  252.     r2 = int(l * 0.58)   # minutes
  253.     r3 = int(l * 0.44)
  254.     r4 = int(l * 0.41)   # hours
  255.     r5 = int(l * 0.05)
  256.  
  257.     angle = m*6 + 1
  258.     l = r2
  259.     mt = 1.7 # minutes thickness
  260.     st = 1.9 # seconds thickness
  261.    
  262.     # Empty minutes
  263.     for angle2 in range(0,360,6):
  264.         display.set_pen(minor)
  265.         if angle2 % 5 == 0:  # Indicate 5 min intervals
  266.             display.set_pen(GREY)
  267.            
  268.         # Thick
  269.         yyp = -int(round(l * math.cos(math.radians(angle2+mt))))
  270.         xxp = int(round(l * math.sin(math.radians(angle2+mt))))
  271.         yym = -int(round(l * math.cos(math.radians(angle2-mt))))
  272.         xxm = int(round(l * math.sin(math.radians(angle2-mt))))
  273.         display.triangle(cx,cy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  274.    
  275.     display.set_pen(c)
  276.     yyp = -int(round(l * math.cos(math.radians(angle+mt))))
  277.     xxp = int(round(l * math.sin(math.radians(angle+mt))))
  278.     yym = -int(round(l * math.cos(math.radians(angle-mt))))
  279.     xxm = int(round(l * math.sin(math.radians(angle-mt))))
  280.     display.triangle(cx,cy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  281.     display.set_pen(BLACK)
  282.     display.circle(cx,cy,r3)
  283.  
  284. def show_hours(h,c):
  285.    
  286.     cx = int(WIDTH /2)  # Centre of clock
  287.     cy = int(HEIGHT /2)
  288.     l = cy              # Max radius
  289.     r1 = int(l * 0.62)
  290.     r2 = int(l * 0.58)
  291.     r3 = int(l * 0.44)
  292.     r4 = int(l * 0.41)
  293.     r5 = int(l * 0.05)
  294.     l = r5
  295.     lh = r4
  296.     ht = 12
  297.        
  298.     display.set_pen(c)    
  299.     angle = h * 30
  300.    
  301.     yy = -int(round(l * math.cos(math.radians(angle))))
  302.     xx = int(round(l * math.sin(math.radians(angle))))
  303.     yyp = -int(round(lh * math.cos(math.radians(angle+ht))))
  304.     xxp = int(round(lh * math.sin(math.radians(angle+ht))))
  305.     yym = -int(round(lh * math.cos(math.radians(angle-ht))))
  306.     xxm = int(round(lh * math.sin(math.radians(angle-ht))))
  307.     display.triangle(cx+xx,cy+yy,cx+xxp,cy+yyp,cx+xxm,cy+yym)
  308.  
  309. def set_time():
  310.     qwstpad.set_leds(2)  # qw/stpad LEDS off - set time indication
  311.     p = 0    
  312.     show_vals(p,val)
  313.     presto.update()
  314.  
  315.     buttons = qwstpad.read_buttons()
  316.     while buttons["A"] == False: # HALT loop with button'A'
  317.         clean()
  318.         diff = 1
  319.         # Read all the buttons from the qwstpad
  320.         buttons = qwstpad.read_buttons()
  321.         if buttons["U"] == True:
  322.             val[p] = val[p] + diff
  323.             if val[p] > maxx[p]:
  324.                 val[p] = minn[p]
  325.         elif buttons["D"] == True:
  326.             val[p] = val[p] - diff
  327.             if val[p] < minn[p]:
  328.                 val[p] = maxx[p]
  329.         elif (buttons["R"] == True) or (buttons["L"] == True):
  330.             if p == 1:
  331.                 p = 0
  332.             else:
  333.                 p = 1
  334.  
  335.         # Show the changed value
  336.         if p == 0:
  337.             mcol = GREEN
  338.             hcol = RED            
  339.         else:
  340.             mcol = RED
  341.             hcol = GREEN
  342.         show_mins(val[1],mcol)
  343.         show_hours(val[0],hcol)
  344.         show_vals(p,val)
  345.         presto.update()
  346.        
  347.         # Wait for button release
  348.         while (buttons["U"]) or (buttons["D"]) or (buttons["L"]) or (buttons["R"]):
  349.             buttons = qwstpad.read_buttons()
  350.         time.sleep(0.1)
  351.  
  352.     # "A" has been pressed - return the values
  353.     clean()
  354.     presto.update()
  355.     h = val[0]
  356.     m = val[1]
  357.     s = 0
  358.     qwstpad.set_leds(0)  # qw/stpad LEDS off
  359.     return (h,m,s)
  360.  
  361. # ========== SET TIME SECTION END ==========================
  362.  
  363. # ================ Change colour section ===================
  364. def get_col(p,cl ):
  365.     delay = 0.15
  366.     clean()
  367.     display.set_pen(colours[p])
  368.     display.clear()
  369.     presto.update()
  370.     running = True
  371.     while running:
  372.         buttons = qwstpad.read_buttons()
  373.         if buttons["U"] == True:
  374.             p = p + 1
  375.             if p == cl:
  376.                 p = 0
  377.         if buttons["D"] == True:
  378.             p = p - 1
  379.             if p < 0:
  380.                 p = cl -1
  381.         display.set_pen(colours[p])
  382.         print(p)
  383.         display.clear()
  384.         presto.update()
  385.        
  386.         if buttons["B"] == True:
  387.             running = False
  388.         # Wait for button release
  389.         while (buttons["U"] == True) or (buttons["D"] == True):
  390.             buttons = qwstpad.read_buttons()
  391.            
  392.     clean()
  393.     return(p)
  394. # ========== END OF COLOUR CHANGE SECTION ============    
  395.  
  396. # ################# Clock running section #####################
  397.  
  398. # Initial time and colours
  399. hours = 10
  400. mins =59
  401. secs = 55
  402. cp = 0
  403. major = colours[cp]        # Major colour
  404. minor = DKGREY      # Minor colour
  405. maxx = [12,59]
  406. minn = [1,0]
  407. val = [hours,mins]
  408. yy = 200
  409.  
  410. mt = 1.7 # minutes thickness
  411. st = 1.9 # seconds thickness
  412.  
  413. # TESTING FLAGS
  414. thin = False
  415. numbers = True
  416. jump = True
  417. # Show zero secs and mins - FLAGS
  418. minspecial = True
  419. secspecial = False
  420.  
  421. last_second = None    # Extra ======================
  422.  
  423. # ################### Clock running loop ######################
  424. #  Time control Extras ===============
  425. now = time.time()
  426. old_time = now
  427. while True:    
  428.     t_start = time.ticks_ms()
  429.     now = time.time()
  430.     old_time = now
  431. #    year, month, day, hour, minute, second, _, _ = time.localtime()  
  432.     #end time control TOP========================================
  433.    
  434.     clean()
  435.     face(hours,mins,secs,major,major,major)
  436.     secs = secs + 1
  437.     # Temp JUMP code ============= FOR TESTING =======================
  438.     if jump:
  439.         if secs == 7:
  440.             secs = 55
  441.      #============== =================================================
  442.     if secs == 60:
  443.         secs = 0
  444.         mins = mins + 1
  445.         if mins == 60:
  446.             mins = 0
  447.             hours = hours +1
  448.             if hours == 13:
  449.                 hours = 1
  450.  
  451.     buttons = qwstpad.read_buttons()
  452.     if buttons["Y"] == True:            # Jump to SET TIME section
  453.         val = [hours,mins]              # Start from current time
  454.         hours, mins,secs = set_time()
  455.     if buttons["-"] == True:
  456.         numbers = False
  457.     if buttons["+"] == True:
  458.         numbers = True
  459.     if buttons["X"] == True:
  460.         cp = get_col(cp,col_leng)
  461.         major = colours[cp]
  462.    
  463.     gc.collect()
  464.     # Time control - Wait for next second
  465.     while old_time == now:        
  466.         time.sleep_ms(10)
  467.         now = time.time()
  468.     old_time = now
  469.    
  470.     t_end = time.ticks_ms()
  471.     print(f"Took {t_end - t_start}ms")
  472.  
  473.  
  474.  
  475.  
  476.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement