Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
BB Korry
Published

Clock that melt time

This is the clock developed to take away the viewer's time

BeginnerWork in progressOver 1 day1,628
Clock that melt time

Things used in this project

Hardware components

ESP32 Basic Core IoT Development Kit
M5Stack ESP32 Basic Core IoT Development Kit
×1
SERVO Module Board 12 Channels
M5Stack SERVO Module Board 12 Channels
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×14

Software apps and online services

MicroPython
MicroPython

Story

Read more

Custom parts and enclosures

Overall view

Schematics

M5Stack Connection

Code

Servo motion and display

MicroPython
Servo motion and display
from m5stack import *
from m5ui import *
from uiflow import *
import time
import module
import math

#■初回変数・定数宣言
ms_count = 1000  #【定数】1秒クロックの調整時間(基準1000msec)
ub_deg = 30      #【定数】上下円盤の片表示時の調整角度(°)
t_mode_time = 8  #【定数】一時的時刻表示の有効時間(sec)
h_disp_time = 2  #【定数】"時"の表示時間(sec)
m_disp_time = 2  #【定数】"分"の表示時間(sec)
seg_red = -1     #【定数】7セグの表示色(赤)
seg_blue = 1     #【定数】7セグの表示色(青)
seg_none = 0     #【定数】7セグの表示色(表示なし)
motion_stop = 50 #【定数】サーボの次軸動作までの待機時間
s0_aj = 0        #【定数】サーボ軸補正角度
s1_aj = -6        #【定数】サーボ軸補正角度
s2_aj = 0        #【定数】サーボ軸補正角度
s3_aj = -3       #【定数】サーボ軸補正角度
s4_aj = -6      #【定数】サーボ軸補正角度
s5_aj = 0        #【定数】サーボ軸補正角度
s6_aj = 0        #【定数】サーボ軸補正角度
s7_aj = 0        #【定数】サーボ軸補正角度
s8_aj = 0        #【定数】サーボ軸補正角度
s9_aj = -6      #【定数】サーボ軸補正角度
s10_aj = -5      #【定数】サーボ軸補正角度
s11_aj = 0       #【定数】サーボ軸補正角度
s12_aj = -15     #【定数】サーボ軸補正角度
s13_aj = 0       #【定数】サーボ軸補正角度
setting_flug = 1 #設定モード中か(0:いいえ/1:はい)
t_mode_flug = 0  #一時的時刻表示中か(0:いいえ/1~:はい)
mh_disp_flug = 0 #"時""分"表示中か(0:いいえ/1~:はい)
disp_stop = 0    #画面動作ストップ中か(0:いいえ/1:はい)
setting_code = 1 #設定モード選択項目(0:モード終了確認/1:時10桁/2:時1桁/3:分10桁/4:分1桁/5:秒10桁/6:秒1桁)
m5_timer = 0     #M5内の稼働時間
s1 = 0           #"秒"1桁目の現在値
s10 = 0          #"秒"10桁目の現在値
m1 = 0           #"分"1桁目の現在値
m10 = 0          #"分"10桁目の現在値
h1 = 2           #"時"1桁目の現在値
h10 = 1          #"時"10桁目の現在値
r0 = 0           #右側7セグ(上)の現在値(0:OFF/1:ON)
r1 = 0           #右側7セグ(左上)の現在値(0:OFF/1:ON)
r2 = 0           #右側7セグ(右上)の現在値(0:OFF/1:ON)
r3 = 0           #右側7セグ(中心)の現在値(0:OFF/1:ON)
r4 = 0           #右側7セグ(左下)の現在値(0:OFF/1:ON)
r5 = 0           #右側7セグ(右下)の現在値(0:OFF/1:ON)
r6 = 0           #右側7セグ(下)の現在値(0:OFF/1:ON)
l0 = 0           #左側7セグ(上)の現在値(0:OFF/1:ON)
l1 = 0           #左側7セグ(左上)の現在値(0:OFF/1:ON)
l2 = 0           #左側7セグ(右上)の現在値(0:OFF/1:ON)
l3 = 0           #左側7セグ(中心)の現在値(0:OFF/1:ON)
l4 = 0           #左側7セグ(左下)の現在値(0:OFF/1:ON)
l5 = 0           #左側7セグ(右下)の現在値(0:OFF/1:ON)
l6 = 0           #左側7セグ(下)の現在値(0:OFF/1:ON)
sn0 = 0          #サーボ0の現在状態
sn1 = 0          #サーボ1の現在状態
sn2 = 0          #サーボ2の現在状態
sn3 = 0          #サーボ3の現在状態
sn4 = 0          #サーボ4の現在状態
sn5 = 0          #サーボ5の現在状態
sn6 = 0          #サーボ6の現在状態
sn7 = 0          #サーボ7の現在状態
sn8 = 0          #サーボ8の現在状態
sn9 = 0          #サーボ9の現在状態
sn10 = 0         #サーボ10の現在状態
sn11 = 0         #サーボ11の現在状態
sn12 = 0         #サーボ12の現在状態
sn13 = 0         #サーボ13の現在状態

