3.2. Temporização

O módulo time agrupa funções para dormir (pausar o script por uma duração conhecida) e para medir quanto tempo algo leva. Em um microcontrolador, isso não são recursos opcionais; é como o script ritma as interações com o mundo externo – por quanto tempo manter um pino em nível alto, quanto esperar entre amostras, quanto tempo se passou desde que um botão foi pressionado pela última vez.

3.2.1. Dormindo

Três funções de dormir bloqueiam o script pela duração solicitada:

  • time.sleep(s) – pausa por s segundos. Aceita um float, então time.sleep(0.5) espera meio segundo.

  • time.sleep_ms(ms) – pausa por ms milissegundos. O argumento deve ser um inteiro.

  • time.sleep_us(us) – pausa por us microssegundos.

import time

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

Use time.sleep_ms() para as necessidades típicas de “esperar um pouco” e time.sleep_us() apenas quando a temporização precisar ser precisa. O simples time.sleep() também serve, mas as variantes com argumento inteiro evitam a conversão de ponto flutuante e se leem de forma mais natural para intervalos curtos.

Dormir é uma chamada bloqueante. Enquanto o script está dormindo, ele não faz mais nada – não lê um pino, não atende uma UART, não atualiza um LED. Recorra a sleep quando bloquear for o que você deseja; use o padrão não bloqueante abaixo quando não for.

3.2.2. Lendo o relógio

Para medir quanto tempo um trecho de código leva, leia o relógio antes e depois:

import time

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

Isso funciona na maioria das vezes. O contador de ticks transborda (volta a zero) após um número grande, porém finito, de ticks, e uma subtração ingênua através desse transbordo produz um número negativo ou positivo absurdamente errado.

Reta numérica de 0 a MAX com um tick inicial próximo de MAX e um tick final próximo de 0; uma seta tracejada de retorno (wrap-around) mostra que, após MAX, o contador retorna a 0.

O contador de ticks volta a zero quando atinge o limite do inteiro. Uma subtração simples através desse transbordo está errada.

3.2.3. ticks_diff

Para obter os ticks decorridos corretamente, mesmo através de um transbordo, use time.ticks_diff():

import time

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

A ordem dos argumentos é ticks_diff(later, earlier) – a expressão se lê “quão depois later está de earlier“. O resultado é um inteiro com sinal; positivo significa que later é de fato posterior, negativo significa que está no passado. A função trata o transbordo internamente.

Dica

Sempre combine time.ticks_ms() / time.ticks_us() com time.ticks_diff(). A subtração crua está correta na maioria das vezes; a hora em que ela erra é quando um script está em execução há muito tempo – normalmente o pior momento para depurar uma falha de temporização.

3.2.4. Temporização não bloqueante

Um script de microcontrolador normalmente tem mais de uma coisa para fazer “ao mesmo tempo”: ler um botão, piscar um LED, consultar um sensor, atender uma UART. sleep não serve para isso – enquanto um sleep está em execução, as outras tarefas ficam paradas.

O padrão usual é manter um prazo (deadline) por tarefa e verificar a cada laço se o prazo já passou. A decisão de agir é construída sobre time.ticks_diff(), nunca sobre sleep:

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)

O LED alterna a cada 500 ms, o sensor é consultado a cada 100 ms, e nenhuma das tarefas bloqueia a outra. time.ticks_add() avança um prazo por um incremento conhecido sem cair na armadilha do transbordo.

Esse formato – um único laço, várias tarefas temporizadas, nenhum sleep no corpo – aparece em todo lugar onde código de hardware existe: debounce de chaves por software, sequenciamento de motores, timeouts de leitura de UART. As mesmas três funções (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) cobrem todos os casos.