- Buffer de transicion persistente (sprTrans) de 25KB asignado una sola vez en setup() para evitar fallos de memoria heap contigua - Eliminacion de carga y descarga dinamica de fuentes en renderPage2ToSprite durante las transiciones para evitar fugas de RAM - Timeout de seguridad por hardware de 250ms en waitForTouchRelease() para prevenir bloqueos por ruido en la lamina resistiva - Pantallas 2 y 3: Reloj atomico GPS con DSEG7 de 80pt y Telemetria satelital completa (rumbo, satelites, altitud, coordenadas) - Documentacion de conexion y pines para modulo GPS N32+/U-blox
216 lines
11 KiB
Python
216 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Genera una ilustración técnica de alta resolución del pinout del módulo GPS
|
|
(U-blox NEO-6M / NEO-7M / N32+) y su correspondencia con la placa ESP32 CYD.
|
|
"""
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
import os
|
|
|
|
W, H = 1000, 680
|
|
im = Image.new("RGB", (W, H), (11, 15, 25)) # Sleek dark navy
|
|
draw = ImageDraw.Draw(im)
|
|
|
|
# Load fonts
|
|
try:
|
|
font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 18)
|
|
font_subtitle = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 12)
|
|
font_sec = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 14)
|
|
font_bold = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 12)
|
|
font_reg = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 11)
|
|
font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 10)
|
|
font_tiny = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 9)
|
|
font_chip = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 10)
|
|
except Exception:
|
|
font_title = font_subtitle = font_sec = font_bold = font_reg = font_small = font_tiny = font_chip = ImageFont.load_default()
|
|
|
|
def draw_card(box, fill, outline, radius=6, width=1):
|
|
draw.rounded_rectangle(box, radius=radius, fill=fill, outline=outline, width=width)
|
|
|
|
# Palette
|
|
C_CARD = (18, 24, 38)
|
|
C_CARD_BORDER = (45, 58, 88)
|
|
C_TEXT_WHITE = (245, 248, 252)
|
|
C_TEXT_MUTED = (145, 158, 180)
|
|
C_TEXT_CYAN = (0, 210, 255)
|
|
|
|
COLOR_VCC = (255, 60, 60)
|
|
COLOR_RX = (255, 145, 0)
|
|
COLOR_TX = (40, 215, 125)
|
|
COLOR_GND = (45, 135, 255)
|
|
COLOR_PPS = (190, 100, 255)
|
|
|
|
# -------------------------------------------------------------
|
|
# 1. HEADER
|
|
# -------------------------------------------------------------
|
|
draw.text((40, 20), "PINOUT Y GUIA DE CONEXION: MODULO GPS U-BLOX / N32+", fill=C_TEXT_WHITE, font=font_title)
|
|
draw.text((40, 46), "Chipsets NEO-6M / NEO-7M / NEO-8M / N32+ con Antena Cerámica y Puerto Serial UART", fill=C_TEXT_CYAN, font=font_subtitle)
|
|
draw.line([(40, 70), (W - 40, 70)], fill=(35, 46, 72), width=1)
|
|
|
|
# -------------------------------------------------------------
|
|
# 2. CUADRO PRINCIPAL DEL MODULO GPS (ILUSTRACION DE PLACA)
|
|
# -------------------------------------------------------------
|
|
board_panel = [40, 85, 480, 480]
|
|
draw_card(board_panel, (14, 18, 30), C_CARD_BORDER, radius=8)
|
|
draw.text((55, 95), "VISTA SUPERIOR DEL MODULO GPS", fill=C_TEXT_CYAN, font=font_sec)
|
|
|
|
# PCB del GPS (Azul industrial estilo U-blox)
|
|
pcb_box = [80, 130, 440, 440]
|
|
draw_card(pcb_box, (15, 50, 105), (35, 80, 155), radius=10, width=2)
|
|
|
|
# Orificios de montaje en las 4 esquinas (con arandela dorada)
|
|
for hx, hy in [(95, 145), (425, 145), (95, 425), (425, 425)]:
|
|
draw.ellipse([hx-7, hy-7, hx+7, hy+7], fill=(190, 160, 60), outline=(140, 110, 30))
|
|
draw.ellipse([hx-4, hy-4, hx+4, hy+4], fill=(11, 15, 25))
|
|
|
|
# Antena Cerámica Cuadrada (Parche cerámico color marrón dorado)
|
|
ant_box = [115, 165, 260, 310]
|
|
draw_card(ant_box, (185, 145, 65), (130, 95, 35), radius=6, width=2)
|
|
# Superficie metalizada superior de la antena
|
|
draw_card([125, 175, 250, 300], (210, 175, 95), (150, 115, 50), radius=4, width=1)
|
|
# Punto central de soldadura / alimentación RF
|
|
draw.ellipse([182, 232, 194, 244], fill=(245, 245, 245), outline=(120, 120, 120), width=1)
|
|
draw.text((135, 315), "ANTENA CERAMICA GPS", fill=(210, 185, 130), font=font_small)
|
|
|
|
# Blindaje Metálico U-blox (Shield Can)
|
|
shield_box = [280, 165, 415, 285]
|
|
draw_card(shield_box, (190, 198, 210), (140, 148, 160), radius=4, width=2)
|
|
draw.rectangle([282, 167, 413, 172], fill=(220, 228, 238)) # Reflejo de luz
|
|
draw.text((295, 178), "u-blox", fill=(190, 30, 30), font=font_sec)
|
|
draw.text((295, 202), "NEO-7M-0-001", fill=(30, 35, 45), font=font_chip)
|
|
draw.text((295, 218), "GPS / GLONASS", fill=(60, 70, 85), font=font_tiny)
|
|
# Mini QR / DataMatrix decorativo
|
|
draw_card([370, 235, 405, 270], (240, 240, 240), (80, 80, 80), radius=2)
|
|
draw.rectangle([374, 239, 380, 245], fill=(30, 30, 30))
|
|
draw.rectangle([395, 239, 401, 245], fill=(30, 30, 30))
|
|
draw.rectangle([374, 260, 380, 266], fill=(30, 30, 30))
|
|
draw.rectangle([386, 248, 392, 254], fill=(30, 30, 30))
|
|
|
|
# Pila de botón de respaldo (RTC / Ephemeris Backup Battery)
|
|
batt_x, batt_y = 305, 325
|
|
draw.ellipse([batt_x-16, batt_y-16, batt_x+16, batt_y+16], fill=(195, 202, 212), outline=(130, 135, 145), width=2)
|
|
draw.text((batt_x-10, batt_y-5), "3V", fill=(50, 55, 65), font=font_tiny)
|
|
draw.text((280, 345), "Pila RTC Backup", fill=C_TEXT_MUTED, font=font_tiny)
|
|
|
|
# LED de Estado PPS (Fix Indicator)
|
|
led_x, led_y = 380, 325
|
|
draw.ellipse([led_x-7, led_y-7, led_x+7, led_y+7], fill=(50, 220, 110), outline=(20, 140, 60), width=1)
|
|
draw.ellipse([led_x-3, led_y-3, led_x+3, led_y+3], fill=(200, 255, 220)) # brillo central
|
|
draw.text((358, 345), "LED PPS (Fix)", fill=(80, 235, 130), font=font_tiny)
|
|
|
|
# Silkscreen del modelo
|
|
draw.text((120, 350), "N32+ GPS MODULE", fill=(220, 230, 245), font=font_bold)
|
|
draw.text((120, 368), "UART: 9600 bps 8N1", fill=(160, 190, 230), font=font_small)
|
|
|
|
# Tira de pines (Header) en la parte inferior del PCB
|
|
# 5 pines: VCC, RX, TX, GND, PPS
|
|
header_box = [130, 395, 390, 430]
|
|
draw_card(header_box, (20, 20, 20), (50, 50, 50), radius=3)
|
|
|
|
pin_defs = [
|
|
("VCC", COLOR_VCC, 160),
|
|
("RX", COLOR_RX, 215),
|
|
("TX", COLOR_TX, 270),
|
|
("GND", COLOR_GND, 325),
|
|
("PPS", COLOR_PPS, 370)
|
|
]
|
|
|
|
for name, col, px in pin_defs:
|
|
# Pin cuadrado dorado con orificio
|
|
draw.rectangle([px-8, 400, px+8, 420], fill=(220, 185, 55), outline=(150, 120, 30))
|
|
draw.ellipse([px-4, 406, px+4, 414], fill=(20, 20, 20))
|
|
# Texto de serigrafia en PCB
|
|
draw.text((px-9, 380), name, fill=col, font=font_chip)
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# 3. DETALLE DE CADA PIN Y CONEXION A LA CYD (COLUMNA DERECHA)
|
|
# -------------------------------------------------------------
|
|
pins_panel = [500, 85, 960, 480]
|
|
draw_card(pins_panel, (14, 18, 30), C_CARD_BORDER, radius=8)
|
|
draw.text((515, 95), "DESCRIPCION DE PINES Y DESTINO EN PLACA CYD", fill=C_TEXT_WHITE, font=font_sec)
|
|
|
|
# Tarjeta Pin 1: VCC
|
|
p1_card = [515, 125, 945, 185]
|
|
draw_card(p1_card, (26, 32, 48), (200, 50, 50), radius=6)
|
|
draw.rectangle([515, 125, 523, 185], fill=COLOR_VCC)
|
|
draw.text((535, 132), "PIN 1: VCC (Alimentacion 3.3V a 5.0V DC)", fill=COLOR_VCC, font=font_bold)
|
|
draw.text((535, 149), "Entrada de corriente con regulador LDO integrado en la placa GPS.", fill=C_TEXT_MUTED, font=font_small)
|
|
draw.text((535, 165), "--> CONECTAR A: Pin 1 del conector P1 de la CYD (Vin 5V USB)", fill=C_TEXT_WHITE, font=font_reg)
|
|
|
|
# Tarjeta Pin 2: RX
|
|
p2_card = [515, 195, 945, 255]
|
|
draw_card(p2_card, (26, 32, 48), (200, 120, 20), radius=6)
|
|
draw.rectangle([515, 195, 523, 255], fill=COLOR_RX)
|
|
draw.text((535, 202), "PIN 2: RX (Entrada Serial UART del GPS - Nivel 3.3V)", fill=COLOR_RX, font=font_bold)
|
|
draw.text((535, 219), "Recibe comandos UBX de reposo (Sleep) y despertar (Wake) desde el ESP32.", fill=C_TEXT_MUTED, font=font_small)
|
|
draw.text((535, 235), "--> CONECTAR A: Pin 2 del conector P1 de la CYD (GPIO 1 / TX0)", fill=C_TEXT_WHITE, font=font_reg)
|
|
|
|
# Tarjeta Pin 3: TX
|
|
p3_card = [515, 265, 945, 325]
|
|
draw_card(p3_card, (26, 32, 48), (30, 160, 90), radius=6)
|
|
draw.rectangle([515, 265, 523, 325], fill=COLOR_TX)
|
|
draw.text((535, 272), "PIN 3: TX (Salida Serial UART del GPS - Nivel 3.3V)", fill=COLOR_TX, font=font_bold)
|
|
draw.text((535, 289), "Transmite sentencias NMEA ($GPRMC, $GPGGA, velocidad, hora satelital).", fill=C_TEXT_MUTED, font=font_small)
|
|
draw.text((535, 305), "--> CONECTAR A: Pin 3 del conector P3 de la CYD (GPIO 35 / RX1)", fill=C_TEXT_WHITE, font=font_reg)
|
|
|
|
# Tarjeta Pin 4: GND
|
|
p4_card = [515, 335, 945, 395]
|
|
draw_card(p4_card, (26, 32, 48), (30, 90, 180), radius=6)
|
|
draw.rectangle([515, 335, 523, 395], fill=COLOR_GND)
|
|
draw.text((535, 342), "PIN 4: GND (Masa / Retorno comun)", fill=COLOR_GND, font=font_bold)
|
|
draw.text((535, 359), "Retorno de corriente y referencia de nivel logico serial.", fill=C_TEXT_MUTED, font=font_small)
|
|
draw.text((535, 375), "--> CONECTAR A: Pin 4 del conector P1 de la CYD (GND)", fill=C_TEXT_WHITE, font=font_reg)
|
|
|
|
# Tarjeta Pin 5: PPS (Opcional)
|
|
p5_card = [515, 405, 945, 465]
|
|
draw_card(p5_card, (22, 28, 42), (120, 60, 180), radius=6)
|
|
draw.rectangle([515, 405, 523, 465], fill=COLOR_PPS)
|
|
draw.text((535, 412), "PIN 5: PPS (Pulse Per Second - Pulso 1 Hz)", fill=COLOR_PPS, font=font_bold)
|
|
draw.text((535, 429), "Pulso de sincronismo atómico cada 1 segundo exacto cuando hay fix 3D.", fill=C_TEXT_MUTED, font=font_small)
|
|
draw.text((535, 445), "--> NO REQUERIDO: Queda libre / no conectar (sincronismo por NMEA)", fill=(160, 170, 185), font=font_small)
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# 4. ESPECIFICACIONES TECNICAS Y TIPS DE INSTALACION (INFERIOR)
|
|
# -------------------------------------------------------------
|
|
info_box = [40, 500, 960, 655]
|
|
draw_card(info_box, (15, 20, 32), (45, 58, 88), radius=8)
|
|
draw.text((55, 510), "ESPECIFICACIONES TECNICAS Y RECOMENDACIONES DE INSTALACION:", fill=C_TEXT_WHITE, font=font_bold)
|
|
|
|
col1_x = 55
|
|
val1_x = 180
|
|
draw.text((col1_x, 532), "• Chipset:", fill=C_TEXT_CYAN, font=font_bold)
|
|
draw.text((val1_x, 532), "U-blox 7 / NEO-7M (o NEO-6M / N32+) 56 canales.", fill=C_TEXT_WHITE, font=font_small)
|
|
|
|
draw.text((col1_x, 552), "• Protocolo:", fill=C_TEXT_CYAN, font=font_bold)
|
|
draw.text((val1_x, 552), "NMEA 0183 a 9600 bps (8N1 - 8 bits, no paridad, 1 stop).", fill=C_TEXT_WHITE, font=font_small)
|
|
|
|
draw.text((col1_x, 572), "• Consumo:", fill=C_TEXT_CYAN, font=font_bold)
|
|
draw.text((val1_x, 572), "Activo: ~45 mA | Modo Sleep (UBX-RXM-PMREQ): < 0.5 mA.", fill=C_TEXT_WHITE, font=font_small)
|
|
|
|
draw.text((col1_x, 592), "• Nivel Logico:", fill=C_TEXT_CYAN, font=font_bold)
|
|
draw.text((val1_x, 592), "3.3V TTL (compatible directo con pines GPIO del ESP32).", fill=C_TEXT_WHITE, font=font_small)
|
|
|
|
col2_x = 525
|
|
val2_x = 705
|
|
draw.text((col2_x, 532), "• Posición de Antena:", fill=(255, 215, 60), font=font_bold)
|
|
draw.text((val2_x, 532), "Cara cerámica orientada al cielo.", fill=C_TEXT_WHITE, font=font_small)
|
|
|
|
draw.text((col2_x, 552), " (En el tablero del vehículo, libre de chapas metálicas o tintes metalizados).", fill=C_TEXT_MUTED, font=font_small)
|
|
|
|
draw.text((col2_x, 575), "• LED Verde (Fix/PPS):", fill=(80, 235, 130), font=font_bold)
|
|
draw.text((val2_x, 575), "Apagado: buscando satélites.", fill=C_TEXT_WHITE, font=font_small)
|
|
|
|
draw.text((col2_x, 595), " (Destella 1 vez por segundo cuando la señal satelital 3D está fijada).", fill=C_TEXT_MUTED, font=font_small)
|
|
|
|
draw.text((col1_x, 625), "NOTA: Al programar el ESP32 por USB, si el pin RX del GPS esta conectado a GPIO 1 (P1), desconectar temporalmente el cable amarillo para evitar colisiones.", fill=(255, 180, 80), font=font_small)
|
|
|
|
# Guardar imagen en hardware/ y en raíz
|
|
out_path_1 = "hardware/pinout_gps.png"
|
|
out_path_2 = "hardware/gps_pinout.png"
|
|
out_path_3 = "pinout_gps.png"
|
|
im.save(out_path_1, "PNG")
|
|
im.save(out_path_2, "PNG")
|
|
im.save(out_path_3, "PNG")
|
|
print("Pinout GPS generado exitosamente en:", out_path_1, out_path_2, out_path_3)
|