3.2. Zamanlama

time modülü, uyumak (betiği bilinen bir süre boyunca duraklatmak) ve bir şeyin ne kadar sürdüğünü ölçmek için kullanılan işlevleri bir araya getirir. Bir mikrodenetleyicide bunlar olsa iyi olur türünden şeyler değildir; betiğin dış dünyayla etkileşimlerini bunlarla ayarladığı yollardır – bir pinin ne kadar süre yüksek tutulacağı, örnekler arasında ne kadar beklenileceği, bir düğmeye en son ne kadar süre önce basıldığı.

3.2.1. Uyumak

Üç uyku işlevi betiği istenen süre boyunca engeller:

  • time.sleep(s)s saniye duraklat. Bir kayan noktalı sayı kabul eder, yani time.sleep(0.5) yarım saniye bekler.

  • time.sleep_ms(ms)ms milisaniye duraklat. Argüman bir tamsayı olmalıdır.

  • time.sleep_us(us)us mikrosaniye duraklat.

import time

print("now")
time.sleep_ms(500)
print("half a second later")

Tipik “biraz bekle” ihtiyaçları için time.sleep_ms() kullanın ve yalnızca zamanlamanın sıkı olması gerektiğinde time.sleep_us() kullanın. Sade time.sleep() de gayet iyidir, ancak tamsayı argümanlı varyantlar kayan noktalı sayı dönüşümünden kaçınır ve kısa aralıklar için daha doğal okunur.

Uyku, engelleyici bir çağrıdır. Betik uyurken başka hiçbir şey yapmaz – bir pini okumaz, bir UART’a hizmet vermez, bir LED’i güncellemez. Engelleme istediğiniz şey olduğunda sleep‘e başvurun; olmadığında ise aşağıdaki engellemeyen deseni kullanın.

3.2.2. Saati okumak

Bir kod parçasının ne kadar sürdüğünü ölçmek için, öncesinde ve sonrasında saati okuyun:

import time

start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")

Bu, çoğu zaman işe yarar. Tik sayacı, büyük ama sonlu bir tik sayısından sonra başa döner (sıfıra geri sarar) ve bu sarmanın ötesinde yapılan saf çıkarma, son derece yanlış bir negatif veya pozitif sayı üretir.

0'dan MAX'a uzanan, MAX'a yakın bir başlangıç tiki ve 0'a yakın bir bitiş tiki olan bir sayı doğrusu; kesik çizgili bir başa-dönme oku, MAX'tan sonra sayacın 0'a döndüğünü gösterir.

Tik sayacı tamsayı sınırına ulaştığında sıfıra geri döner. Bu sarmanın ötesinde yapılan sade bir çıkarma yanlıştır.

3.2.3. ticks_diff

Sarma boyunca bile, geçen tikleri doğru almak için time.ticks_diff() kullanın:

import time

start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")

Argüman sırası ticks_diff(later, earlier) şeklindedir – ifade “later, earlier‘dan ne kadar sonradır” diye okunur. Sonuç işaretli bir tamsayıdır; pozitif later‘ın gerçekten daha sonra olduğu, negatif ise geçmişte olduğu anlamına gelir. İşlev sarmayı dahili olarak ele alır.

Tüyo

time.ticks_ms() / time.ticks_us() işlevlerini her zaman time.ticks_diff() ile birlikte kullanın. Ham çıkarma çoğu zaman doğrudur; yanlış olduğu zaman ise bir betik uzun süredir çalışıyorken ortaya çıkar – ki bu genellikle bir zamanlama aksaklığının hatalarını ayıklamak için en kötü zamandır.

3.2.4. Engellemeyen zamanlama

Bir mikrodenetleyici betiğinin genellikle “aynı anda” yapması gereken birden fazla şey vardır: bir düğmeyi okumak, bir LED’i yakıp söndürmek, bir sensörü yoklamak, bir UART’a hizmet vermek. sleep bunun için iyi değildir – bir sleep çalışırken diğer görevler durmuştur.

Standart desen, her görev için bir son teslim süresi (deadline) tutmak ve her döngüde son teslim süresinin geçip geçmediğini kontrol etmektir. Harekete geçme kararı sleep üzerine değil, her zaman time.ticks_diff() üzerine kurulur:

import time

next_blink = time.ticks_ms()
next_poll  = time.ticks_ms()
state = False

while True:
    now = time.ticks_ms()

    if time.ticks_diff(now, next_blink) >= 0:
        state = not state
        # update LED here
        next_blink = time.ticks_add(next_blink, 500)

    if time.ticks_diff(now, next_poll) >= 0:
        # read sensor here
        next_poll = time.ticks_add(next_poll, 100)

LED her 500 ms’de bir değişir, sensör her 100 ms’de bir yoklanır ve hiçbir görev diğerini engellemez. time.ticks_add() bir son teslim süresini, sarmaya takılmadan bilinen bir artış kadar ilerletir.

Bu şekil – tek bir döngü, birkaç zamanlanmış görev, gövdede sleep olmadan – donanım kodunun gittiği her yerde ortaya çıkar: anahtarların yazılımsal seğirme giderme işlemi (debouncing), motor sıralaması, UART okuma zaman aşımları. Aynı üç işlev (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) her durumu kapsar.