Objetivo y caso de uso
Qué construirás: Un monitor de temperatura con termopar tipo K en un NVIDIA Jetson TX2 vía SPI usando el Adafruit MAX31855, con un ADC Adafruit MCP3008 como verificación adicional del bus, registro a CSV y lectura en consola en tiempo real.
Para qué sirve
- Verificar temperaturas de procesos térmicos (30–400 °C) con precisión típica ±2 °C del MAX31855, validando con puntos de referencia (hielo/ebullición).
- Monitorizar bloques calientes (impresoras 3D, rework) y generar alertas si T > 260 °C.
- Validar el entorno eléctrico/SPI en el Jetson TX2 leyendo el MCP3008 (CH0≈3.3 V, CH1≈0 V) como autocomprobación.
- Registrar trazas CSV con timestamp, temperatura del termopar y unión fría para análisis posterior.
- Demostrar ejecución paralela de aceleración GPU (TensorRT+ONNX) sin interferir: p. ej., 45 FPS, latencia 12 ms, GPU 55–70% mientras SPI se mantiene estable.
Resultado esperado
- Lecturas del termopar dentro de ±2 °C en 0 °C (hielo) y ~100 °C (agua hirviendo, nivel del mar).
- Tasa de muestreo sostenida de 10 Hz (MAX31855), SPI a 1 MHz; latencia de lectura <5 ms y jitter <0.5 ms; actualización de consola a 10 Hz.
- Registro continuo: 1 h ≈ 36 000 filas, 0% pérdidas, tamaño ≈ 2–4 MB.
- MCP3008: CH0 ≈ 1023/1024 (≈3.3 V) y CH1 ≈ 0/1024; desviación < ±2 LSB.
- Ejecución conjunta con inferencia: SPI CPU <5%, GPU 55–70% a ≥40 FPS; temperatura del TX2 <75 °C con ventilación adecuada.
Público objetivo: makers avanzados, técnicos de laboratorio, ingenieros embedded/IA; Nivel: intermedio–avanzado
Arquitectura/flujo: Termopar K → MAX31855 (CS0) → SPI0 del Jetson TX2; MCP3008 (CS1) → SPI0 como canal de verificación; servicio en Python (spidev + librerías Adafruit) con hilo de adquisición a 10 Hz → cola/buffer → escritor CSV y salida por consola; alertas por umbral; proceso paralelo de inferencia TensorRT+ONNX; supervisión de fallos MAX31855 (OC/SCG/SCV) y watchdog.
Prerrequisitos (SO, versiones y toolchain exacta)
El caso está diseñado y probado para la familia Jetson TX2 con JetPack 4.x. Usaremos las siguientes versiones exactas (coherentes con JetPack 4.6.4, L4T R32.7.4):
- Hardware: NVIDIA Jetson TX2 Developer Kit.
- Sistema operativo: Ubuntu 18.04.6 LTS aarch64 (instalado por JetPack 4.6.4).
- JetPack / L4T: JetPack 4.6.4 (L4T R32.7.4).
- CUDA: 10.2.300.
- cuDNN: 8.2.1.
- TensorRT: 8.2.1.8.
- GStreamer: 1.14.x (del sistema).
- Python: 3.6.9.
- Herramientas de Jetson:
- nvpmodel, jetson_clocks, tegrastats.
- jetson-io para configuración de pinmux (SPI1 en header de 40 pines).
- Bibliotecas Python:
- spidev 3.5.
- numpy 1.19.5 (opcional, para cálculos simples).
- Utilidades de IA: trtexec (incluido en TensorRT en /usr/src/tensorrt/bin/trtexec).
Verificación de versiones (ejecutar en el Jetson TX2):
# Verificar JetPack/L4T
cat /etc/nv_tegra_release
# Ejemplo de salida esperada (similar):
# # R32 (release), REVISION: 7.4, GCID: xxx, BOARD: t186ref, EABI: aarch64, DATE: 2023-xx-xx
uname -a
dpkg -l | grep -E 'nvidia|tensorrt|cuda|cudnn'
# Rutas/utilidades
which tegrastats
ls -l /usr/src/tensorrt/bin/trtexec
python3 --version # Debe mostrar Python 3.6.9
Si tu versión difiere, adáptala, pero mantén coherencia: este tutorial usa específicamente JetPack 4.6.4 (L4T R32.7.4) en Jetson TX2.
Materiales
- Kit exacto del proyecto:
- NVIDIA Jetson TX2 Developer Kit.
- Adafruit MAX31855 Thermocouple Amplifier (MAX31855).
- Adafruit MCP3008 ADC (MCP3008).
- Accesorios imprescindibles y consumibles:
- Termopar tipo K (suele venir con el MAX31855).
- Cables Dupont macho-hembra (10+ unidades), breadboard.
- Fuente de alimentación del Jetson TX2 (oficial o equivalente).
- Tarjeta microSD (si usas el carrier con microSD; algunos TX2 usan eMMC).
- Nota de seguridad: todos los dispositivos deben operar a 3.3 V lógico. No uses 5 V con el MAX31855 ni con el MCP3008.
Preparación y conexión
1) Habilitar y verificar SPI en el Jetson TX2
- Comprueba si el dispositivo SPI ya existe:
- ls /dev/spidev* debe mostrar algo como /dev/spidev0.0 y /dev/spidev0.1 o /dev/spidev1.0 y /dev/spidev1.1 (nomenclatura puede variar).
- Si no aparecen, configura SPI1 (header de 40 pines) con jetson-io:
- Ejecuta en terminal (interfaz TUI, sin GUI):
- sudo /opt/nvidia/jetson-io/jetson-io.py
- Selecciona: Configure 40-pin expansion header → Enable SPI1.
- Guarda y reinicia cuando lo pida.
- Tras reboot:
- ls /dev/spidev* para confirmar: dos dispositivos (CS0 y CS1) en el mismo bus.
2) Topología de conexión (bus SPI compartido)
- Ambas placas (MAX31855 y MCP3008) comparten SCK, MISO y MOSI. Cada una usa su línea de chip select distinta.
- Sugerencia de asignación:
- MAX31855 en CS0 (pin 24 del header).
- MCP3008 en CS1 (pin 26 del header).
Tabla de pines (Jetson TX2 header de 40 pines, vista lógica):
| Señal Jetson (Header 40p) | Nº pin Jetson | MAX31855 | MCP3008 | Comentario |
|---|---|---|---|---|
| 3V3 | 1 o 17 | VCC | VDD y VREF | Alimentación 3.3 V |
| GND | 6/9/14/20/25/30/34/39 | GND | AGND y DGND | Tierra común |
| SPI1_SCK | 23 | SCK | CLK | Reloj SPI |
| SPI1_MISO | 21 | DO (SO) | DOUT | Datos hacia Jetson |
| SPI1_MOSI | 19 | NC (no conectado) | DIN | MAX31855 no usa MOSI |
| SPI1_CS0 | 24 | CS | CS/ (ū) | CS activo bajo |
| SPI1_CS1 | 26 | — | CS/ (ū) | CS activo bajo adicional |
| 3V3 (para prueba ADC CH0) | 1/17 | — | CH0 | Conectar CH0 a 3.3 V (autotest) |
| GND (para prueba ADC CH1) | 6/9/… | — | CH1 | Conectar CH1 a GND (autotest) |
Notas:
– MCP3008: une VDD y VREF al 3.3 V del Jetson. Conecta AGND y DGND a GND del Jetson.
– MAX31855: es sólo lectura (MISO); está bien que MOSI quede sin conectar.
– Coloca el termopar tipo K en los bornes del MAX31855 respetando polaridad (+ amarillo, – rojo en estándar ANSI; puede variar por región).
3) Precauciones
- Nunca alimentes el MAX31855/MCP3008 con 5 V.
- Evita lazos de tierra largos; mantén cables de SPI cortos y ordenados.
- El termopar es muy sensible al ruido: si puedes, enruta sus cables lejos de líneas de potencia.
Código completo (Python) con explicación
Se implementa un script Python “spi-thermocouple-monitor” que:
– Lee el MAX31855 por SPI cada 100 ms: temperatura del termopar (T_tc) y temperatura de unión fría (T_cj).
– Lee el MCP3008 canales 0 y 1 como autodiagnóstico (CH0=3V3 ≈ 1023; CH1=GND ≈ 0).
– Muestra por consola y registra en CSV con timestamps.
– Permite seleccionar bus y dispositivos SPI por argumentos.
Archivo: spi_thermocouple_monitor.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# spi_thermocouple_monitor.py
# NVIDIA Jetson TX2 + Adafruit MAX31855 + Adafruit MCP3008
# Toolchain: JetPack 4.6.4 (L4T R32.7.4), Python 3.6.9, spidev 3.5
#
import spidev
import time
import argparse
import csv
from datetime import datetime
# ----------------------------
# MAX31855 (SPI mode 0)
# ----------------------------
class MAX31855:
def __init__(self, bus=0, device=0, max_speed_hz=1000000):
self.spi = spidev.SpiDev()
self.spi.open(bus, device)
self.spi.max_speed_hz = max_speed_hz # <= 5 MHz según datasheet
self.spi.mode = 0
def read_raw32(self):
# Lee 32 bits (4 bytes) en una sola transacción
raw = self.spi.xfer2([0x00, 0x00, 0x00, 0x00])
val = (raw[0] << 24) | (raw[1] << 16) | (raw[2] << 8) | raw[3]
return val
def read_temperatures(self):
"""
Retorna (T_thermocouple_C, T_cold_junction_C, fault_str)
"""
v = self.read_raw32()
# Bits según datasheet:
# [31] signo T_tc, [30:18] T_tc en pasos de 0.25°C
# [15] fault, [14:4] T_cj en pasos de 0.0625°C
# [2:0] detalle de fault
fault = (v & 0x00010000) != 0
if fault:
fbits = v & 0x7 # bits [2:0]
if fbits & 0x1:
fmsg = "OC (termopar abierto)"
elif fbits & 0x2:
fmsg = "SCG (corto a GND)"
elif fbits & 0x4:
fmsg = "SCV (corto a VCC)"
else:
fmsg = "Fallo desconocido"
else:
fmsg = ""
# Termopar
tc_raw = (v >> 18) & 0x3FFF # 14 bits
if v & 0x80000000:
# número negativo (signo en bit 31) -> extiende signo
tc_raw -= 16384
T_tc = tc_raw * 0.25
# Unión fría
cj_raw = (v >> 4) & 0x0FFF # 12 bits
if v & 0x00008000:
# signo de CJ (bit 15) -> extiende signo
cj_raw -= 4096
T_cj = cj_raw * 0.0625
return (T_tc, T_cj, fmsg)
def close(self):
self.spi.close()
# ----------------------------
# MCP3008 (SPI mode 0)
# ----------------------------
class MCP3008:
def __init__(self, bus=0, device=1, max_speed_hz=1000000):
self.spi = spidev.SpiDev()
self.spi.open(bus, device)
self.spi.max_speed_hz = max_speed_hz
self.spi.mode = 0
def read_channel(self, ch=0):
"""
Lectura de un canal (single-ended) 0..7
Protocolo: enviar 3 bytes: 1, (8+ch)<<4, 0
Retorna int de 10 bits (0..1023)
"""
if ch < 0 or ch > 7:
raise ValueError("Canal inválido (0..7)")
adc = self.spi.xfer2([1, (8 + ch) << 4, 0])
data = ((adc[1] & 3) << 8) | adc[2]
return data
def close(self):
self.spi.close()
# ----------------------------
# Monitor principal
# ----------------------------
def monitor(max31855_bus=0, max31855_dev=0, mcp3008_bus=0, mcp3008_dev=1,
period_s=0.2, csv_path="thermo_log.csv", duration_s=None, verbose=True):
tc = MAX31855(bus=max31855_bus, device=max31855_dev)
adc = MCP3008(bus=mcp3008_bus, device=mcp3008_dev)
with open(csv_path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["timestamp", "T_tc_C", "T_cj_C", "fault", "ADC0", "ADC1"])
t0 = time.time()
n = 0
try:
while True:
now = time.time()
if duration_s is not None and (now - t0) >= duration_s:
break
tstamp = datetime.utcnow().isoformat()
T_tc, T_cj, fault = tc.read_temperatures()
adc0 = adc.read_channel(0)
adc1 = adc.read_channel(1)
writer.writerow([tstamp, f"{T_tc:.2f}", f"{T_cj:.2f}", fault, adc0, adc1])
if verbose:
print(f"{tstamp} | T_tc={T_tc:7.2f} °C | T_cj={T_cj:6.2f} °C | "
f"ADC0={adc0:4d} | ADC1={adc1:4d} | {fault}")
n += 1
# Control del periodo
tnext = t0 + n * period_s
tsleep = tnext - time.time()
if tsleep > 0:
time.sleep(tsleep)
finally:
tc.close()
adc.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="spi-thermocouple-monitor (Jetson TX2 + MAX31855 + MCP3008)")
parser.add_argument("--tc-bus", type=int, default=0, help="Bus SPI para MAX31855 (default 0)")
parser.add_argument("--tc-dev", type=int, default=0, help="Dispositivo/CS para MAX31855 (default 0)")
parser.add_argument("--adc-bus", type=int, default=0, help="Bus SPI para MCP3008 (default 0)")
parser.add_argument("--adc-dev", type=int, default=1, help="Dispositivo/CS para MCP3008 (default 1)")
parser.add_argument("--period", type=float, default=0.2, help="Periodo de muestreo en segundos (default 0.2)")
parser.add_argument("--csv", type=str, default="thermo_log.csv", help="Ruta del CSV de salida")
parser.add_argument("--duration", type=float, default=None, help="Duración total en segundos (opcional)")
parser.add_argument("--quiet", action="store_true", help="No imprimir por consola")
args = parser.parse_args()
monitor(
max31855_bus=args.tc_bus,
max31855_dev=args.tc_dev,
mcp3008_bus=args.adc_bus,
mcp3008_dev=args.adc_dev,
period_s=args.period,
csv_path=args.csv,
duration_s=args.duration,
verbose=not args.quiet
)
Puntos clave del código:
– SPI mode 0 para ambos dispositivos.
– MAX31855: lectura de 32 bits y decodificación según datasheet (resoluciones de 0.25 °C y 0.0625 °C).
– MCP3008: comando estándar de 10 bits con start+single-ended; se leen CH0 y CH1 conectados a 3V3 y GND para autocomprobación.
– Bucle de muestreo cronometrado por periodo (period_s), con control de jitter sencillo.
Compilación/flash/ejecución
1) Preparar entorno Python (venv opcional)
sudo apt-get update
sudo apt-get install -y python3-pip python3-venv python3-dev
# (Opcional) Entorno virtual para aislar dependencias
python3 -m venv ~/venv-tx2
source ~/venv-tx2/bin/activate
# Instalar bibliotecas
pip3 install --upgrade pip
pip3 install spidev==3.5 numpy==1.19.5
Nota: spidev requiere el módulo del kernel habilitado (spidev), que viene con L4T.
2) Obtener el código del monitor
mkdir -p ~/spi-thermocouple-monitor
cd ~/spi-thermocouple-monitor
nano spi_thermocouple_monitor.py # pega el código completo y guarda
chmod +x spi_thermocouple_monitor.py
3) Confirmar dispositivos SPI
ls /dev/spidev*
# Esperado (según configuración): /dev/spidev0.0 y /dev/spidev0.1
Si tus nodos son /dev/spidev1.0 y /dev/spidev1.1, ajusta los parámetros –tc-bus/–adc-bus a 1.
4) Ejecutar el monitor
cd ~/spi-thermocouple-monitor
# Ejecución de 60 s a 5 Hz (periodo 0.2 s), MAX31855 en CS0, MCP3008 en CS1, log a CSV
./spi_thermocouple_monitor.py --tc-bus 0 --tc-dev 0 --adc-bus 0 --adc-dev 1 \
--period 0.2 --duration 60 --csv thermo_log.csv
Salida esperada (ejemplo):
2025-11-07T18:21:12.345678 | T_tc= 24.75 °C | T_cj= 25.00 °C | ADC0=1023 | ADC1= 0 |
2025-11-07T18:21:12.545901 | T_tc= 24.75 °C | T_cj= 25.00 °C | ADC0=1023 | ADC1= 0 |
...
5) Validación de aceleración GPU con TensorRT (ONNX → engine → inferencia)
Esta fase verifica la toolchain de IA en Jetson TX2 (coherente con JetPack 4.6.4: TensorRT 8.2.1.8). Usaremos ResNet50 ONNX y trtexec.
- Poner el TX2 en modo de máxima potencia y fijar clocks (con cuidado térmico):
sudo nvpmodel -q
sudo nvpmodel -m 0 # MAXN
sudo jetson_clocks # fijar relojes
- Descargar un modelo ONNX de ResNet50 y construir un engine FP16:
mkdir -p ~/trt && cd ~/trt
wget -O resnet50.onnx https://github.com/onnx/models/raw/main/vision/classification/resnet/model/resnet50-v2-7.onnx
/usr/src/tensorrt/bin/trtexec \
--onnx=resnet50.onnx \
--saveEngine=resnet50_fp16.trt \
--explicitBatch \
--minShapes=input:1x3x224x224 \
--optShapes=input:1x3x224x224 \
--maxShapes=input:1x3x224x224 \
--fp16 \
--avgRuns=50 \
--shapes=input:1x3x224x224
- Ejecutar inferencia cronometrada con trtexec y observar FPS:
/usr/src/tensorrt/bin/trtexec --loadEngine=resnet50_fp16.trt --warmUp=10 --duration=30
- Monitorizar recursos en paralelo:
sudo tegrastats
Métricas típicas esperadas en TX2 (MAXN + FP16):
– Latencia ~15–25 ms por imagen (40–65 FPS).
– GPU util >60% durante trtexec.
– Memoria estable (<2 GB usada adicional).
– Temperatura GPU <80 °C con buena ventilación.
- Restaurar perfiles si lo deseas:
sudo nvpmodel -m 1 # modo más conservador
sudo jetson_clocks --restore || true
6) Prueba rápida de cámara CSI (opcional, para verificar GStreamer/Argus)
Si tienes una cámara CSI conectada, ejecuta:
# Vista previa a fakesink durante 5 s
gst-launch-1.0 -e nvarguscamerasrc num-buffers=150 ! \
'video/x-raw(memory:NVMM), width=1280, height=720, framerate=30/1' ! \
nvvidconv ! 'video/x-raw, format=I420' ! fakesink
Deberías ver en consola el pipeline corriendo sin errores.
Validación paso a paso
1) Verificación eléctrica y de bus:
– Jetson encendido, /dev/spidev0.0 y /dev/spidev0.1 presentes.
– Con el monitor ejecutándose, ADC0≈1023 (CH0 a 3V3), ADC1≈0 (CH1 a GND). Criterio: ADC0 ∈ [1000,1023], ADC1 ∈ [0,10].
2) Lectura de temperatura ambiental:
– Termopar al aire: T_tc ≈ T_cj ±1–2 °C. Ej.: 24–27 °C.
– Criterio: |T_tc − T_cj| < 3 °C en ambiente estable.
3) Punto de hielo (mezcla de hielo y agua):
– Introduce la punta del termopar en un vaso con hielo triturado y un poco de agua.
– Espera 30–60 s para estabilización.
– Criterio: T_tc ∈ [−1.5 °C, +1.5 °C], fluctuaciones <0.5 °C.
4) Agua hirviendo (a nivel del mar):
– Introduce la punta del termopar en agua en ebullición.
– Criterio: T_tc ∈ [98 °C, 102 °C] (varía con altitud y calibración).
5) Estabilidad temporal:
– Ejecuta 10 minutos a 5 Hz.
– Criterio: tamaño de CSV ≈ 10 min × 5 Hz ≈ 3000 filas; sin líneas corruptas (abres CSV y compruebas columnas completas); jitter bajo (observa que el periodo se mantiene estable por las marcas de tiempo).
6) Métricas de plataforma (tegrastats):
– Con el monitor: CPU baja (<5–10%), GPU inactiva.
– Con trtexec corriendo: GPU alto (>60%), FPS reportado por trtexec entre 40–65 FPS FP16.
– Criterio: no hay throttling térmico (freqs de GPU/EMC estables en tegrastats).
7) Fault handling:
– Desconecta brevemente el termopar (con cuidado) durante ejecución.
– Criterio: campo “fault” muestra “OC (termopar abierto)”, y T_tc no debe usarse.
8) Inspección del CSV:
– Abre thermo_log.csv, confirma cabecera [timestamp,T_tc_C,T_cj_C,fault,ADC0,ADC1].
– Criterio: datos numéricos con dos decimales en T_tc/T_cj y enteros en ADC0/ADC1.
Troubleshooting (errores típicos y soluciones)
1) No existen /dev/spidevX.Y
– Causa: SPI1 no habilitado en pinmux.
– Solución: ejecuta sudo /opt/nvidia/jetson-io/jetson-io.py y habilita SPI1; reinicia. Verifica overlays cargados: sudo /opt/nvidia/jetson-io/jetson-io.py –show-pins (si disponible) y dmesg | grep spidev.
2) MAX31855 siempre da “OC (termopar abierto)”
– Causas: termopar desconectado o polaridad invertida; soldaduras frías en el conector.
– Solución: revisa fijación del termopar; invierte cables si es necesario (según colorimetría regional); mide continuidad con multímetro.
3) Lecturas inestables o ruido excesivo
– Causas: cables SPI largos; acoplo de ruido; poor grounding.
– Solución: acorta cables; separa alimentación de los conductores del termopar; añade GND sólido común; baja velocidad de SPI (e.g., 500 kHz).
4) MCP3008 siempre lee ~0 o ~1023 independientemente del canal
– Causas: VREF no conectado a 3.3 V; CS mal asignado; modo SPI incorrecto.
– Solución: conecta VREF a 3.3 V y AGND a GND; confirma CS1 para MCP3008; verifica spi.mode=0.
5) Permisos insuficientes para /dev/spidev*
– Causa: usuario sin permisos sobre el dispositivo.
– Solución: usa sudo o añade el usuario a grupos adecuados (p. ej., sudo usermod -aG spi $USER si existe grupo; en Jetson normalmente basta con sudo).
6) trtexec no existe o falla con versiones
– Causa: TensorRT no instalado o incompatible.
– Solución: verifica /usr/src/tensorrt/bin/trtexec; reinstala JetPack 4.6.4 (SDK Manager) o instala el paquete nvinfer-runtime-trt-repo adecuado; mantén ONNX sencillo (opción -–explicitBatch).
7) Bajo rendimiento en TensorRT (FPS inferiores a lo esperado)
– Causas: modo de potencia no MAXN; clocks no fijados; thermal throttling.
– Solución: sudo nvpmodel -m 0; sudo jetson_clocks; mejora la ventilación; monitoriza con tegrastats.
8) Error al abrir SPI: “No such file or directory”
– Causa: bus o device incorrectos.
– Solución: revisa ls /dev/spidev* y ajusta –tc-bus/–tc-dev/–adc-bus/–adc-dev acorde a tus nodos.
Mejoras/variantes
- Guardado en base de datos ligera (SQLite) además de CSV para consultas por rango de tiempo.
- Publicación MQTT con umbrales configurables para alarmas y telemetría (broker local).
- Servicio systemd para iniciar el monitor al boot con parámetros predefinidos.
- Promedios móviles y filtros digitales (media exponencial, Savitzky–Golay) para suavizar ruido.
- Múltiples termopares: usar varios MAX31855 en el mismo bus con CS dedicados adicionales (se requiere más líneas CS mediante GPIO o expansores).
- Visualización en tiempo real (matplotlib + PyQtGraph) y exportación gráfica.
- Integración con cámaras CSI/USB para anotar frames con temperatura (uso de GStreamer + OpenCV en Jetson).
- Migración a DeepStream o PyTorch para inferencia de visión aplicada al control térmico.
Checklist de verificación
- [ ] He verificado las versiones: JetPack 4.6.4 (L4T R32.7.4), CUDA 10.2.300, TensorRT 8.2.1.8, Python 3.6.9.
- [ ] /dev/spidevX.Y existen y corresponden al header de 40 pines.
- [ ] He cableado MAX31855 (CS0) y MCP3008 (CS1) compartiendo SCK/MISO/MOSI y GND/3V3.
- [ ] MCP3008: VDD=VREF=3.3 V, AGND=DGND=GND, CH0 a 3.3 V, CH1 a GND.
- [ ] El script spi_thermocouple_monitor.py corre sin excepciones y genera thermo_log.csv.
- [ ] Lecturas de ADC: CH0≈1023 y CH1≈0; lecturas del termopar razonables en ambiente.
- [ ] Prueba de hielo: ~0 °C; prueba de ebullición: ~100 °C (tolerancias dentro de ±2 °C).
- [ ] He ejecutado trtexec FP16 con ResNet50 y observado FPS dentro de 40–65 en MAXN.
- [ ] He monitorizado tegrastats sin throttling térmico y restaurado nvpmodel tras la prueba.
Con este caso práctico, has construido un “spi-thermocouple-monitor” funcional y reproducible sobre NVIDIA Jetson TX2 Developer Kit usando el amplificador MAX31855 y el ADC MCP3008, ambos por SPI, con logging a CSV y validación cruzada del entorno (incluida la toolchain de IA con TensorRT).
Encuentra este producto y/o libros sobre este tema en Amazon
Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.




