Skip to the content
2 layers156.5 × 120 mmControladora Semaforos, the printed circuit board in 3D

Controladora Semaforos

dieleoz/Controladora_Semaforos-2

La tabla de abajo es verdad. Lee lo que mide antes de lo que puntúa.

Size
156.5 × 120 mm
Copper layers
2
Thickness
1.6 mm
Parts
185
Nets
116
Pads
485
Tracks, vias
1,447, 89
Pours
1
Routed
Yes
KiCad
KiCad 9.0 (file 20241229)
Created
28 Aug 2026
Updated
27 Oct 2026

Overview

Controladora Semaforos is an open-source printed circuit board by dieleoz, from the dieleoz/Controladora_Semaforos-2 repository on GitHub. It is a 2-layer board of 156.5 × 120 mm with 185 parts on 116 nets, routed with 1,447 tracks and 89 vias.

It is built around the MAX3485ED, TLP127 and LM1117DT-3.3, with the IRLZ44N and SS210 among its other parts. Its parts include 72 resistors, 30 capacitors, 30 diodes, 17 connectors and 15 ICs. It belongs with the STM32 boards of this library.

Main components

5

README

README.md

🚦 Controladora de Semáforos Móviles de 3 Estados (V9.1)

🧭 Las decisiones vigentes viven en DECISIONES.md — una fila por decision, con su fecha, su motivo y que deroga. (Aqui se publicaba cuantas hay; se quito el 11/09 porque decia 18 y 9 cuando ya eran mas: se cuentan alli.) Si un parrafo de cualquier documento contradice una fila de ahi, gana la fila: el parrafo esta caducado. Se lee ANTES de encargar un cambio de alcance.


🔴 Lo que este README no puede decirte, y es lo primero

▶️ Donde esta parado el trabajo y por donde se retoma lo dice ESTADO.md, que se reescribe en cada cierre; aqui no se repite. Lo que paso, en HISTORIA.md y en git log.

La instalación certificada es e303485 (V8.4, 31/07/2026). Lo de debajo llegó a una mesa el 3-4/09 y la noche del 04/09 —banco con dos tarjetas; la última cinta, 05/09 22:19, sobre 42a52cd— y 🔴 el 10/09 llegó por primera vez a una calle: un Maestro (SERIE:179DB0) corrió en El Sisga con firmware V9 SIN_BANCO —el paquete del 08/09 (7ff7d12); después se probó el del 10/09 (b354fe9)—. Su cinta y su diario están en evidencia/ (308 tramas, 308 checksums que casan). Lo que se reportó allí, lo que dice la cinta y la rama que salió de ahí, validada por el diff, están en roadmap.md §3.16 (N-162). 🔴 Con 7ff7d12, el Maestro 179DB0 se declara en hora con el reloj parado: no se usa el Modo Degradado allí. Desde el 29/09 el funcional prueba en banco las candidatas (a505fa2, 6bd1e4f, d3606be; cintas en evidencia/300920261130/, 011020260934/, 021020260914/), pero ninguna ha pasado banco completo.

La razon lineas de instrumento / lineas de producto la mide el pre-commit en cada commit (.githooks/trinquete.sh, contra el techo RAZON_TECHO de .topes): si sube por encima del techo, el commit se para. El techo solo baja, cuando un acta de campo archiva un tema (CLAUDE.md §4). Cuenta el indice, sin historico/, e incluye la app y el ESP32, asi que no se compara con las razones de la serie anterior (esa serie, en HISTORIA.md).

Tres auditorías externas independientes dijeron lo mismo, y la tercera lo dijo de la respuesta a la segunda. La regla que salió de ahí vive en CLAUDE.md §0 y §8:

Un 20/20 sobre decenas de miles de líneas de instrumento que nunca han tocado una tarjeta no es un entregable: es una coartada.

La tabla de abajo es verdad. Lee lo que mide antes de lo que puntúa.


📐 LA SPEC — empieza por aquí, y son nueve ficheros (SPEC_0 a SPEC_8)

Escritas el 12–13/09 desde el fuente, verificando cada afirmación contra el código; manda la SPEC y DECISIONES.md es su índice. SPEC_0 es la vista del sistema y SPEC_7 el modo sin reloj. Sustituyen a ~17.000 líneas de manuales que describían un sistema que ha cambiado cuatro veces. Nacieron por debajo de 300 líneas a propósito (hoy SPEC_1 y SPEC_2 lo pasan): un fichero que no se puede leer entero no lo lee nadie entero, y entonces cada lector deriva su propia versión.

