1+ // Componente React para visualização interativa da pinagem do ESP-32 DevKit-V1.
2+
3+ import React , { useState } from 'react' ;
4+ import styles from './Esp32Pinagem.module.css' ;
5+
6+ // Definição de Cores das Funções
7+ const SIGNAL_TYPES = {
8+ pwr : { label : "Alimentação (PWR)" , color : "#ef4444" } ,
9+ gnd : { label : "Terra (GND)" , color : "#94a3b8" } ,
10+ ser : { label : "Comunicação (SPI/I2C/UART)" , color : "#3b82f6" } ,
11+ ana : { label : "Analógico (ADC)" , color : "#10b981" } ,
12+ rtc : { label : "RTC / Controle" , color : "#a855f7" } ,
13+ tch : { label : "Touch Capacitivo" , color : "#ec4899" } ,
14+ dac : { label : "Saída Analógica (DAC)" , color : "#f59e0b" } ,
15+ warn : { label : "Reservado / Flash" , color : "#f97316" } ,
16+ gen : { label : "GPIO Padrão" , color : "#64748b" }
17+ } ;
18+
19+ const PIN_DEFINITIONS = [
20+ {
21+ id : "EN" , side : "L" , pos : 0 ,
22+ func : [ { name :"EN" , type :"rtc" } ] ,
23+ note : "Pino 'Chip Enable'. Puxe para BAIXO para reiniciar (Reset). Possui pull-up interno. Use um capacitor de 100nF para GND para debouncing automático."
24+ } ,
25+ {
26+ id : "VP" , side : "L" , pos : 1 , isInputOnly : true ,
27+ func : [ { name :"GPIO36" , type :"gen" } , { name :"ADC1_CH0" , type :"ana" } , { name :"RTC_GPIO0" , type :"rtc" } ] ,
28+ note : "Apenas Entrada (Input Only). Baixo ruído (pré-amplificador). Sem resistores de pull-up/down internos."
29+ } ,
30+ {
31+ id : "VN" , side : "L" , pos : 2 , isInputOnly : true ,
32+ func : [ { name :"GPIO39" , type :"gen" } , { name :"ADC1_CH3" , type :"ana" } , { name :"RTC_GPIO3" , type :"rtc" } ] ,
33+ note : "Apenas Entrada (Input Only). Baixo ruído (pré-amplificador). Sem resistores de pull-up/down internos."
34+ } ,
35+ {
36+ id : "D34" , side : "L" , pos : 3 , isInputOnly : true ,
37+ func : [ { name :"GPIO34" , type :"gen" } , { name :"ADC1_CH6" , type :"ana" } , { name :"RTC_GPIO4" , type :"rtc" } ] ,
38+ note : "Apenas Entrada (Input Only). Sem resistores de pull-up/down internos. Ótimo para leitura analógica pura."
39+ } ,
40+ {
41+ id : "D35" , side : "L" , pos : 4 , isInputOnly : true ,
42+ func : [ { name :"GPIO35" , type :"gen" } , { name :"ADC1_CH7" , type :"ana" } , { name :"RTC_GPIO5" , type :"rtc" } ] ,
43+ note : "Apenas Entrada (Input Only). Sem resistores de pull-up/down internos."
44+ } ,
45+ {
46+ id : "D32" , side : "L" , pos : 5 ,
47+ func : [ { name :"GPIO32" , type :"gen" } , { name :"ADC1_CH4" , type :"ana" } , { name :"TOUCH9" , type :"tch" } , { name :"XTAL_P" , type :"rtc" } ] ,
48+ note : "Entrada/Saída. Conectado ao cristal de 32KHz (se presente). Funcional em Deep Sleep."
49+ } ,
50+ {
51+ id : "D33" , side : "L" , pos : 6 ,
52+ func : [ { name :"GPIO33" , type :"gen" } , { name :"ADC1_CH5" , type :"ana" } , { name :"TOUCH8" , type :"tch" } , { name :"XTAL_N" , type :"rtc" } ] ,
53+ note : "Entrada/Saída. Conectado ao cristal de 32KHz (se presente). Funcional em Deep Sleep."
54+ } ,
55+ {
56+ id : "D25" , side : "L" , pos : 7 ,
57+ func : [ { name :"GPIO25" , type :"gen" } , { name :"DAC_1" , type :"dac" } , { name :"ADC2_CH8" , type :"ana" } , { name :"RTC_GPIO6" , type :"rtc" } ] ,
58+ note : "DAC Verdadeiro (Conversor Digital-Analógico). Nota: ADC2 não funciona com Wi-Fi ativo."
59+ } ,
60+ {
61+ id : "D26" , side : "L" , pos : 8 ,
62+ func : [ { name :"GPIO26" , type :"gen" } , { name :"DAC_2" , type :"dac" } , { name :"ADC2_CH9" , type :"ana" } , { name :"RTC_GPIO7" , type :"rtc" } ] ,
63+ note : "DAC Verdadeiro (Conversor Digital-Analógico). Nota: ADC2 não funciona com Wi-Fi ativo."
64+ } ,
65+ {
66+ id : "D27" , side : "L" , pos : 9 ,
67+ func : [ { name :"GPIO27" , type :"gen" } , { name :"ADC2_CH7" , type :"ana" } , { name :"TOUCH7" , type :"tch" } , { name :"RTC_GPIO17" , type :"rtc" } ] ,
68+ note : "GPIO de uso geral. Nota: ADC2 não funciona com Wi-Fi ativo."
69+ } ,
70+ {
71+ id : "D14" , side : "L" , pos : 10 ,
72+ func : [ { name :"GPIO14" , type :"gen" } , { name :"HSPI_CLK" , type :"ser" } , { name :"ADC2_CH6" , type :"ana" } , { name :"TOUCH6" , type :"tch" } , { name :"JTAG_TMS" , type :"ser" } ] ,
73+ note : "Clock do HSPI. Sinal de depuração JTAG (TMS). Emite sinal PWM na inicialização."
74+ } ,
75+ {
76+ id : "D12" , side : "L" , pos : 11 , isStrapping : true ,
77+ func : [ { name :"GPIO12" , type :"gen" } , { name :"HSPI_MISO" , type :"ser" } , { name :"ADC2_CH5" , type :"ana" } , { name :"TOUCH5" , type :"tch" } , { name :"JTAG_TDI" , type :"ser" } ] ,
78+ note : "⚠️ STRAPPING PIN (Crítico): Define a voltagem da Flash (3.3V vs 1.8V). Se puxado para ALTO no boot, a placa pode não ligar (Brownout)."
79+ } ,
80+ {
81+ id : "D13" , side : "L" , pos : 12 ,
82+ func : [ { name :"GPIO13" , type :"gen" } , { name :"HSPI_MOSI" , type :"ser" } , { name :"ADC2_CH4" , type :"ana" } , { name :"TOUCH4" , type :"tch" } , { name :"JTAG_TCK" , type :"ser" } ] ,
83+ note : "Dados do HSPI. Sinal de depuração JTAG (TCK). ADC2 conflitante com Wi-Fi."
84+ } ,
85+ { id : "GND" , side : "L" , pos : 13 , func : [ { name :"GND" , type :"gnd" } ] , note : "Terra comum." } ,
86+ { id : "VIN" , side : "L" , pos : 14 , func : [ { name :"VIN" , type :"pwr" } ] , note : "Entrada de 5V. Passa pelo regulador AMS1117 para virar 3.3V. Aceita até ~9V (limite térmico)." } ,
87+ {
88+ id : "D23" , side : "R" , pos : 0 ,
89+ func : [ { name :"GPIO23" , type :"gen" } , { name :"VSPI_MOSI" , type :"ser" } ] ,
90+ note : "MOSI do barramento VSPI padrão. Usado para displays SPI e cartões SD."
91+ } ,
92+ {
93+ id : "D22" , side : "R" , pos : 1 ,
94+ func : [ { name :"GPIO22" , type :"gen" } , { name :"I2C_SCL" , type :"ser" } ] ,
95+ note : "Clock I2C padrão (Wire). Essencial para displays OLED e sensores I2C."
96+ } ,
97+ {
98+ id : "TX0" , side : "R" , pos : 2 ,
99+ func : [ { name :"GPIO1" , type :"gen" } , { name :"UART0_TX" , type :"ser" } ] ,
100+ note : "Saída Serial de Debug. Conectado ao chip USB. Não use se precisar do Monitor Serial."
101+ } ,
102+ {
103+ id : "RX0" , side : "R" , pos : 3 ,
104+ func : [ { name :"GPIO3" , type :"gen" } , { name :"UART0_RX" , type :"ser" } ] ,
105+ note : "Entrada Serial de Debug. Conectado ao chip USB. Fica em nível ALTO durante o boot."
106+ } ,
107+ {
108+ id : "D21" , side : "R" , pos : 4 ,
109+ func : [ { name :"GPIO21" , type :"gen" } , { name :"I2C_SDA" , type :"ser" } ] ,
110+ note : "Dados I2C padrão (Wire). Essencial para displays OLED e sensores I2C."
111+ } ,
112+ {
113+ id : "D19" , side : "R" , pos : 5 ,
114+ func : [ { name :"GPIO19" , type :"gen" } , { name :"VSPI_MISO" , type :"ser" } ] ,
115+ note : "MISO do barramento VSPI padrão. Usado para displays SPI e cartões SD."
116+ } ,
117+ {
118+ id : "D18" , side : "R" , pos : 6 ,
119+ func : [ { name :"GPIO18" , type :"gen" } , { name :"VSPI_CLK" , type :"ser" } ] ,
120+ note : "Clock do barramento VSPI padrão. Usado para displays SPI e cartões SD."
121+ } ,
122+ {
123+ id : "D5" , side : "R" , pos : 7 , isStrapping : true ,
124+ func : [ { name :"GPIO5" , type :"gen" } , { name :"VSPI_CS0" , type :"ser" } ] ,
125+ note : "Chip Select (CS) do VSPI. STRAPPING PIN: Gera sinal PWM no boot."
126+ } ,
127+ {
128+ id : "D17" , side : "R" , pos : 8 ,
129+ func : [ { name :"GPIO17" , type :"gen" } , { name :"UART2_TX" , type :"ser" } ] ,
130+ note : "Serial 2 TX. Frequentemente usado para módulos GPS ou SIM800L (HardwareSerial 2)."
131+ } ,
132+ {
133+ id : "D16" , side : "R" , pos : 9 ,
134+ func : [ { name :"GPIO16" , type :"gen" } , { name :"UART2_RX" , type :"ser" } ] ,
135+ note : "Serial 2 RX. Frequentemente usado para módulos GPS ou SIM800L (HardwareSerial 2)."
136+ } ,
137+ {
138+ id : "D4" , side : "R" , pos : 10 ,
139+ func : [ { name :"GPIO4" , type :"gen" } , { name :"ADC2_CH0" , type :"ana" } , { name :"TOUCH0" , type :"tch" } , { name :"HSPI_HD" , type :"ser" } ] ,
140+ note : "ADC2 (Conflito Wi-Fi). Em algumas placas, está ligado ao LED branco do flash ou cartão SD."
141+ } ,
142+ {
143+ id : "D2" , side : "R" , pos : 11 , isStrapping : true ,
144+ func : [ { name :"GPIO2" , type :"gen" } , { name :"ADC2_CH2" , type :"ana" } , { name :"TOUCH2" , type :"tch" } , { name :"HSPI_WP" , type :"ser" } ] ,
145+ note : "LED ONBOARD (Azul). STRAPPING PIN: Deve estar BAIXO ou flutuando p/ gravar código. Tem pull-down fraco."
146+ } ,
147+ {
148+ id : "D15" , side : "R" , pos : 12 , isStrapping : true ,
149+ func : [ { name :"GPIO15" , type :"gen" } , { name :"ADC2_CH3" , type :"ana" } , { name :"TOUCH3" , type :"tch" } , { name :"HSPI_CS0" , type :"ser" } , { name :"JTAG_TDO" , type :"ser" } ] ,
150+ note : "STRAPPING PIN: Se ALTO, silencia mensagens de boot. JTAG TDO. Tem pull-up fraco."
151+ } ,
152+ { id : "GND" , side : "R" , pos : 13 , func : [ { name :"GND" , type :"gnd" } ] , note : "Terra comum." } ,
153+ { id : "3V3" , side : "R" , pos : 14 , func : [ { name :"3V3" , type :"pwr" } ] , note : "Saída 3.3V do regulador. Máx ~600mA. Alimente sensores aqui." }
154+ ] ;
155+
156+ export default function Esp32Pinagem ( ) {
157+ const [ activePinId , setActivePinId ] = useState ( null ) ;
158+ const activePin = PIN_DEFINITIONS . find ( p => p . id === activePinId ) ;
159+
160+ const getPinType = ( pin ) => {
161+ if ( ! pin ) return '' ;
162+ if ( pin . id . startsWith ( 'GPIO' ) ) return pin . isInputOnly ? 'Input Only' : 'I/O Digital' ;
163+ if ( [ '3V3' , 'VIN' , 'GND' , 'EN' ] . includes ( pin . id ) ) return 'Power/Control' ;
164+ return 'Special' ;
165+ } ;
166+
167+ return (
168+ < div className = { styles . container } >
169+ < div className = { styles . workbench } >
170+ < svg className = { styles . boardSvg } viewBox = "0 0 480 680" xmlns = "http://www.w3.org/2000/svg" >
171+ < defs >
172+ < linearGradient id = "pcbGrad" x1 = "0%" y1 = "0%" x2 = "0%" y2 = "100%" >
173+ < stop offset = "0%" style = { { stopColor :'#1a2028' , stopOpacity :1 } } />
174+ < stop offset = "100%" style = { { stopColor :'#131920' , stopOpacity :1 } } />
175+ </ linearGradient >
176+ </ defs >
177+ < rect x = "110" y = "40" width = "260" height = "520" rx = "6" fill = "url(#pcbGrad)" stroke = "#1f2933" strokeWidth = "1.5" />
178+ < rect x = "140" y = "75" width = "200" height = "170" rx = "3" fill = "#0a0e14" stroke = "#1f2933" strokeWidth = "1" />
179+
180+ < text x = "240" y = "160" textAnchor = "middle" fill = "#52606d" fontFamily = "'Fira Code', monospace" fontWeight = "600" fontSize = "16" letterSpacing = "2" > ESP32</ text >
181+
182+ { PIN_DEFINITIONS . map ( pin => {
183+ const isLeft = pin . side === 'L' ;
184+ const xBase = isLeft ? 125 : 355 ;
185+ const yBase = 110 + ( pin . pos * 28 ) ;
186+ const isSelected = activePinId === pin . id ;
187+
188+ return (
189+ < g
190+ key = { pin . id }
191+ className = { `${ styles . pinGroup } ${ isSelected ? styles . selected : '' } ` }
192+ onClick = { ( ) => setActivePinId ( pin . id ) }
193+ >
194+ < rect x = { isLeft ? xBase - 12 : xBase } y = { yBase - 5 } width = "12" height = "10" rx = "2" className = { styles . pinConductor } />
195+
196+ < rect x = { isLeft ? xBase - 40 : xBase - 10 } y = { yBase - 14 } width = "50" height = "28" fill = "transparent" />
197+
198+ { /* Texto do Pino */ }
199+ < text x = { isLeft ? xBase - 18 : xBase + 18 } y = { yBase + 4 } textAnchor = { isLeft ? 'end' : 'start' } className = { styles . pinLabel } >
200+ { pin . id }
201+ </ text >
202+ </ g >
203+ ) ;
204+ } ) }
205+ </ svg >
206+ </ div >
207+
208+ < aside className = { styles . inspector } >
209+ < div className = { styles . inspectorHeader } >
210+ < span className = { styles . label } > Inspetor de Hardware</ span >
211+ </ div >
212+
213+ < div className = { styles . inspectorContent } >
214+ { ! activePin ? (
215+ < div className = { styles . emptyState } >
216+ < svg className = { styles . emptyIcon } viewBox = "0 0 24 24" fill = "none" strokeWidth = "1.5" stroke = "currentColor" >
217+ < circle cx = "12" cy = "12" r = "10" > </ circle >
218+ < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" > </ line >
219+ < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" > </ line >
220+ </ svg >
221+ < p > Clique em um pino da placa para ver detalhes técnicos.</ p >
222+ </ div >
223+ ) : (
224+ < >
225+ < div className = { styles . pinIdDisplay } > { activePin . id } </ div >
226+
227+ < div className = { styles . pinMeta } >
228+ < span > { getPinType ( activePin ) } </ span >
229+ { activePin . isStrapping && < span style = { { color : '#f59e0b' } } > • Strapping Pin</ span > }
230+ { activePin . isInputOnly && < span style = { { color : '#ef4444' } } > • Apenas Entrada</ span > }
231+ </ div >
232+
233+ < div className = { styles . detailSection } >
234+ < span className = { styles . label } > Funções Multiplexadas</ span >
235+ < div className = { styles . capabilitiesList } >
236+ { activePin . func . map ( ( f , i ) => {
237+ const sig = SIGNAL_TYPES [ f . type ] ;
238+ return (
239+ < span key = { i } className = { styles . capabilityBadge } style = { {
240+ borderColor : `${ sig . color } 44` ,
241+ color : sig . color ,
242+ background : `linear-gradient(90deg, ${ sig . color } 11, transparent)`
243+ } } >
244+ { f . name }
245+ </ span >
246+ ) ;
247+ } ) }
248+ </ div >
249+ </ div >
250+
251+ < div className = { styles . detailSection } >
252+ < span className = { styles . label } > Notas</ span >
253+ < div className = { styles . techNote } >
254+ { activePin . note }
255+ </ div >
256+ </ div >
257+ </ >
258+ ) }
259+ </ div >
260+
261+ < div className = { styles . legendFooter } >
262+ < span className = { styles . label } style = { { marginBottom :'10px' } } > Legenda de Sinais</ span >
263+ < div className = { styles . legendGrid } >
264+ { Object . entries ( SIGNAL_TYPES ) . map ( ( [ key , sig ] ) => (
265+ < div key = { key } className = { styles . legendItem } >
266+ < div className = { styles . legendSwatch } style = { { backgroundColor : sig . color } } > </ div >
267+ { sig . label . split ( ' ' ) [ 0 ] }
268+ </ div >
269+ ) ) }
270+ </ div >
271+ </ div >
272+ </ aside >
273+ </ div >
274+ ) ;
275+ }
0 commit comments