time — funções relacionadas com o tempo

O módulo time fornece funções para obter a hora e data atuais, medir intervalos de tempo e efetuar atrasos.

Época de Tempo: As OpenMV Cams baseadas em Alif e i.MX RT usam a época POSIX de 1970-01-01 00:00:00 UTC. As OpenMV Cams baseadas em STM32 usam uma época de 2000-01-01 00:00:00 UTC. O ano da época pode ser determinado em tempo de execução com gmtime(0)[0].

Manutenção da data/hora do calendário real: Isto requer um Relógio de Tempo Real (RTC). Na OpenMV Cam, a hora do sistema é fornecida pelo objeto machine.RTC. A hora do calendário atual pode ser definida com machine.RTC().datetime(tuple) e é mantida por um dos seguintes meios:

  • Uma bateria de reserva (componente opcional em algumas OpenMV Cams).

  • Um protocolo de tempo em rede como ntptime (requer uma ligação de rede).

  • Definindo-a manualmente em cada arranque. O RTC é normalmente mantido entre soft resets, mas perde-se em caso de corte de energia, a não ser que esteja instalada uma bateria de reserva.

Se a hora do calendário não for mantida, as funções abaixo que referenciam a hora absoluta atual não se comportarão como esperado.

Funções

time.gmtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]
time.localtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]

Converte o tempo secs expresso em segundos desde a Época (ver acima) num tuplo de 8 elementos que contém: (year, month, mday, hour, minute, second, weekday, yearday) Se secs não for fornecido ou for None, é utilizada a hora atual do RTC.

A função gmtime() devolve um tuplo de data-hora em UTC, e localtime() devolve um tuplo de data-hora na hora local.

O formato das entradas no tuplo de 8 elementos é:

  • year inclui o século (por exemplo 2014).

  • month é 1-12

  • mday é 1-31

  • hour é 0-23

  • minute é 0-59

  • second é 0-59

  • weekday é 0-6 para Seg-Dom

  • yearday é 1-366

time.mktime(date_time_tuple: Tuple[int, int, int, int, int, int, int, int]) int

Esta é a função inversa de localtime. O seu argumento é um tuplo completo de 8 elementos que expressa um tempo conforme localtime. Devolve um inteiro que é o número de segundos desde a época de tempo.

time.sleep(seconds: float) None

Aguarda o número de segundos indicado. seconds pode ser um número de vírgula flutuante, para aguardar uma fração de segundos. Para atrasos de maior precisão ou apenas em números inteiros, use as funções sleep_ms() e sleep_us().

Chamar sleep(), incluindo sleep(0), garante a execução das funções de callback pendentes.

time.sleep_ms(ms: int) None

Atrasa pelo número de milissegundos indicado; deve ser positivo ou 0.

Esta função atrasará pelo menos o número de milissegundos indicado, mas pode demorar mais se houver outro processamento a efetuar, como handlers de interrupção ou outras threads. Passar 0 para ms ainda permite que esse outro processamento ocorra. Use sleep_us() para atrasos mais precisos.

Chamar sleep_ms(), incluindo sleep_ms(0), garante a execução das funções de callback pendentes.

time.sleep_us(us: int) None

Atrasa pelo número de microssegundos indicado; deve ser positivo ou 0.

Esta função tenta fornecer um atraso preciso de pelo menos us microssegundos, mas pode demorar mais se o sistema tiver outro processamento de maior prioridade a executar.

time.ticks_ms() int

Devolve um contador de milissegundos crescente com um ponto de referência arbitrário, que volta ao início após um determinado valor.

O valor de retorno não é exposto explicitamente, mas iremos referir-nos a ele como TICKS_MAX para simplificar a discussão. O período dos valores é TICKS_PERIOD = TICKS_MAX + 1. TICKS_PERIOD é garantidamente uma potência de dois, mas pode diferir de port para port. O mesmo valor de período é utilizado para todas as funções ticks_ms(), ticks_us(), ticks_cpu() (por simplicidade). Assim, estas funções devolvem um valor no intervalo [0 .. TICKS_MAX], inclusivo, com TICKS_PERIOD valores no total. Note que apenas são utilizados valores não negativos. Na maioria das vezes, os valores devolvidos por estas funções devem ser tratados como opacos. As únicas operações disponíveis para eles são as funções ticks_diff() e ticks_add() descritas abaixo.