qué contesta
SPEC_0_El_Sistemala vista del sistema: qué es, cómo se pone un cruce a funcionar y lo que el equipo no hace (§5)
SPEC_7_Modo_Sin_Relojel modo sin reloj y sin radio: el veredicto es que no se construye
SPEC_1_Ciclo_y_Lucesqué hace un poste con sus tres luces y su pluma: modos, tiempos, transiciones, la barrera de salidas
SPEC_2_Dos_Puntas_y_Radio🔴 lo único de verdad difícil: que los dos postes NUNCA den verde a la vez, con una radio lenta que pierde tramas y sin cable entre ellos; y sin radio, el Degradado con testigo (§7.bis) y el automatico a eleccion del tecnico (§7.ter, 29/09)
SPEC_3_La_Horade dónde sale la hora y qué pasa cuando se pierde — es lo que autoriza el Degradado, o sea el modo que da verdes sin confirmar con la otra punta
SPEC_4_App_y_Bluetoothla única forma de operar el equipo (D-16): qué órdenes hay, qué contesta el equipo a cada una y de qué depende esa respuesta
SPEC_5_Cobre_Camaras_Pluma🛑 qué hay en cada pin, qué es peligroso y qué no se ha medido nunca. Se lee con un destornillador en la mano
SPEC_8_Camaras_y_Barrera🛑 qué HACE el equipo con las cámaras y la barrera: el veto, el retardo de 3 s, cuándo pide que se revise una cámara, los dos interruptores de administrador, y qué NO protege. Es la otra mitad de SPEC_5: aquí lo que decide el firmware, allí lo que decide el cobre
SPEC_6_Campo_Radio_y_Alarmasel procedimiento de campo del Degradado, la configuración de radio y antenas, y la tabla completa de alarmas → qué hace el técnico

⚠️ La spec dice qué HACE el equipo hoy, no qué debería hacer. Lo que no cumple una decisión vigente vive en el apartado «HUECOS MEDIDOS» de cada una, con la medida pegada. Y los manuales viejos siguen en el árbol a propósito: se intentó jubilarlos y se paró con medida — hay contenido que ninguna spec cubre todavía (la receta de la APK, los ensayos de cámara con instrumento, la trama canónica con checksums de la que cuelga un pack). Está contado en roadmap.md 1.35(a).

🔧 Qué se probó en banco, y qué no

El 3 y 4 de Septiembre esto vio una tarjeta. El funcional ejecutó la guía de 29 pasos sobre 617bd00: 24 pasos completados, 4 bloqueados por el enlace Bluetooth y 1 abortado por un incidente de seguridad. Informe en evidencia/Informe_Pruebas_Banco_Semaforos_V9.0.pdf.

Funcionó en cobre: carga por SWD al primer intento, radio entre puntas con caída a ámbar en ~20 s y vuelta sola en ~3 s, talanquera, cámara de demanda y masa común a 0 V.

✅ La regresión N-42 —el Modo Automático no movía las luces— está CERRADA EN COBRE. La cerró la sesión de banco de la noche del 04/09, con el responsable delante: «ahí cambia ese amarillo y este a verde. Ahora está funcionando». El arreglo es ceb8cc5 —se retiró el asistente entero: una sola puerta, el modo arranca corriendo—. (Este README publicó «regresión abierta» hasta el 07/09; el banco la había cerrado tres días antes.)

🔴 Y aparecieron tres defectos que ninguna cifra de la tabla de abajo podía ver, porque ninguno es una propiedad del código: la tarjeta Maestro tiene un corto de 3,3 V a masa (N-116), las entradas de campo no tienen ninguna protección mientras las salidas sí (N-120), y el ESP32 no se anunciaba por Bluetooth (N-117). Los tres pasaron el 20/20 sin despeinarlo.

(El cuarto de aquella lista, N-118 —«el mando A/B no responde, 0,6 V en reposo»—, quedó REFUTADO el 05/09: el propio banco había medido las dos ramas del experimento en la misma tabla. Mismo cobre, distinto pinMode, distinta tensión. Ver 05_Funcional/historico/DECISIONES_hist.md, cerradas.)

Verificación actual — cifras copiadas del acta evidencia/2026-10-16_compuerta.txt, que genera python 01_Firmware/compuerta.py en una sola corrida. No se escriben a mano — y desde N-62 eso ya no es una promesa: el pack documentos_01_cifras_del_acta compara esta tabla contra la última acta en cada corrida del banco. Cuando se escribió por primera vez, falló: esta tabla publicaba 32 rutas y 86,4 % de flash cuando el acta que ella misma citaba medía 38 rutas y 92,8 %. Las cifras eran del 05/08 y llevaban la palabra «copiadas» encima.