#■サーボ初期設定
servo = module.get(module.SERVO)
pwm12 = machine.PWM(machine.Pin(2))
pwm12.freq(50)
pwm13 = machine.PWM(machine.Pin(5))
pwm13.freq(50)

#■画面初期設定
setScreenColor(0x000000)
title0 = M5Title(title="mode:setting", x=3, fgcolor=0xFFFFFF, bgcolor=0x0000ff)
label0 = M5TextBox(95, 70, ":", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)
label1 = M5TextBox(30, 70, "1", lcd.FONT_DejaVu40, 0x0000ff, rotate=0)
label2 = M5TextBox(60, 70, "2", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)
label3 = M5TextBox(130, 70, "0", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)
label4 = M5TextBox(160, 70, "0", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)
label5 = M5TextBox(230, 70, "0", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)
label6 = M5TextBox(260, 70, "0", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)
label7 = M5TextBox(50, 110, "next", lcd.FONT_Default, 0xFFFFFF, rotate=0)
label8 = M5TextBox(140, 110, "down", lcd.FONT_Default, 0xFFFFFF, rotate=0)
label9 = M5TextBox(242, 110, "up", lcd.FONT_Default, 0xFFFFFF, rotate=0)
label10 = M5TextBox(195, 70, ":", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)

#■ボタンA押したときの動作
def buttonA_wasPressed():
    global setting_flug, setting_code
    
    #設定モードでない時:設定モードに切り替える
    if setting_flug == 0:
        if disp_stop == 0:
            if t_mode_flug == 0:
                setting_flug = 1
                setting_code = 1
                
    #設定モードの時:設定項目を送る
    else:
        if setting_code >= 6:
            setting_code = 0
            
        else:
            setting_code += 1
            
    #■画面更新
    screen_refresh()
btnA.wasPressed(buttonA_wasPressed)

#■ボタンB押したときの動作
def buttonB_wasPressed():
    global setting_flug,t_mode_flug,s1,s10,m1,m10,h1,h10
    
    #設定モードでない時:一時的時刻表示を行う
    if setting_flug == 0:
        if disp_stop == 0:    
            if t_mode_flug == 0:
                t_mode_flug = 1
                
    #設定モードの時:設定項目をマイナスする(または設定終了する)
    else:
        if setting_code == 0:
            setting_flug = 0
            
        elif setting_code == 1:
            if h10 <= 0:
                h10 = 2
                
            else:
                h10 -= 1
                
            if h10 == 2:
                if h1 >= 4:
                    h1 = 3
                    
        elif setting_code == 2:
            if h10 == 2:
                if h1 <= 0:
                    h1 = 3
                    
                else:
                    h1 -= 1
                    
            else:
                if h1 <= 0:
                    h1 = 9
                    
                else:
                    h1 -= 1
                    
        elif setting_code == 3:
            if m10 <= 0:
                m10 = 5
                
            else:
                m10 -= 1
                
        elif setting_code == 4:
            if m1 <= 0:
                m1 = 9
                
            else:
                m1 -= 1
                
        elif setting_code == 5:
            if s10 <= 0:
                s10 = 5
                
            else:
                s10 -= 1
                
        elif setting_code == 6:
            if s1 <= 0:
                s1 = 9
                
            else:
                s1 -= 1
                
    #■画面更新
    screen_refresh()              
