Timestamps Unix em sistemas embarcados, APIs e bancos de dados
Projete timestamps de sensores com RTC, NTP, relógios monotônicos, JSON e SQL, incluindo sincronização no ESP32.
Uma medição útil combina valor, referência temporal e incerteza. Unix facilita a interoperabilidade sem garantir exatidão nem ordem. Inspecione registros com Conversor Unix Timestamp / Epoch e consulte os fundamentos em Entenda os timestamps Unix e o tempo Epoch.
RTC e relógio do sistema
Um RTC mantém calendário ou contador enquanto a CPU dorme, frequentemente com alimentação de reserva. Ele não está necessariamente em UTC nem sincronizado. O relógio do sistema relaciona a base de hardware à época. Após perda de alimentação, valide o RTC: sua data padrão não é uma medição.
STM32, ESP32 e Linux embarcado
No STM32, subsegundos, domínio de reserva e recursos RTC variam entre famílias; consulte o manual e ST AN4759. Não existe um registro Unix universal. ESP-IDF combina temporizadores RTC e de alta resolução conforme a configuração. Linux oferece CLOCK_REALTIME e relógios monotônicos. Verifique libc e ABI além da largura da CPU.
NTP e SNTP
NTP estima deslocamento e atraso de rede; SNTP simplifica o cliente. A assimetria dos pacotes continua gerando erro. A época e as eras de NTP não são segundos Unix: deixe a tradução para a pilha. Registre estado, idade e incerteza da sincronização. Um salto altera a hora imediatamente; uma correção gradual muda temporariamente a velocidade do relógio.
Relógio civil e relógio monotônico
O relógio civil informa a data UTC e pode saltar após correções. O monotônico mede durações a partir de uma origem arbitrária, não uma data UTC; pode reiniciar na inicialização e seu comportamento em suspensão depende do relógio escolhido. Use-o para prazos e tentativas, adicionando uma referência UTC para correlacionar dispositivos.
Horodatagem de sensores
Capture o tempo perto da amostra ADC ou interrupção que define a medição. O envio inclui filas, rádio e retransmissões; preserve separadamente a recepção do servidor. Para blocos, registre origem, período e sequência considerando a deriva. O guia de amostragem complementa o projeto.
Eventos e telemetria
Inclua identificação do dispositivo, inicialização e sequência. Uma correção para trás pode repetir UTC sem repetir o evento. Diferencie tempo medido e reconstruído. Ordenar só por UTC não garante causalidade entre dispositivos com intervalos de incerteza sobrepostos.
Unidade e orçamento de erro
| Unidade do timestamp | 1 s | 1700000000 s |
|---|---|---|
| Segundos (s) | 1 | 1700000000 |
| Milissegundos (ms) | 1000 | 1700000000000 |
| Microssegundos (µs) | 1000000 | 1700000000000000 |
| Nanossegundos (ns) | 1000000000 | 1700000000000000000 |
Segundos atendem agendamentos grosseiros, milissegundos muitas telemetrias, microssegundos aquisições adequadas e nanossegundos hardware apropriado. Resolução, repetibilidade e exatidão são diferentes. Um erro livre de 20 ppm acumula aproximadamente 1,728 s em 24 horas nominais; temperatura e envelhecimento podem alterá-lo.
APIs REST e JSON
{
"timestamp_ns": "1700000000123456789",
"captured_at": "2023-11-14T22:13:20.123456789Z",
"time_quality": "synced",
"uncertainty_ms": 20,
"boot_id": "device-session-42",
"sequence": 17
}
Documente época, unidade, sinal e faixa. Use strings decimais para valores grandes se os clientes usam binary64. JSON.stringify não aceita BigInt diretamente. timestamp_ns explicita a unidade. Tempo desconhecido deve ser null com qualidade, não uma data fictícia próxima de 1970.
ISO 8601 e RFC 3339
Inclua Z ou deslocamento numérico e precisão fracionária documentada. 2023-11-14T22:13:20Z e 2023-11-14T23:13:20+01:00 representam o mesmo instante. Uma hora sem sufixo não determina UTC. Um deslocamento não preserva as regras futuras de Europe/Paris.
Bancos SQL
CREATE TABLE sensor_measurement (
device_id text NOT NULL,
boot_id text NOT NULL,
sequence bigint NOT NULL,
captured_at timestamptz,
monotonic_us bigint NOT NULL,
time_quality text NOT NULL,
temperature_c double precision NOT NULL,
PRIMARY KEY (device_id, boot_id, sequence)
);
INSERT INTO sensor_measurement VALUES ('sensor-1', 'boot-42', 17,
TIMESTAMPTZ '2023-11-14T22:13:20.123456Z', 9812370, 'synced', 23.625);
O exemplo usa PostgreSQL. timestamptz armazena um instante e o apresenta no fuso da sessão, sem manter o identificador IANA original. Guarde-o separadamente se necessário. A precisão é de microssegundos; nanossegundos exatos exigem outro campo inteiro ou decimal. Outros bancos têm regras próprias. Índice temporal e identidade dispositivo/inicialização/sequência cumprem funções distintas.
UTC e agendamento local
Armazene eventos em UTC. Uma regra diária às 08:00 em Paris precisa de hora local e fuso IANA, pois o UTC muda com o horário de verão. Defina o comportamento quando uma hora é pulada ou repetida. Acrescentar 86400 segundos Unix não garante a mesma hora local no dia seguinte.
Limites de time_t
Não deduza time_t de sizeof(void*). Um campo de segundos com sinal de 32 bits chega a 2038 mesmo com partes de 64 bits. ESP-IDF usa time_t com sinal de 64 bits desde v5.0; firmware e protocolos antigos podem permanecer limitados. Revise printf, colunas SQL, carregadores de inicialização, drivers RTC e migrações OTA.
Exemplo ESP32: sensor e sincronização NTP
Este código ESP-IDF 5.x/6.x é chamado uma vez após inicializar esp-netif e conectar Wi-Fi ou Ethernet. O driver da placa fornece uma temperatura finita a log_sensor. A espera inicial limita-se a 15 segundos e cada aquisição gera um registro JSON.
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "esp_netif_sntp.h"
#include "esp_timer.h"
#include "esp_random.h"
static bool clock_synced;
static int64_t last_sync_us;
static uint32_t boot_id;
static uint64_t sequence;
void ntp_after_network_ready(void) {
boot_id = esp_random();
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
esp_netif_sntp_init(&config);
clock_synced = esp_netif_sntp_sync_wait(pdMS_TO_TICKS(15000)) == ESP_OK;
if (clock_synced) last_sync_us = esp_timer_get_time();
}
void log_sensor(double temperature_c) {
int64_t monotonic_us = esp_timer_get_time();
struct timeval tv;
bool valid = clock_synced && monotonic_us - last_sync_us < INT64_C(3600000000)
&& gettimeofday(&tv, NULL) == 0;
printf("{\"boot_id\":\"%08" PRIx32 "\",\"sequence\":%" PRIu64
",\"monotonic_us\":\"%" PRId64 "\",\"timestamp_us\":",
boot_id, sequence++, monotonic_us);
if (valid) {
int64_t utc_us = (int64_t)tv.tv_sec * INT64_C(1000000) + tv.tv_usec;
printf("\"%" PRId64 "\"", utc_us);
} else printf("null");
printf(",\"time_quality\":\"%s\",\"temperature_c\":%.3f}\n",
valid ? "synced" : "unsynced", temperature_c);
}
timestamp_us e monotonic_us são strings decimais. Sem sincronização, UTC é null e a ordem permanece disponível. A janela de uma hora é uma política ilustrativa, não uma garantia de exatidão. O exemplo não renova a confiança após sincronizações automáticas: em produção atualize last_sync_us por notificação, proteja estado compartilhado e trate reconexões e incerteza. O identificador aleatório de inicialização de 32 bits é ilustrativo; use contador persistente ou identificador robusto quando colisões forem críticas.
Reinicialização, deriva e perda de sincronização
Reiniciar cria uma nova linha monotônica. Preserve sua identidade e não una contadores de inicializações diferentes sem validação. Durante desconexões, aumente a incerteza conforme o oscilador e a última referência confiável. Um RTC com reserva ajuda, mas precisa de qualidade explícita. Torne grandes correções observáveis sem reescrever silenciosamente o histórico.
Boas práticas e testes
- Definir época, unidade e sinal em cada interface.
- UTC para eventos e relógio monotônico para prazos.
- Preservar sequência, identidade de inicialização e qualidade temporal.
- Testar início sem rede, bateria RTC esgotada, correções para trás, mudanças de horário e limites inteiros.
- Atualizar dados de fuso usados em agendamentos futuros.
Perguntas técnicas
NTP garante exatidão de microssegundos?
Não. Assimetria de rede, escalonamento e latência de aquisição permanecem. Meça toda a cadeia e indique a incerteza adequada.
Um contador monotônico basta para obter UTC?
É necessária uma correspondência com UTC, modelo de deriva, idade e incerteza. A correspondência não atravessa automaticamente uma reinicialização.
Devo armazenar tudo em hora local?
Guarde os instantes em UTC e um fuso separado para regras civis ou contexto original. Converta ao apresentar.
Ferramentas e referências
Conversor Unix Timestamp / Epoch · Entenda os timestamps Unix e o tempo Epoch · Tolerância de osciladores.
- IETF · RFC 3339
- IETF · RFC 5905 (NTP)
- IETF · RFC 8259 (JSON)
- Python · PEP 418
- Espressif · ESP-IDF
- STMicroelectronics · AN4759
- PostgreSQL · SQL
Ferramentas e guias relacionados
Calculadora de capacitores de carga de cristal · Ler o guia completo de projeto