Nota: Efetuar operações matemáticas padrão (+, -) ou operadores relacionais (<, <=, >, >=) diretamente sobre estes valores conduzirá a resultados inválidos. Efetuar operações matemáticas e depois passar os seus resultados como argumentos a ticks_diff() ou ticks_add() também conduzirá a resultados inválidos dessas funções.

time.ticks_us() int

Tal como ticks_ms() acima, mas em microssegundos.

time.ticks_cpu() int

Semelhante a ticks_ms() e ticks_us(), mas com a maior resolução possível no sistema. Normalmente são ciclos de CPU, daí o nome da função. Mas não tem de ser um relógio de CPU; pode ser usada outra fonte de temporização disponível no sistema (por ex. um temporizador de alta resolução). A unidade de temporização exata (resolução) desta função não é especificada ao nível do módulo time, mas a documentação de um port específico pode fornecer informações mais detalhadas. Esta função destina-se a benchmarking muito fino ou ciclos de tempo real muito apertados. Evite utilizá-la em código portável. Está disponível em todas as OpenMV Cams.

time.ticks_add(ticks: int, delta: int) int

Desloca um valor de ticks por um determinado número, que pode ser positivo ou negativo. Dado um valor ticks, esta função permite calcular o valor de ticks delta ticks antes ou depois dele, seguindo a definição aritmética modular dos valores de ticks (ver ticks_ms() acima). O parâmetro ticks deve ser um resultado direto de uma chamada às funções ticks_ms(), ticks_us() ou ticks_cpu() (ou de uma chamada anterior a ticks_add()). No entanto, delta pode ser qualquer número inteiro ou expressão numérica. ticks_add() é útil para calcular prazos para eventos/tarefas. (Nota: deve usar a função ticks_diff() para trabalhar com prazos.)

Exemplos:

# Find out what ticks value there was 100ms ago
print(ticks_add(time.ticks_ms(), -100))

# Calculate deadline for operation and test for it
deadline = ticks_add(time.ticks_ms(), 200)
while ticks_diff(deadline, time.ticks_ms()) > 0:
    do_a_little_of_something()

# Find out TICKS_MAX used by this port
print(ticks_add(0, -1))
time.ticks_diff(ticks1: int, ticks2: int) int

Mede a diferença de ticks entre valores devolvidos pelas funções ticks_ms(), ticks_us() ou ticks_cpu(), como um valor com sinal que pode sofrer retorno.

A ordem dos argumentos é a mesma que para o operador de subtração: ticks_diff(ticks1, ticks2) tem o mesmo significado que ticks1 - ticks2. No entanto, os valores devolvidos pelas funções ticks_ms(), etc. podem sofrer retorno, pelo que usar diretamente a subtração sobre eles produzirá um resultado incorreto. É por isso que ticks_diff() é necessária: implementa aritmética modular (ou mais especificamente, em anel) para produzir resultados corretos mesmo para valores com retorno (desde que não estejam demasiado distantes entre si, ver abaixo). A função devolve um valor com sinal no intervalo [-TICKS_PERIOD/2 .. TICKS_PERIOD/2-1] (esta é a definição típica de intervalo para inteiros binários com sinal em complemento para dois). Se o resultado for negativo, significa que ticks1 ocorreu antes no tempo do que ticks2. Caso contrário, significa que ticks1 ocorreu depois de ticks2. Isto só é válido se ticks1 e ticks2 estiverem afastados entre si por no máximo TICKS_PERIOD/2-1 ticks. Se tal não se verificar, será devolvido um resultado incorreto. Especificamente, se dois valores de ticks estiverem afastados por TICKS_PERIOD/2-1 ticks, esse valor será devolvido pela função. No entanto, se tiver decorrido TICKS_PERIOD/2 de ticks de tempo real entre eles, a função devolverá -TICKS_PERIOD/2, ou seja, o valor do resultado sofrerá retorno para o intervalo negativo de valores possíveis.