btnB.wasPressed(buttonB_wasPressed)

#■ボタンC押したときの動作
def buttonC_wasPressed():
    global setting_flug,disp_stop,s1,s10,m1,m10,h1,h10
    #設定モードでない時:原点復帰を行い、時刻表示を一時停止する
    
    if setting_flug == 0:
        if disp_stop == 0:
            if t_mode_flug == 0:     
                disp_stop = 1
                servo_move(seg_none)
        else:
            disp_stop = 0
            
    #設定モードの時:設定項目をプラスする(または設定終了する)
    else:
        if setting_code == 0:
            setting_flug = 0
            
        elif setting_code == 1:
            if h10 >= 2:
                h10 = 0
                
            else:
                h10 += 1
                
            if h10 == 2:
                if h1 >= 4:
                    h1 = 3
                    
        elif setting_code == 2:
            if h10 == 2:
                if h1 >= 3:
                    h1 = 0
                    
                else:
                    h1 += 1
                    
            else:
                if h1 >= 9:
                    h1 = 0
                    
                else:
                    h1 += 1
                    
        elif setting_code == 3:
            if m10 >= 5:
                m10 = 0
                
            else:
                m10 += 1
                
        elif setting_code == 4:
            if m1 >= 9:
                m1 = 0
                
            else:
                m1 += 1
                
        elif setting_code == 5:
            if s10 >= 5:
                s10 = 0
                
            else:
                s10 += 1
                
        elif setting_code == 6:
            if s1 >= 9:
                s1 = 0
                
            else:
                s1 += 1
                
    #■画面更新
    screen_refresh()
btnC.wasPressed(buttonC_wasPressed)

#■タイマカウントのイベント
def tmr1sec():
    global mh_disp_flug,t_mode_flug,s1,s10,m1,m10,h1,h10
    
    #"時""分"表示中の時の残り時間計算
    if mh_disp_flug != 0:
        mh_disp_flug += 1
        if mh_disp_flug >= 1 + h_disp_time + m_disp_time + 1:
            mh_disp_flug = 0
            
    #一時的時刻表示が要求されたとき、"時""分"表示フラグを立てる
    if t_mode_flug == 1:
        mh_disp_flug = 1
        
    #一時的時刻表示の残り時間計算
    if t_mode_flug != 0:
        t_mode_flug += 1
        if t_mode_flug >= 1 + t_mode_time:
            t_mode_flug = 0
            
    #設定中でなければ時刻を1秒進める
    if setting_flug == 0:
        s1 += 1
        
    #時刻表示の繰り上がり計算
    if s1 >= 10:
        s1 = 0
        s10 += 1
        if s10 >= 6:
            if setting_flug == 0:
                if t_mode_flug == 0:     
                    if disp_stop == 0:
                        mh_disp_flug = 1
                        
            s10 = 0
            m1 += 1
            if m1 >= 10:
                m1 = 0
                m10 += 1
                if m10 >= 6:
                    if t_mode_flug == 0:     
                        if disp_stop == 0:
                            mh_disp_flug = -1   
                            
                    m10 = 0
                    h1 += 1
                    if h10 <= 1:
                        if h1 >= 10:
                            h1 = 0
                            h10 += 1
                            
                        else:
                            if h1 >= 5:
                                h1 = 0
                                h10 =0
                                
    #一時停止状態でなければサーボを動かす
    if disp_stop == 0:
        #"時""分"表示中でなければ、"秒"を赤色で表示
        if mh_disp_flug == 0:
            r_set(s1)
            l_set(s10)
            servo_move(seg_red)
        
        #1時間経過時は特殊表示をする
        elif mh_disp_flug == -1:
            m5_timer = time.ticks_ms()
            r_set(8)
            l_set(8)        
            servo_move(seg_none)
            wait_ms(100)
            servo_move(seg_red)            
            wait_ms(100)
            servo_move(seg_blue)
            wait_ms(100)
            servo_move(seg_red)            
            wait_ms(100)           
            servo_move(seg_none)
            wait_ms(400)             
            r_set(h1)
            l_set(h10)  
            servo_move(seg_blue)
            wait_ms(400) 
            servo_move(seg_none)            
            wait_ms(400) 
            servo_move(seg_blue)
            wait_ms(400) 
            servo_move(seg_none) 
            wait_ms(400) 
            servo_move(seg_blue)
            wait_ms(1800)
            
            if time.ticks_ms() - m5_timer >= 1000:
                s1 += math.floor((time.ticks_ms() - m5_timer) / 1000)
            
        #"時""分"表示開始直後は、"時"を青色で表示
        elif mh_disp_flug == 1:
            r_set(h1)
            l_set(h10)
            servo_move(seg_blue)
            
        #"時"表示時間終了後は、一旦無表示
        elif mh_disp_flug == 1 + h_disp_time:
            r_set(0)
            l_set(0)
            servo_move(seg_none) 
            
        #最後に、"分"を青色で表示
        elif mh_disp_flug == 1 + h_disp_time + 1:
            r_set(m1)
            l_set(m10)
            servo_move(seg_blue) 