ComprobaciónEstado
guarda de rutas de los instrumentos✅64 rutas parseadas, todas existen
banco por packs (70 packs)🔴 FALLA1492/1497 comprobaciones en 70 packs — 69 PASS, 1 FALLA. decisiones_01_anclas acusa a D-22 (necesita una tarjeta delante) y a D-94..D-97 (decididas por Fable el 14/10, sin construir); no se decora (CLAUDE.md §1)
compila Maestro / Esclavo / Repetidor / ESP32✅78.8 % · 65.3 % · 20.6 % · 35.8 % — el Maestro ocupa 50020 de 63488 B (las dos ultimas paginas quedan para las franjas de noche, D-108, y el testigo de D-35); el Esclavo, 41468 B. Bajo al quitar la libreria RTC (N-172) y subio con la salida programada (D-52) y el verde del testigo (D-59)
simulador funcional✅9/9 — eran 20, y 11 de aquellas no medían nada: se retiraron una a una con su evidencia
simulador de repetidor✅10/10
compila ESP32✅35.8 % — 1126409 de 3.145.728 B
simulador del puente ESP32✅159/159 — las tres puntas: bluetooth.cpp compilado, la app en jsdom, y solo el ESP32 modelado
simulador de app y bluetooth✅12/12 — estuvo en ABORTADO unas horas el 05/09: N-149 le añadió el campo ESC al $STATUS y el instrumento no supo con qué compararlo. Se enseñó a leerlo el mismo día. Queda escrito porque mientras duró, todo lo que vigilaba entró sin mirar (CLAUDE.md §1)
app ejecutada en DOM✅802/802 — carga index.html en jsdom, más app.js y los js/*.js que el propio HTML declara, en su orden, y los ejercita: pestañas, modales, ingesta de telemetría, fuzzing de 200 tramas corruptas y los botones que mandan comandos. Es el único instrumento que ejecuta la app en vez de leerla
test funcional de la app✅70/70 — decía «22/22» a mano y ejecuta 34; su prueba de Courier RTC era una tautología
test unitarios TDD de la app✅87/87 — la segunda suite unitaria, que hasta el 01/09 no estaba en la compuerta: 23 pruebas verdes que no medían nada. (Esta fila publicó 55/55 hasta el 07/09: era la cifra del 02/09, y documentos_01 no la vigila — no está en su tupla CIFRAS.)
test unitarios de la app✅67/67 — seis suites que no cargan el navegador: NMEA y checksums, generador de comandos y barrera de PIN, validación de SET_TIEMPOS, Courier RTC, gestor de cruces y escala de 20 cruces
arnés del ciclo✅78/78 — corre sobre el ciclo_degradado.h real compilado, sin espejo en Python
arnés del respaldo✅compila el calcularSuma() real; identidad de respaldo.cpp entre puntas + prueba de vida
arnés del Degradado a dos puntas✅158/158 — las dos puntas en Degradado cada una con su reloj. Entrega el número: el cruce aguanta 29 s de desfase contra los 20,2 s que el equipo puede acumular en 48 h, o sea factor 1,44 — y no el 2 que afirmaban los comentarios de las dos puntas
arnés de las dos puntas✅175/175 — el C++ real de las DOS puntas en el mismo proceso y el mismo instante: verde simultáneo en 0 instantes. Cubre G3/N-163 (suelta del verde), D-34 (verde del Esclavo frente al ámbar del Maestro, G12–G14) y D-53 (rojo+amarillo antes de cada verde). Sin banco
arnés del automático✅88/88 — compila coordinador.cpp + semaforo.cpp + modo_automatico.cpp + modo_inteligente.cpp, demanda.cpp y el botones.cpp real, y comprueba SFTY-2 sobre las escrituras de pin. Las 16 nuevas son el Bloque G de D-33: el retardo de bajada de la pluma y el veto de la cámara, ejecutados

🛑 Aquí había una fila más, arnés de pantalla, y NO se actualiza: se RETIRA. Compilaba los cuatro lcd.cpp/menu.cpp reales contra 131 .c de U8g2, y se fue con el LCD el 13/09 (D-32 (1), 17d3a1f). La compuerta baja de 20 filas a 19 y el banco pierde sus 287 comprobaciones (145 Maestro + 142 Esclavo): es una bajada A PROPÓSITO, no una regresión. Se dice aquí abajo y no en la tabla porque en la tabla sólo caben filas con una medida detrás — una fila sin medida se lee como medida.

18 PASS · 1 FALLA · 0 ABORTADO, de 19 comprobaciones — la compuerta sale con código 1.

🔴 El 1 es el hallazgo, no una regresión. Lo acusa decisiones_01_anclas: D-22 y D-94..D-97 están vigentes en DECISIONES.md sin una línea que las construya. D-22 es poner Y1 y espera una tarjeta delante: si Y1 no oscila, el _Error_Handler es noreturn y la tarjeta queda a oscuras; D-94..D-97 son SPEC sin construir que también piden placa.

🛑 Ninguna se apaga poniéndole un ancla: se construye o se deja rojo. El 07/09 se intentó cerrar las de entonces poniéndoles el ancla en un comentario y la compuerta se puso en 20/20 sin que se construyera nada (roadmap.md §3.10); las anclas se revirtieron y el rojo volvió, que es donde tiene que estar.

🟢 Y cuando vuelva a 0, ese verde será más peligroso que el rojo, no menos. Mientras la compuerta sale con 1 nadie la confunde con un permiso; un 0 sí se confunde. Lo que dice es exactamente esto: los modelos y los arneses de PC no encuentran nada. No dice que el firmware funcione en la tarjeta. El contraejemplo está fechado: los tres defectos que pararon el banco del 3-4/09 pasaron estas 19 comprobaciones sin despeinarlas. Verde no es entregable.

Por qué la compuerta está hecha así — cuatro lecciones, en una línea cada una

ABORTADO no es PASSuna comprobación que no pudo correr no dice nada del firmware. Así se perdió la cobertura del Maestro sin que nadie se enterara (N-28)
Un FALLA contado como PASSlos tres validadores monolíticos imprimían FALLA y salían con código 0. Se retiraron el 05/08 exigiendo que los packs sumaran exactamente sus comprobaciones y que el texto de cada una coincidiera — Costura 41 = 41, Maestro 64/67 = 64/67, Esclavo 31 = 31 (N-46)
Un gcc que existe no es un gcc que enlazados arneses cayeron a ABORTADO de un día para otro con el mismo compilador en el acta: ld no abría una ruta con ñ. La compuerta le exige enlazar un main() vacío antes de fiarse (N-44)
Un pack puede estar verde sin medir nadala prueba 2.8 del checksum hacía break sobre una condición siempre cierta y no evaluaba un solo candidato. Al arreglarla apareció un camino explotable en FLAGS/SYNC_BAJA (N-51)

El detalle de las cuatro, con su medida, está en roadmap.md.

Un acta no es una frase. evidencia/ guarda fecha, hash de HEAD y versión de toolchain de cada corrida, así que "20/20" deja de ser un número que envejece en un README y pasa a ser algo que el auditor re-corre sobre ese mismo commit. Estado de hoy en ESTADO.md; reglas permanentes en CLAUDE.md.

📦 El banco son 70 packs — y eso NO es una medalla

text
python 01_Firmware/Simulaciones/banco/correr.py --listar
python 01_Firmware/Simulaciones/banco/correr.py --pack esclavo_03   # un fallo, solo, en 1 s

Por qué se migró — había tanto instrumento como firmware: 8.898 líneas contra 8.895, uno a uno. Y los simuladores no ejecutan el C++, lo reimplementan a mano: son una segunda copia que alguien sincroniza, y eso falló cuatro veces en una semana.

⚠️ Pero correr.py NO es compuerta.py. El banco es una fila de veinte: un x/y de packs no dice nada de las otras diecinueve, y una de ellas puede estar en ABORTADO por el mismo cambio que acabas de comitear. Antes de comitear se corre compuerta.py, completo.

📦 Qué se le manda al funcional, y por qué son dos paquetes

Un paquete es una autorización implícita: quien lo recibe asume que puede instalarlo. Con el banco sin pasar, eso obliga a separar lo que pide una medida de lo que entrega una versión.

Encargo de bancoPide que alguien ponga la tarjeta delante. Lleva los binarios con sus MD5 y los firmware marcados SIN_VALIDAR en el propio nombre
Entrega de versiónFuente para PlatformIO + APK + el .html de pruebas vigente + LEEME_PRIMERO.txt. Sin .bin, sin manuales, sin .md y sin acta; se deja en entregas/ (ignorada por git), nunca en la raíz

El LEEME_PRIMERO no abre con la cifra en verde — abre diciendo qué corre en campo, que esto no es eso, y qué sigue roto. El método está en orquestador:entregar y en .claude/particularidades/entregar.md.

Certificado en campo: 31 de Julio de 2026 (V8.4, dos radios en enlace directo) Última actualización del repositorio: 11 de Septiembre de 2026 (la cifra vigente y su hash de HEAD están en el acta que cita la tabla de arriba, y no se repiten aquí: este pie llevaba 14 PASS sobre HEAD 2cde016 cuando el acta ya medía otra cosa, y un recuento viejo no se lee como viejo, se lee como medida.) Repositorio Oficial: github.com/dieleoz/Controladora_Semaforos-2 — remoto origin. Normativa Aplicable: Resolución 2024 del Ministerio de Transporte de Colombia (Secuencia de Luces y Tiempos de Seguridad Vial)


🧭 La arquitectura vigente, decidida en obra el 28/08 y cerrada el 31/08

El documento con el detalle medido —fichero:linea en cada afirmación, las decisiones abiertas con dueño y las medidas de multímetro— es 05_Funcional/17_Arquitectura_28-08_y_Decisiones_Abiertas.md, y manda la SPEC (05_Funcional/SPEC_0..8; DECISIONES.md es su índice). Aquí va sólo el reparto, porque un README que describe el aparato anterior manda a cablear el aparato anterior.

El reparto, en una frase

El STM32 sigue siendo el controlador del semáforo. El ESP32 es un módulo de expansión colgado de un puerto serie: aporta reloj y Bluetooth, y NO manda sobre las luces.

text
                       fuente propia 12 V (NO sale de la tarjeta)
                                    |
   +--------------------+     +-----v--------------------+
   |   STM32F103C8      |     |         ESP32            |
   |   (controlador)    |     |   (modulo de expansion)  |
   |                    |     |                          |
   |  luces    J3-J8    |     |  DS3231  GPIO21 SDA      |
   |  barrera  J15      |     |          GPIO22 SCL      |
   |  camaras  J16 (*)  |     |          (pila propia)   |
   |  LoRa     J12      |     |                          |
   |           USART3   |     |  Bluetooth (sustituye    |
   |                    |     |   al modulo SPP)         |
   |  USART1 remapeado  |     |                          |
   |  PB6 TX == J17 p3 <------ GPIO16 (RX2)              |
   |  PB7 RX == J17 p2 ------> GPIO17 (TX2)              |
   +---------|----------+     +-----------|--------------+
             |                            |
             +-------- masa comun --------+
                       9600 8N1

(*) Aquí ponía camaras J14, J16. ✏️ 11/09: las cámaras van a J16 —dos por poste, p10 y p12 (D-25)—. J14 no lleva cámara: A-2 lo reserva al fin de carrera, pero el firmware lo sigue leyendo como cámara de demanda (CAM_DEMANDA_PIN = PB0) — conflicto abierto, del responsable → D-27 (11/09): J14 LIBRE, sin cablear; el fin de carrera no se instala en este despliegue, así que en J14 no se conecta nada (ARQUITECTURA.map §7.3).

El enlace, pin a pin — y la fuente

ESP32direcciónJ17STM32
GPIO17 (TX2)➡️p2PB7 — RX del micro
GPIO16 (RX2)⬅️p3PB6 — TX del micro
GND—p7 o p9GND — masa común obligatoria

9600 8N1. El USART1 ya está remapeado a PB6/PB7 en el firmware de las dos puntas (N-76, bluetooth.cpp, grep -n "SerialBT(PB7, PB6)") — el puerto y el pinout son los mismos que ya tenía el módulo SPP; lo que se enchufa, no.

🔴 El ESP32 lleva fuente propia desde 12 V. NO cuelga de los 3,3 V de J17 p6/p8. Ese riel sale del U5 y es el mismo que alimenta al STM32 que gobierna el semáforo: un ESP32 con radio da picos de corriente del orden de medio amperio, y un reset del controlador provocado por un periférico de diagnóstico es el reparto de riesgo que no se acepta. El accesorio no puede tumbar al que manda.

Lo que se retira, y por qué — tachado, no borrado

Una vía descartada que desaparece en silencio vuelve a proponerse. Por eso van tachadas con su motivo al lado, y no suprimidas.

se retirapor quéconsecuencia
Pantalla LCD ST7920 (las dos puntas)este PCB no permite ampliación, y la pantalla ocupaba cinco pines —PB3 PB4 PB5 PB6 PB7— de los que el Bluetooth necesita PB6/PB7: no había de dónde sacarlos. Confirmado por el responsable el 05/09 (D-17.bis)toda la operación pasa por la app. Se retira del EQUIPO, no del código: lcd.cpp y menu.cpp siguen compilando y Validacion_LCD sigue dando 271/271 sobre un framebuffer del PC
Módulo Bluetooth SPP dedicado (HC-05 / JDY-30)lo sustituye el ESP32 por el mismo J17no se compran
Los CUATRO botoneslos pines 3 y 4 son los que necesitan las cámaras, y el 05/09 el responsable retiró la botonera entera: «todo por app»⚠️ DOS funciones de botón están muertas y DOS SIGUEN VIVAS, y el reparto no es casual: botonAceptar()/botonCancelar() son return false; —son los de PB14/PB15, los pines que ahora son cámaras—; pero botonArriba()/botonAbajo() tienen llamadores vivos y leen BOTON1/BOTON2, que son los pines del mando. 🔴 Lo que alguien cierre en J16 p5/p8 contra los 3,3 V SIGUE ENTRANDO al firmware. (Botón 1 y Botón 2 SON Mando A y Mando B: los mismos dos pines con dos nombres.)
El mando de relés (hardware)05/09, el responsable: «ya no tenemos mandos de A y B, sólo la app» (D-1)🔴 El CÓDIGO no se toca 🛑 DEROGADO POR D-30 (12/09): el software TAMBIÉN sale —el responsable: «hasta el sw lo quitamos»—. Decidido y SIN CONSTRUIR, y va con su precio medido, que es lo que lo tiene parado: mando_ambarLocal() tiene SEIS llamadas vivas (no cinco), y de ellas la que ABRE PASO es el veto del CMD_GO_GREEN del Esclavo; retirar sólo el armador deja ese if ABIERTO, no inerte. Además mando.cpp es el único escritor de senalActiva, así que el cambio toca SFTY-2, y después ningún instrumento vigila la interceptación de las salidas por señal. ⚠️ Y no cierra el cobre: J16 p5/p8 siguen vacíos y el firmware los lee por DOS caminos, no sólo por el del mando (CLAUDE.md §3)

🔴 Y su consecuencia declarada, que es una propiedad del sistema y no una avería (D-16): SIN TELÉFONO NO HAY FORMA DE OPERAR EL EQUIPO. Ni ámbar, ni volver a automático, ni parar el cruce. Va escrito en el manual del operario: el teléfono es herramienta crítica.

Las cámaras van a J16 p10 y p12 — dos por poste (D-25, 11/09) — y ya se cablean

(Resumen: la tabla que manda es 05_Funcional/17_… §1.7. La columna «red» es el nombre heredado del netlist, no el papel del pin.)

J16redpinuso nuevo
p1/12V—🔴 12 V crudos. Se tapa físicamente en CADA equipo que se monte (N-120) — es el único conector de señal de la tarjeta que los trae, sin opto ni clamp
p5/Boton1PB9libre y SIN CABLEAR (A-2, cerrada el 05/09: el fin de carrera va a J14 — 11/09, D-27: y tampoco allí, el fin de carrera no se instala; J14 queda libre). 🔴 El firmware sigue leyendo ese pin y alimentando el reconocedor de secuencias del mando
p8/Boton2PB13igual que p5
p10/Boton3PB14🎯 CAM_C_PIN — cámara 1, contacto de alarma entre p9 (3,3 V) y p10 (verificada en banco el 03/09)
p12/Boton4PB15🎯 CAM_D_PIN — cámara 2, contacto de alarma entre p11 (3,3 V) y p12

✅ D-25 (11/09, el responsable): las conexiones de la guía de cámaras del Sisga quedan DEFINITIVAS —4 cámaras, dos por poste— y derogan de D-13 solo «una por poste, p12 vacío». 🔴 Lo que el que cablea tiene que saber, medido en el firmware de hoy: las dos entradas hacen LO MISMO (piden paso; botones.cpp, CAM_J16[2]), ninguna protege la pluma (el veto es A-1.bis, sin construir), y una segunda cámara muerta desde la instalación no la detecta nadie (el vigilante salta el pin que nunca dio un flanco): se comprueba cada cámara por separado al instalar. Las frases falsas de la guía del 10/09 se corrigen en su versión nueva (roadmap.md §3.16) → ✏️ 11/09: es 05_Funcional/Camaras_Sisga_4x.html, con la fe de erratas delante y la talanquera en J15 al final. ⚠️ La app (también la APK del 10/09) pone CAM: OK — las dos ven en cuanto detecta CUALQUIERA de las dos cámaras del poste, aunque la otra no haya detectado nunca: por eso cada cámara se comprueba con el multímetro en su borne (0 V en reposo, 3,3 V con algo en la zona), y no con la app.

✅ La medida M3 está CERRADA desde el 03/09 y las cámaras se cablean (D-3). Medido en cobre —multímetro, conector vacío, paso 20 de la Guía—: el pull-down de 10 kΩ que declaraba el netlist es real y está en las cuatro posiciones (R65–R68 con su 100 nF); p10 y p12 dan 0 V en reposo, así que la entrada es activa en ALTO, que es lo que el firmware ya hacía. El paso 21 cableó p10 contra p11 en normalmente abierto y funcionó, sin demandas fantasma.

🛑 No se cablea cámara a J16 hasta cerrar la medida M3 — caducado: este README lo siguió publicando cuatro días después de cerrarse, y el 05/09 se le contestó al responsable con ese párrafo. Se conserva tachado porque una vía descartada que desaparece vuelve a proponerse.

⚠️ El orden sigue siendo asimétrico: primero el firmware cargado, después el destornillador. Un commit no protege de un destornillador — se exige la carga verificada en la tarjeta, no el merge. ✏️ 11/09, con D-25 vale para los DOS pines: con un binario anterior a deeeab4 (la V8.4 incluida) PB14 es botonAceptar() y PB15 es botonCancelar(), así que lo que se cablee en p10 o en p12 puede actuar como un botón en un equipo que está en la calle.

Seis luces gobernadas, no ocho

pines.h declara ocho salidas de luz, pero el semáforo peatonal nunca se conectó a nada:

declaradopin¿lo escribe alguien?
ROJO1 AMARILLO1 VERDE1 / ROJO2 AMARILLO2 VERDE2PA0-PA5✅ sí, y sólo semaforo.cpp
ROJO_PEATON · VERDE_PEATONPA6 · PA7🔴 ni un pinMode ni un digitalWrite en ninguna de las dos puntas
BUZZERPB1🔴 igual: declarado y nunca escrito

Es hardware pagado y muerto —tiene opto, MOSFET y bornera propia—. Se anota aquí porque "conserva las 8 luces" es la clase de frase que se copia de documento en documento sin que nadie corra el grep: la barrera de salidas de CLAUDE.md §2 custodia ocho nombres; el equipo mueve seis.

🛑 Lo que esta arquitectura NO autoriza

  • Nada de esto ha pasado banco entero, y la compuerta no lo suple. Lo que este apartado llama medido se midió en su mayoría sobre ficheros —el .cpp, el .h, el .kicad_sch y el .kicad_pcb—. Un fichero dice lo que alguien dibujó; una placa dice lo que se fabricó.
  • 🟠 Sin pantalla, $STATUS es el único tablero que existe — y hoy trae BAT:-- porque no hay un solo analogRead en src/. Un campo que no se mide se retira o se marca; no se deja con aspecto de medida.
  • 🟠 El ESP32 de este proyecto no tiene watchdog en el Repetidor (los dos STM32 sí: 4 s; el ESP32 de expansión también, desde vigilante.cpp), y hay precedente escrito de uno clavado tumbando el enlace. Con la pantalla y el mando retirados, un ESP32 colgado deja el equipo sin ninguna superficie de mando.

El plano de conexiones que se entrega —J17, J16, PB6/PB7, el DS3231 y el SWD— es 05_Funcional/Montaje_Campo_2026-10-05.html, con el cobre medido en 17_... y SPEC_5.


🗂️ Paquete Oficial de Entregables y Manuales (05_Funcional/, en .md y .docx)

ARCHIVADOS el 28/09 en 05_Funcional/historico/: todas las filas salvo la 10 y la 17. No son vigentes; mandan las SPEC_0..8 (CLAUDE.md §15). La columna «Estado» describe cada manual antes de archivarlo.

#ManualEstado
11_Manual_UsuarioOperación y comportamiento vial (Resolución 2024)
22_Manual_Hardware_y_PruebasHardware, borneras y ensamblaje STM32
33_Protocolo_Pruebas_RigurosasProtocolo de auditoría funcional. ⚠️ reescrito: cada prueba lleva su marca SE REESCRIBE / SE RETIRA / SE APLAZA
44_Manual_Configuracion_RadiosE90-DTU (2.4 kbps / 30 dBm / FEC)
55_Manual_Puente_ESP32Puente repetidor V7.6 — fuera de la configuración vigente
66_Preguntas_Diseno_FuncionalDecisiones de diseño cerradas
77_Especificacion_AntenasAntenas y línea de vista
88_Procedimiento_Modo_DegradadoOperación de emergencia por reloj sin radio
99_Manual_Parametrizacion_Camara_IA4 cámaras, dos por poste en J16 p10/p12 (D-25, 11/09) — ⚠️ el manual todavía dice una por poste: pendiente de alinear ✏️ alineado el 11/09 (el .docx no: se regenera aparte). Es el entregable principal del diseño de cámaras (D-12): toda la inteligencia vive en la configuración de la cámara. 🎯
11/09, D-27: sus VALORES de configuración salen del manual del modelo, 05_Funcional/historico/MANUAL_CONFIGURACION_CAMARAS_IA.md §4 —tabla valor a valor en su §4 Paso 3—; las cuatro cámaras están compradas
1010_Manual_Modulo_Bluetooth_Telemetria⚠️ manda enchufar un HC-05 en J17, que es donde va el ESP32
1111_Manual_Instalacion_RTC_DS3231_BateriaDS3231 en PB0/PB8 → se muda al ESP32. ⚠️ manual sin corregir
1212_Cobertura_de_Pruebas_y_HuecosQué mide cada instrumento y qué queda sin medir
1313_Manual_Modulo_Expansion_I2C_y_Compras⚠️ su §4 queda sin sujeto: el I²C ya no vive en el STM32
1414_Manual_App_Movil_IOT_VIALOperación de la app: SPP, gestor de cruces y Courier RTC
1515_Lista_de_Compras_HardwareQué se pide, cuánto y cuándo
1616_Documento_Auditoria_Arquitectura_y_Usabilidad_AppAuditoría de arquitectura y usabilidad de la app
1717_Arquitectura_28-08_y_Decisiones_Abiertas🧭 Manda sobre las filas 9, 10, 11 y 13. Es donde se anotan las medidas de cobre
1818_Especificacion_Firmware_ESP32Especificación del firmware del módulo de expansión ESP32
1919_Especificacion_Placa_Portadora_ESP32Especificación de la placa portadora del ESP32

(La lista se ha desfasado CUATRO veces por lo mismo, y sigue sin instrumento: el 27/08 anunciaba 11 manuales de los 14 que existían; el 28/08, 15 de 16; el 31/08, 16 de 17; y hasta el 11/09, 17 de 19. Contar los ficheros es ls 05_Funcional/[0-9]*.md; que nadie lo haga es lo que hace falta cerrar.)


🛠️ Estructura del Ecosistema de Firmware

  • 01_Firmware/Maestro: El controlador. Máquina de estados STM32, barrera de salidas (semaforo.cpp, el único que escribe pines de luz), Modo Degradado, mando de relés (código conservado) y telemetría Bluetooth (USART1 remapeado a PB6/PB7 → J17).
  • 01_Firmware/Esclavo: Nodo secundario STM32 con ACK por radio (USART3), fallback de orfandad a 25 s, ámbar local con veto SFTY-21 y telemetría Bluetooth.
  • 01_Firmware/ESP32_Expansion: El módulo de expansión —reloj DS3231 y Bluetooth—, con watchdog (vigilante.cpp).
  • 01_Firmware/Repetidor: Puente ESP32 back-to-back. ⚠️ Fuera de la configuración vigente y sin watchdog: es el mismo firmware que se quedó clavado tumbando el enlace el 31/07. No es el ESP32 de expansión.
  • 01_Firmware/Simulaciones/: simuladores y banco/ con sus packs (cuántos, en el acta).
  • 01_Firmware/Validacion_LCD/ · _Ciclo/ · _Respaldo/ · _Automatico/: los arneses que compilan C++ real. Qué compila cada uno y su punto ciego: ARQUITECTURA.map; su crónica, ARQUITECTURA_hist.map.
  • 01_Firmware/compuerta.py: la única forma correcta de verificar — 18 PASS · 1 FALLA · 0 ABORTADO, exit code 1. Las cifras están en la tabla de arriba, que se copia del acta; ésta es sólo la puerta. Qué se corre según lo que se toca (la cadencia) y por qué el simulador está congelado: CLAUDE.md §4.
  • .githooks/ y .topes: el pre-commit del método (topes de documentos, ancho, relatos, 500 líneas por fichero de código salvo el firmware grabado) y el trinquete instrumentos/producto. Se activa con git config core.hooksPath .githooks.
  • .claude/particularidades/: lo propio de este repo para las skills del plugin orquestador@diego (entregar, verificar) y la mecánica larga de CLAUDE.md.
  • ESTADO.md es el punto de retomar; HISTORIA.md, la crónica; DECISIONES.md, lo ya contestado.
  • Los paquetes no se versionan: salen a entregas/ (ignorada por git), y los retirados a entregas/RETIRADOS/.

🛑 Y para cerrar donde se abrió: nada de este README es un permiso. En campo corre la V8.4; la V9.1 compila y pasa 18 de las 19 filas de la compuerta — la que falla es el censo de decisiones sin construir, y falla con razón (D-22 necesita una tarjeta delante). Lo que hay hoy en el árbol no ha visto una tarjeta. Nada sube a campo sin pasar banco — y el banco no lo sustituye ningún número verde de esta página.

Parts

185
QtyValueFootprintReferences
2610KResistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR1, R20, R22, R24, R26, R29, R31, R34, R36, R39, R41, R44, R46, R49, R51, R54 +10
20220Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR19, R21, R25, R27, R30, R32, R35, R37, R40, R42, R45, R47, R50, R52, R55, R57 +4
17LEDLED_SMD:LED_1206_3216Metric_Pad1.42x1.75mm_HandSolderD1, D2, D3, D4, D5, D10, D12, D13, D15, D17, D19, D21, D23, D25, D27, D29 +1
161KResistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR12, R13, R14, R15, R16, R17, R23, R28, R33, R38, R43, R48, R53, R58, R63, R73
11Conn_01x02TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_HorizontalJ1, J3, J4, J5, J6, J7, J8, J9, J11, J13, J15
10100nFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC16, C17, C18, C19, C20, C21, C22, C23, C24, C30
101N4148Diode_THT:D_DO-35_SOD27_P7.62mm_HorizontalD11, D14, D16, D18, D20, D22, D24, D26, D28, D30
10IRLZ44NPackage_TO_SOT_THT:TO-220-3_VerticalQ1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10
10TLP127Package_SO:Toshiba_SOIC-4-6_4.4x3.6mm_P1.27mmU6, U7, U8, U9, U10, U11, U12, U13, U14, U15
6100 nFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC1, C2, C3, C4, C10, C11
5100nfCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC25, C26, C27, C28, C29
410uFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC12, C13, C14, C15
420 pFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC6, C7, C8, C9
44.7KResistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR7, R8, R9, R11
4MountingHole_3.2mm_M3_DIN965MountingHole:MountingHole_3.2mm_M3_DIN965H1, H2, H3, H4
3Conn_01x02Connector_Molex:Molex_KK-254_AE-6410-02A_1x02_P2.54mm_VerticalJ10, J12, J14
3SS210Diode_SMD:D_SMAD6, D7, D8
2120Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR6, R10
2ESD-Logo_8.9x8mm_SilkScreenSymbol:ESD-Logo_8.9x8mm_SilkScreenV1, V2
2MAX3485Package_SO:SOIC-8_3.9x4.9mm_P1.27mmU2, U3
10Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR5
11 uFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC5
110kResistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR2
11MResistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR4
132.768kHzCrystal:Crystal_DS10_D1.0mm_L4.3mm_HorizontalY2
1330Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolderR18
18MHzCrystal:Crystal_HC49-U_VerticalY1
1Conn_01x04_PinConnector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalJ2
1Conn_01x12_PinConnector_Molex:Molex_KK-254_AE-6410-16A_1x16_P2.54mm_VerticalJ16
1Conn_01x13_PinConnector_Molex:Molex_KK-254_AE-6410-16A_1x16_P2.54mm_VerticalJ17
1LM1117DT-3.3Package_TO_SOT_SMD:TO-252-3_TabPin2U5
1LM7805_TO220Package_TO_SOT_THT:TO-220-3_VerticalU4
1LOGOLogos:LOGOG***
1STM32F103C8TxPackage_QFP:LQFP-48_7x7mm_P0.5mmU1
1SW_Omron_B3FSButton_Switch_SMD:SW_SPST_Omron_B3FS-100xPSW1
1WEEE-Logo_5.6x8mm_SilkScreenSymbol:WEEE-Logo_5.6x8mm_SilkScreenV3

Similar boards

  • 2 layers108 × 110 mmBms active hw, the printed circuit board in 3D

    Bms active hw

    NGOQUOC98/ESP32_PCB

    136 parts1
  • 4 layers110 × 90 mmPLC V1, the printed circuit board in 3D

    PLC V1

    paulmartinezcuenta/UltiCore-V1-PLC

    Custom industrial-grade PLC and logic controller engineered around the ESP32 platform.

    202 parts1MIT
  • 4 layers90 × 61.5 mmPM Controller, the printed circuit board in 3D

    PM Controller

    ZeshuLiu/PolaMiyaHardware

    132 parts1
  • 4 layers191 × 113 mmJhl synth3, the printed circuit board in 3D

    Jhl synth3

    koyoi/jhl_synth3_pcb

    128 parts
  • 2 layersPLC V1, the printed circuit board in 3D

    PLC V1

    JosueHerrera05/Josue_Herrera_Electiva_2026_C2

    Repositorio Electíva Diseño Mecatrónico 2026-C2

    59 partsMIT
  • 2 layers50 × 57 mmLED driver3, the printed circuit board in 3D

    LED driver3

    xtompok/LED_driver

    3x5A PWM driver for LED strips

    131 partsMIT
  • 2 layers90 × 48.9 mmEsp32 octal wled, the printed circuit board in 3D

    Esp32 octal wled

    klaus-liebler/esp32_octal_wled

    79 partsMIT
  • 2 layers110 × 80 mmFd1 controller, the printed circuit board in 3D

    Fd1 controller

    saikoushiknalubola/firedamp-fd1

    FD-1 is a wellhead node for coal mine methane drainage boreholes. It measures gas purity (NDIR CH4 and electrochemical O2), flow (ISO 5167 orifice + differential pressure) and line pressure at each borehole, throttles…

    48 parts

Questions

How big is the Controladora Semaforos PCB?

It measures 156.5 × 120 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Controladora Semaforos use?

185 parts, built around the MAX3485ED, TLP127, LM1117DT-3.3 and IRLZ44N. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Controladora Semaforos KiCad files?

From the dieleoz/Controladora_Semaforos-2 repository on GitHub, at the commit this page was made from: the board is 01_Firmware/Controladora_Semaforos/Controladora_Semaforos/Controladora_Semaforos.kicad_pcb and its schematic 01_Firmware/Controladora_Semaforos/Controladora_Semaforos/Controladora_Semaforos.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Controladora Semaforos design in my own project?

Its repository states no licence, so its author keeps all rights: ask dieleoz before reusing the design.