Justificação informal das restrições acima: Suponha que está fechado numa sala sem meios de monitorizar a passagem do tempo exceto um relógio padrão de 12 posições. Se olhar para o mostrador agora e não voltar a olhar durante 13 horas (por ex. se adormecer por muito tempo), quando finalmente olhar de novo pode parecer que passou apenas 1 hora. Para evitar este erro, basta olhar para o relógio regularmente. A sua aplicação deve fazer o mesmo. A metáfora do «sono demasiado longo» mapeia-se diretamente para o comportamento da aplicação: não permita que a sua aplicação execute uma única tarefa por demasiado tempo. Execute as tarefas em passos e faça a gestão do tempo entre eles.

ticks_diff() foi concebida para acomodar vários padrões de utilização, entre eles:

  • Sondagem com timeout. Neste caso, a ordem dos eventos é conhecida e lidará apenas com resultados positivos de ticks_diff()

    # Wait for GPIO pin to be asserted, but at most 500us
    start = time.ticks_us()
    while pin.value() == 0:
        if time.ticks_diff(time.ticks_us(), start) > 500:
            raise TimeoutError
    
  • Agendamento de eventos. Neste caso, o resultado de ticks_diff() pode ser negativo se um evento estiver em atraso:

    # This code snippet is not optimized
    now = time.ticks_ms()
    scheduled_time = task.scheduled_time()
    if ticks_diff(scheduled_time, now) > 0:
        print("Too early, let's nap")
        sleep_ms(ticks_diff(scheduled_time, now))
        task.run()
    elif ticks_diff(scheduled_time, now) == 0:
        print("Right at time!")
        task.run()
    elif ticks_diff(scheduled_time, now) < 0:
        print("Oops, running late, tell task to run faster!")
        task.run(run_faster=true)
    

Nota: Não passe valores de time() a ticks_diff(); deve usar operações matemáticas normais sobre eles. Mas note que time() pode (e irá) também sofrer overflow. Isto é conhecido como https://en.wikipedia.org/wiki/Year_2038_problem .

time.time() int

Devolve o número de segundos, como inteiro, desde a Época, assumindo que o RTC subjacente está definido e mantido conforme descrito acima. Se um RTC não estiver definido, esta função devolve o número de segundos desde um ponto de referência temporal específico do port (para placas embebidas sem RTC com bateria de reserva, normalmente desde o arranque ou reset). Se pretender desenvolver uma aplicação MicroPython portável, não deve depender desta função para fornecer precisão superior a um segundo. Se necessitar de maior precisão em timestamps absolutos, use time_ns(). Se os tempos relativos forem aceitáveis, use as funções ticks_ms() e ticks_us(). Se necessitar de hora do calendário, gmtime() ou localtime() sem argumento é uma melhor escolha.

Diferença para o CPython

No CPython, esta função devolve o número de segundos desde a época Unix (1970-01-01 00:00 UTC) como valor de vírgula flutuante, normalmente com precisão de microssegundos. Na OpenMV Cam, devolve um inteiro com precisão de um segundo – o hardware não consegue representar simultaneamente um grande intervalo de tempo e precisão sub-segundo num float – e a época difere por placa (ver Época de Tempo acima). Sem um RTC com bateria de reserva que tenha sido definido, conta segundos desde o arranque/reset.

time.time_ns() int

Semelhante a time(), mas devolve nanossegundos desde a Época, como inteiro (normalmente um inteiro grande, pelo que será alocado no heap).

Construtores

class time.clock

Devolve um objeto clock.

Métodos

tick() None

Inicia o rastreio do tempo decorrido.

fps() float

Para o rastreio do tempo decorrido e devolve os FPS (fotogramas por segundo) atuais.

Chame sempre tick antes de chamar esta função.

avg() float

Para o rastreio do tempo decorrido e devolve o tempo médio decorrido atual em milissegundos.

Chame sempre tick antes de chamar esta função.

reset() None

Reinicia o objeto clock.