#■右側7セグの表示設定
def r_set(num):
    global r0,r1,r2,r3,r4,r5,r6
    if num == 1:
        r0 = 0
        r1 = 0
        r2 = 1
        r3 = 0
        r4 = 0
        r5 = 1
        r6 = 0
        
    elif num == 2:
        r0 = 1
        r1 = 0
        r2 = 1
        r3 = 1
        r4 = 1
        r5 = 0
        r6 = 1
        
    elif num == 3:
        r0 = 1
        r1 = 0
        r2 = 1
        r3 = 1
        r4 = 0
        r5 = 1
        r6 = 1
        
    elif num == 4:
        r0 = 0
        r1 = 1
        r2 = 1
        r3 = 1
        r4 = 0
        r5 = 1
        r6 = 0
        
    elif num == 5:
        r0 = 1
        r1 = 1
        r2 = 0
        r3 = 1
        r4 = 0
        r5 = 1
        r6 = 1
        
    elif num == 6:
        r0 = 1
        r1 = 1
        r2 = 0
        r3 = 1
        r4 = 1
        r5 = 1
        r6 = 1
        
    elif num == 7:
        r0 = 1
        r1 = 0
        r2 = 1
        r3 = 0
        r4 = 0
        r5 = 1
        r6 = 0
        
    elif num == 8:
        r0 = 1
        r1 = 1
        r2 = 1
        r3 = 1
        r4 = 1
        r5 = 1
        r6 = 1
        
    elif num == 9:
        r0 = 1
        r1 = 1
        r2 = 1
        r3 = 1
        r4 = 0
        r5 = 1
        r6 = 1
        
    elif num == 0:
        r0 = 1
        r1 = 1
        r2 = 1
        r3 = 0
        r4 = 1
        r5 = 1
        r6 = 1

#■左側7セグの表示設定
def l_set(num):
    global l0,l1,l2,l3,l4,l5,l6
    if num == 1:
        l0 = 0
        l1 = 0
        l2 = 1
        l3 = 0
        l4 = 0
        l5 = 1
        l6 = 0
        
    elif num == 2:
        l0 = 1
        l1 = 0
        l2 = 1
        l3 = 1
        l4 = 1
        l5 = 0
        l6 = 1
        
    elif num == 3:
        l0 = 1
        l1 = 0
        l2 = 1
        l3 = 1
        l4 = 0
        l5 = 1
        l6 = 1
        
    elif num == 4:
        l0 = 0
        l1 = 1
        l2 = 1
        l3 = 1
        l4 = 0
        l5 = 1
        l6 = 0
        
    elif num == 5:
        l0 = 1
        l1 = 1
        l2 = 0
        l3 = 1
        l4 = 0
        l5 = 1
        l6 = 1
        
    elif num == 6:
        l0 = 1
        l1 = 1
        l2 = 0
        l3 = 1
        l4 = 1
        l5 = 1
        l6 = 1
        
    elif num == 7:
        l0 = 1
        l1 = 0
        l2 = 1
        l3 = 0
        l4 = 0
        l5 = 1
        l6 = 0
        
    elif num == 8:
        l0 = 1
        l1 = 1
        l2 = 1
        l3 = 1
        l4 = 1
        l5 = 1
        l6 = 1
        
    elif num == 9:
        l0 = 1
        l1 = 1
        l2 = 1
        l3 = 1
        l4 = 0
        l5 = 1
        l6 = 1
        
    elif num == 0:
        l0 = 1
        l1 = 1
        l2 = 1
        l3 = 0
        l4 = 1
        l5 = 1
        l6 = 1

#■サーボ動作
def servo_move(color):
    global sn0,sn1,sn2,sn3,sn4,sn5,sn6,sn7,sn8,sn9,sn10,sn11,sn12,sn13,pwm12,pwm13

    #現在角度から各配置までの移動処理
    if r0 * color != sn0:
        servo.write_angle(0, 90 + r0 * color * 90 + (1 - r0 * color^2)*s0_aj)
        wait_ms(motion_stop)
        sn0 = r0 * color

    if r1 * color != sn1:
        servo.write_angle(1, 90 + r1 * color * 90 + (1 - r1 * color^2)*s1_aj)
        wait_ms(motion_stop)
        sn1 = r1 * color

    if r2 * color != sn2:
        servo.write_angle(2, 90 + r2 * color * 90 + (1 - r2 * color^2)*s2_aj)
        wait_ms(motion_stop)
        sn2 = r2 * color

    if r3 * color != sn3:
        servo.write_angle(3, 90 + r3 * color * 90 + (1 - r3 * color^2)*s3_aj)
        wait_ms(motion_stop)
        sn3 = r3 * color

    if r4 * color != sn4:
        servo.write_angle(4, 90 + r4 * color * 90 + (1 - r4 * color^2)*s4_aj)
        wait_ms(motion_stop)
        sn4 = r4 * color

    if r5 * color != sn5:
        servo.write_angle(5, 90 + r5 * color * 90 + (1 - r5 * color^2)*s5_aj)
        wait_ms(motion_stop)
        sn5 = r5 * color

    if r6 * color != sn6:
        servo.write_angle(6, 90 + r6 * color * 90 + (1 - r6 * color^2)*s6_aj)
        wait_ms(motion_stop)
        sn6 = r6 * color

    if l0 * color != sn7:
        servo.write_angle(7, 90 + l0 * color * 90 + (1 - l0 * color^2)*s7_aj)
        wait_ms(motion_stop)
        sn7 = l0 * color

    if l1 * color != sn8:
        servo.write_angle(8, 90 + l1 * color * 90 + (1 - l1 * color^2)*s8_aj)
        wait_ms(motion_stop)
        sn8 = l1 * color

    if l2 * color != sn9:
        servo.write_angle(9, 90 + l2 * color * 90 + (1 - l2 * color^2)*s9_aj)
        wait_ms(motion_stop)
        sn9 = l2 * color

    if l3 * color != sn10:
        servo.write_angle(10, 90 + l3 * color * 90 + (1 - l3 * color^2)*s10_aj)
        wait_ms(motion_stop)
        sn10 = l3 * color

    if l4 * color != sn11:
        servo.write_angle(11, 90 + l4 * color * 90 + (1 - l4 * color^2)*s11_aj)
        wait_ms(motion_stop)
        sn11 = l4 * color

    if l5 * color != sn12:
        l5calc = 90 + l5 * color * 90 +(1 - l5* color^2)*s12_aj
        pwm12.duty(2.7 + l5calc/19.35)
        wait_ms(motion_stop)
        sn12 = l5 * color

    if l6 * color != sn13:
        l6calc = 90 + l6 * color * 90 +(1 - l6 * color^2)*s13_aj
        pwm13.duty(2.7 + l6calc/19.35)
        wait_ms(motion_stop)
        sn13 = l6 * color

#■画面更新
def screen_refresh():
    #時刻の文字表示
    label1.setText(str(h10))
    label2.setText(str(h1))
    label3.setText(str(m10))
    label4.setText(str(m1))
    label5.setText(str(s10))
    label6.setText(str(s1))  
    
    #タイトルの文字表示・色表示
    if setting_flug == 1:
        title0.setTitle('mode:setting')
        title0.setBgColor(0x0000ff)
        
    elif disp_stop == 1:
        title0.setTitle('mode:stop')
        title0.setBgColor(0x606060)
        
    elif mh_disp_flug >= 1:
        title0.setTitle('mode:H/M disp')
        title0.setBgColor(0x008000)
        
    else:
        title0.setTitle('mode:S disp')
        title0.setBgColor(0xff0000)
        
    #ボタン機能の文字表示
    if setting_flug == 1:
        if setting_code == 0:
            label7.setText('next')
            label8.setText('-')
            label9.setText('end')
            
        else:
            label7.setText('next')
            label8.setText('down')
            label9.setText('up')
            
    else:
        label7.setText('Set')
        label8.setText('M/H')
        label9.setText('Stop')
        
    #時刻の色表示
    if setting_flug == 1:
        if setting_code == 0:
            label1.setColor(0x0000ff)
            label2.setColor(0x0000ff)
            label3.setColor(0x0000ff)
            label4.setColor(0x0000ff)
            label5.setColor(0x0000ff)
            label6.setColor(0x0000ff)
            
        elif setting_code == 1:
            label1.setColor(0x0000ff)
            label2.setColor(0xffffff)
            label3.setColor(0xffffff)
            label4.setColor(0xffffff)
            label5.setColor(0xffffff)
            label6.setColor(0xffffff)
            
        elif setting_code == 2:
            label1.setColor(0xffffff)
            label2.setColor(0x0000ff)
            label3.setColor(0xffffff)
            label4.setColor(0xffffff)
            label5.setColor(0xffffff)
            label6.setColor(0xffffff)
            
        elif setting_code == 3:
            label1.setColor(0xffffff)
            label2.setColor(0xffffff)
            label3.setColor(0x0000ff)
            label4.setColor(0xffffff)
            label5.setColor(0xffffff)
            label6.setColor(0xffffff)
            
        elif setting_code == 4:
            label1.setColor(0xffffff)
            label2.setColor(0xffffff)
            label3.setColor(0xffffff)
            label4.setColor(0x0000ff)
            label5.setColor(0xffffff)
            label6.setColor(0xffffff)
            
        elif setting_code == 5:
            label1.setColor(0xffffff)
            label2.setColor(0xffffff)
            label3.setColor(0xffffff)
            label4.setColor(0xffffff)
            label5.setColor(0x0000ff)
            label6.setColor(0xffffff)
            
        elif setting_code == 6:
            label1.setColor(0xffffff)
            label2.setColor(0xffffff)
            label3.setColor(0xffffff)
            label4.setColor(0xffffff)
            label5.setColor(0xffffff)
            label6.setColor(0x0000ff)
            
    elif disp_stop == 1:
        label1.setColor(0x606060)
        label2.setColor(0x606060)
        label3.setColor(0x606060)
        label4.setColor(0x606060)
        label5.setColor(0x606060)
        label6.setColor(0x606060)
        
    elif mh_disp_flug >= 1:
        if mh_disp_flug >= 1 + h_disp_time:
            label1.setColor(0xffffff)
            label2.setColor(0xffffff)
            label3.setColor(0x00ff00)
            label4.setColor(0x00ff00)
            label5.setColor(0xffffff)
            label6.setColor(0xffffff)
            
        else:
            label1.setColor(0x00ff00)
            label2.setColor(0x00ff00)
            label3.setColor(0xffffff)
            label4.setColor(0xffffff)
            label5.setColor(0xffffff)
            label6.setColor(0xffffff)  
            
    else:    
        label1.setColor(0xffffff)
        label2.setColor(0xffffff)
        label3.setColor(0xffffff)
        label4.setColor(0xffffff)
        label5.setColor(0xff0000)
        label6.setColor(0xff0000)

#■タイマー動作
while True:
    if (time.ticks_ms()) >= m5_timer + ms_count :
        m5_timer = time.ticks_ms()
        tmr1sec()
        screen_refresh() 
    wait_ms(2)

Credits

BB Korry

BB Korry

1 project • 0 followers

Comments