commit 4bc355581779dd712a4576c529a5b050ab9681a8 from: Ale date: Sun Mar 15 17:49:23 2026 UTC feat(3d): rediseñar escena 3D con materiales reales y layout corregido - Laser: cilindro D18x65mm metalico con anillo enfoque y lente roja - Soporte Neiko: base + columna + brazo articulado + pinza - ESP32 sobre protoboard como fuente 5V con cables a railes - Modulo jack ShillehTek entre MAX9814 y cable hacia PC - Laptop movida a X=72 (fuera de la caja) - BPW34 forzado a X < Cx=44 (siempre fuera de la caja) - Haz laser con efecto glow semitransparente - Protoboard con cuadricula de puntos y railes coloreados - bg pasado como parametro a setup_ax2 (fix variable scope) commit - f80919e8dfcbfba89f034d7912f86fbddbe24da2 commit + 4bc355581779dd712a4576c529a5b050ab9681a8 blob - 72e6e079375bb030552e2d4c12b4dbc53bf8e8d5 blob + 450215e1260b9130ac550e8a81deae98b41611e1 --- Scripts/simulacion_3d_laser.m +++ Scripts/simulacion_3d_laser.m @@ -1,8 +1,4 @@ -%% SIMULACION 3D — MICROFONO LASER -% Visualizacion 3D animada del experimento completo: -% Caja insonorizada → vidrio vibrante → laser → BPW34 → -% TIA (LM358) → MAX9814 → PC → FFT → reconstruccion -% +%% SIMULACION 3D — MICROFONO LASER (posiciones corregidas) % Autor: Alejandro B. E. — Fisica 2do Semestre clear; close all; clc; @@ -10,343 +6,478 @@ clear; close all; clc; fprintf('╔══════════════════════════════════════════════════════╗\n'); fprintf('║ SIMULACION 3D — Microfono Laser ║\n'); fprintf('╚══════════════════════════════════════════════════════╝\n\n'); -fprintf(' Presiona Q en la figura 3D para detener la animacion.\n\n'); +fprintf(' Presiona Q para detener la animacion.\n\n'); %% ═══════════════════════════════════════════════════════ -% PARAMETROS +% SEÑAL SIMULADA %% ═══════════════════════════════════════════════════════ +f1=440; f2=880; f3=660; +fs=8000; duracion=3.0; +t=(0:1/fs:duracion-1/fs)'; +N=length(t); -% Audio simulado (acorde La mayor: 440 + 880 + 660 Hz) -f1 = 440; f2 = 880; f3 = 660; -fs = 8000; % Hz -duracion = 3.0; % s +audio_original = 0.5*sin(2*pi*f1*t) + 0.3*sin(2*pi*f2*t) + 0.2*sin(2*pi*f3*t); +audio_original = audio_original / max(abs(audio_original)); -t = (0 : 1/fs : duracion - 1/fs)'; -N = length(t); +R_bpw34=0.3; P_laser=1e-3; mod_depth=0.15; Rf_TIA=10e3; Av_MAX=1; +P_luz = P_laser*(1+mod_depth*audio_original); +I_foto = R_bpw34*P_luz + 1e-8*randn(N,1); +V_tia = I_foto*Rf_TIA; V_tia=V_tia-mean(V_tia); +V_max = max(-1.65,min(1.65,Av_MAX*V_tia)); -% Senal de audio dentro de la caja (normalizada -1 a 1) -audio_original = 0.5*sin(2*pi*f1*t) + ... - 0.3*sin(2*pi*f2*t) + ... - 0.2*sin(2*pi*f3*t); -audio_original = audio_original / max(abs(audio_original)); % normalizar +Y=fft(V_max); mag_Y=abs(Y); +mascara=mag_Y>max(mag_Y)*0.08; mascara=mascara|flipud(mascara); +V_rec=real(ifft(Y.*mascara)); +factor=(audio_original'*V_rec)/(V_rec'*V_rec+1e-12); +V_rec_escalado=V_rec*factor; +cc=corrcoef(audio_original,V_rec_escalado); rho=cc(1,2); -% Parametros fisicos -R_bpw34 = 0.3; % A/W — responsividad BPW34 @ 650nm -P_laser = 1e-3; % W — potencia laser -mod_depth = 0.15; % antes 0.4, — — profundidad de modulacion del vidrio -Rf_TIA = 10e3; % Ω — resistencia TIA -Av_MAX = 1; % antes 3, V/V — ganancia MAX9814 +fprintf(' Frecuencias: %.0f + %.0f + %.0f Hz\n',f1,f2,f3); +fprintf(' Correlacion: %.4f\n\n',rho); -%% ─── PIPELINE DE SENAL (CORREGIDO) ───────────────────── - -% 1. Modulacion optica: vibracion del vidrio modula P_laser -P_luz = P_laser * (1 + mod_depth * audio_original); -% P_luz oscila entre P_laser*(1-m) y P_laser*(1+m) — nunca negativo - -% 2. BPW34: P_luz → I_foto (corriente) -I_foto = R_bpw34 * P_luz + 1e-8 * randn(N,1); -% I_foto_DC = R * P_laser = 0.3 * 1e-3 = 300 µA (offset DC) -% I_foto_AC = R * P_laser * mod_depth * audio = ±120 µA (señal util) - -% 3. TIA: I_foto → V_tia, luego ELIMINAR DC por resta de media -% (en hardware esto lo hace el capacitor de acoplamiento C_ac) -V_tia_total = I_foto * Rf_TIA; % V = I * Rf → offset DC + señal AC -V_tia = V_tia_total - mean(V_tia_total); % solo componente AC -% V_tia_AC pico = mod_depth * R * P_laser * Rf = 0.4*0.3*1e-3*10e3 = 1.2 mV -% Nota: señal pequeña — el MAX9814 la amplifica - -% 4. MAX9814: amplificar y saturar -V_max = Av_MAX * V_tia; -V_max = max(-1.65, min(1.65, V_max)); % saturacion ±1.65V - -% 5. FFT sobre la señal capturada -Y = fft(V_max); -mag_Y = abs(Y); - -% Filtrado: umbral de magnitud (conservar picos principales) -umbral = max(mag_Y) * 0.08; -mascara = mag_Y > umbral; -% Simetria conjugada obligatoria para ifft real -mascara = mascara | flipud(mascara); -Y_filt = Y .* mascara; - -% 6. Reconstruccion (IFFT) -V_rec = real(ifft(Y_filt)); - -% Escalar V_rec para comparar con audio_original (minimos cuadrados) -factor = (audio_original' * V_rec) / (V_rec' * V_rec + 1e-12); -V_rec_escalado = V_rec * factor; - -% Correlacion -cc = corrcoef(audio_original, V_rec_escalado); -rho = cc(1,2); - -fprintf(' Senal simulada:\n'); -fprintf(' Frecuencias: %.0f + %.0f + %.0f Hz\n', f1, f2, f3); -fprintf(' I_foto DC: %.0f uA\n', mean(I_foto)*1e6); -fprintf(' V_TIA AC pico: %.4f V\n', max(abs(V_tia))); -fprintf(' V_MAX pico: %.4f V\n', max(abs(V_max))); -fprintf(' Correlacion: %.4f\n\n', rho); - %% ═══════════════════════════════════════════════════════ -% FIGURA PRINCIPAL +% LAYOUT (vista superior): +% +% Y +% ^ +% | [Protoboard+ESP32+LM358+MAX9814+Jack] [BPW34] [CAJA] [Laptop] +% | X=0..22 X=30..35 X=44..66 X=72..83 +% └──────────────────────────────────────────────────────────────────────> X +% +% El laser (sobre soporte Neiko) apunta desde X~27 en angulo 30° al vidrio (X=44) +% La reflexion va hacia el BPW34 (X~31) %% ═══════════════════════════════════════════════════════ -fig = figure('Name','Simulacion 3D — Microfono Laser', ... - 'NumberTitle','off', ... - 'Position',[30 30 1500 900], ... - 'Color',[0.05 0.05 0.08], ... - 'KeyPressFcn', @(s,e) setappdata(s,'salir', strcmp(e.Key,'q'))); -setappdata(fig, 'salir', false); -%% ═══════════════════════════════════════════════════════ -% SUBPLOT 3D -%% ═══════════════════════════════════════════════════════ -ax3d = subplot('Position', [0.02 0.35 0.55 0.62]); -set(ax3d,'Color',[0.05 0.05 0.08],'XColor','w','YColor','w','ZColor','w'); +bg=[0.04 0.04 0.06]; + +fig=figure('Name','Simulacion 3D — Microfono Laser',... + 'NumberTitle','off','Position',[20 20 1600 950],... + 'Color',bg,... + 'KeyPressFcn',@(s,e) setappdata(s,'salir',strcmp(e.Key,'q'))); +setappdata(fig,'salir',false); + +ax3d=subplot('Position',[0.01 0.32 0.65 0.66]); +set(ax3d,'Color',bg,'XColor',[0.5 0.5 0.5],... + 'YColor',[0.5 0.5 0.5],'ZColor',[0.5 0.5 0.5],'GridAlpha',0.12); hold(ax3d,'on'); grid(ax3d,'on'); -view(ax3d, 35, 22); -xlabel(ax3d,'X (cm)','Color','w'); -ylabel(ax3d,'Y (cm)','Color','w'); -zlabel(ax3d,'Z (cm)','Color','w'); -title(ax3d,'Montaje experimental 3D','Color',[1 0.7 0.1],'FontWeight','bold','FontSize',12); -ax3d.GridColor = [0.2 0.2 0.2]; -xlim(ax3d,[-2 58]); ylim(ax3d,[-3 38]); zlim(ax3d,[-1 33]); +view(ax3d,38,26); +xlabel(ax3d,'X (cm)','Color',[0.55 0.55 0.55],'FontSize',8); +ylabel(ax3d,'Y (cm)','Color',[0.55 0.55 0.55],'FontSize',8); +zlabel(ax3d,'Z (cm)','Color',[0.55 0.55 0.55],'FontSize',8); +title(ax3d,'Montaje experimental — Microfono Laser',... + 'Color',[1 0.75 0.15],'FontWeight','bold','FontSize',13); +ax3d.GridColor=[0.14 0.14 0.14]; +xlim(ax3d,[-3 90]); ylim(ax3d,[-5 38]); zlim(ax3d,[-1 36]); lighting(ax3d,'gouraud'); -light(ax3d,'Position',[60 60 60],'Style','infinite'); +light(ax3d,'Position',[90 80 80],'Style','infinite','Color',[1 1 1]); +light(ax3d,'Position',[0 0 40],'Style','infinite','Color',[0.3 0.3 0.4]); -% Helper: dibujar caja - function dibujar_caja(ax,x0,y0,z0,Lx,Ly,Lz,col,al) - verts = [x0 y0 z0; - x0+Lx y0 z0; - x0+Lx y0+Ly z0; - x0 y0+Ly z0; - x0 y0 z0+Lz; - x0+Lx y0 z0+Lz; - x0+Lx y0+Ly z0+Lz; - x0 y0+Ly z0+Lz]; - faces = [1 2 6 5; 2 3 7 6; 3 4 8 7; - 4 1 5 8; 1 2 3 4; 5 6 7 8]; - patch(ax,'Vertices',verts,'Faces',faces, ... - 'FaceColor',col,'FaceAlpha',al, ... - 'EdgeColor',[0.55 0.55 0.55],'LineWidth',0.7); + function dibujar_caja(ax,x0,y0,z0,Lx,Ly,Lz,col,al,ec) + if nargin<10, ec=[0.55 0.55 0.55]; end + verts=[x0 y0 z0; x0+Lx y0 z0; x0+Lx y0+Ly z0; x0 y0+Ly z0; + x0 y0 z0+Lz; x0+Lx y0 z0+Lz; x0+Lx y0+Ly z0+Lz; x0 y0+Ly z0+Lz]; + faces=[1 2 6 5;2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; + patch(ax,'Vertices',verts,'Faces',faces,'FaceColor',col,'FaceAlpha',al,... + 'EdgeColor',ec,'LineWidth',0.8); end -Lc = 20; % tamaño caja (cm) + function etiqueta(ax,x,y,z,txt,col,sz) + if nargin<7, sz=8.5; end + text(ax,x,y,z,txt,'Color',col,'FontSize',sz,'FontWeight','bold',... + 'HorizontalAlignment','center','FontName','Helvetica'); + end -% Caja insonorizada -dibujar_caja(ax3d, 0,0,0, Lc,Lc,Lc, [0.35 0.25 0.15], 0.22); -text(ax3d, Lc/2, Lc/2, Lc+1.5,'Caja insonorizada', ... - 'Color',[0.85 0.65 0.3],'FontSize',9,'HorizontalAlignment','center'); +%% ───────────────────────────────────────────────────────── +% COORDENADAS CLAVE +%% ───────────────────────────────────────────────────────── +% Caja insonorizada (centro-derecha) +Lc=22; Cx=44; Cy=5; Cz=0; -% Vidrio (cara x=Lc) -[yv,zv] = meshgrid(linspace(0.5,Lc-0.5,12), linspace(0.5,Lc-0.5,12)); -xv0 = Lc * ones(size(yv)); -h_vidrio = surf(ax3d, xv0, yv, zv, ... - 'FaceColor',[0.5 0.8 1.0],'FaceAlpha',0.28, ... - 'EdgeColor',[0.4 0.7 0.9],'EdgeAlpha',0.12); -text(ax3d, Lc+0.3, Lc/2, Lc+0.8,'Vidrio', ... - 'Color',[0.5 0.9 1.0],'FontSize',9); +% Protoboard (izquierda, bien separada de la caja) +Px=0; Py=12; Pz=0; Pw=22; Pd=11; Ph=0.6; -% Audifono dentro de la caja -th = linspace(0,2*pi,40); -for lado = [-1 1] - yc = Lc/2 + lado*5; - fill3(ax3d, Lc/2-0.3+zeros(1,40), ... - yc + 3*cos(th), ... - Lc/2 + 3*sin(th), ... - [0.2 0.2 0.2],'FaceAlpha',0.85,'EdgeColor',[0.5 0.5 0.5]); +% Soporte Neiko (entre protoboard y caja) +Nx=27; Ny=3; Nz=0; + +% Laser (sobre el soporte) +laser_pos=[30, 6, 11]; + +% Punto de impacto en el vidrio (cara izquierda de la caja, x=Cx) +P_imp=[Cx, Cy+11, Cz+11]; + +% Laptop (derecha de la caja, bien separada) +LPx=72; LPy=8; LPz=0; + +%% ───────────────────────────────────────────────────────── +% CAJA INSONORIZADA +%% ───────────────────────────────────────────────────────── +dibujar_caja(ax3d,Cx,Cy,Cz,Lc,Lc,Lc,[0.28 0.20 0.12],0.16,[0.55 0.42 0.28]); +% Aristas +for xi=[Cx Cx+Lc] + for yi=[Cy Cy+Lc] + plot3(ax3d,[xi xi],[yi yi],[Cz Cz+Lc],... + 'Color',[0.55 0.42 0.28],'LineWidth',1.2); + end end -text(ax3d, Lc/2-5, Lc/2, Lc/2+5.5,'Audifono', ... - 'Color',[0.7 0.7 0.7],'FontSize',8); +etiqueta(ax3d,Cx+Lc/2,Cy+Lc/2,Cz+Lc+2,'CAJA INSONORIZADA',[0.88 0.68 0.3],9); -% Modulo laser KY-008 -laser_pos = [35, 4, 10]; -[xl,yl,zl] = cylinder(0.8,20); -surf(ax3d, xl*3+laser_pos(1), yl+laser_pos(2), zl+laser_pos(3), ... - 'FaceColor',[0.15 0.65 0.15],'EdgeColor','none','FaceAlpha',0.92); -text(ax3d, laser_pos(1)+0.5, laser_pos(2)-0.5, laser_pos(3)-2.2,'Laser KY-008', ... - 'Color',[0.3 1.0 0.3],'FontSize',8,'FontWeight','bold'); +% Vidrio (cara izquierda x=Cx) +[yv,zv]=meshgrid(linspace(Cy+0.5,Cy+Lc-0.5,14),linspace(Cz+0.5,Cz+Lc-0.5,14)); +xv0=Cx*ones(size(yv)); +h_vidrio=surf(ax3d,xv0,yv,zv,... + 'FaceColor',[0.5 0.82 1.0],'FaceAlpha',0.22,... + 'EdgeColor',[0.4 0.7 0.95],'EdgeAlpha',0.18); +etiqueta(ax3d,Cx-0.8,Cy+Lc/2,Cz+Lc+1,'Vidrio ~2mm',[0.5 0.9 1.0],8); -% Punto de impacto en vidrio -P_imp = [Lc, 10, 10]; +% Audifono (dentro de la caja) +th=linspace(0,2*pi,40); +for lado=[-1 1] + yc=Cy+Lc/2+lado*5.5; + fill3(ax3d,Cx+Lc/2-0.2+zeros(1,40),yc+3.5*cos(th),Cz+Lc/2+3.5*sin(th),... + [0.18 0.18 0.18],'FaceAlpha',0.88,'EdgeColor',[0.45 0.45 0.45]); + fill3(ax3d,Cx+Lc/2-0.1+zeros(1,40),yc+2*cos(th),Cz+Lc/2+2*sin(th),... + [0.07 0.07 0.07],'FaceAlpha',0.95,'EdgeColor','none'); +end +etiqueta(ax3d,Cx+Lc/2+4,Cy+Lc/2,Cz+Lc/2+8.5,'Audifono',[0.62 0.62 0.62],7.5); -% Haz laser (rojo solido) -h_haz_ida = plot3(ax3d, ... - [laser_pos(1) P_imp(1)], ... - [laser_pos(2) P_imp(2)], ... - [laser_pos(3) P_imp(3)], ... - 'r-','LineWidth',2.5); +%% ───────────────────────────────────────────────────────── +% SOPORTE NEIKO +%% ───────────────────────────────────────────────────────── +% Base +dibujar_caja(ax3d,Nx-3,Ny-2,Nz,6,5,0.8,[0.22 0.22 0.22],0.95,[0.38 0.38 0.38]); +% Columna +[xc2,yc2,zc2]=cylinder(0.5,16); +surf(ax3d,xc2+Nx,yc2+Ny+0.5,zc2*10+Nz+0.8,... + 'FaceColor',[0.36 0.36 0.39],'EdgeColor','none','FaceAlpha',0.95); +% Brazo + articulacion +plot3(ax3d,[Nx Nx+3],[Ny+0.5 Ny+0.5],[Nz+10 Nz+10],... + 'Color',[0.42 0.42 0.44],'LineWidth',4); +[xs,ys,zs]=sphere(10); +surf(ax3d,xs*0.65+Nx+3,ys*0.65+Ny+0.5,zs*0.65+Nz+10,... + 'FaceColor',[0.5 0.5 0.52],'EdgeColor','none','FaceAlpha',0.9); +plot3(ax3d,[Nx+3 laser_pos(1)],[Ny+0.5 laser_pos(2)],[Nz+10 laser_pos(3)],... + 'Color',[0.42 0.42 0.44],'LineWidth',3); +etiqueta(ax3d,Nx,Ny-3.5,Nz+0.5,'Soporte Neiko',[0.58 0.58 0.58],7.5); -% Reflexion hacia BPW34 -v_inc = (P_imp - laser_pos) / norm(P_imp - laser_pos); -n_vid = [-1 0 0]; -v_ref = v_inc - 2*dot(v_inc,n_vid)*n_vid; -bpw34_pos = P_imp + 12*v_ref; +%% ───────────────────────────────────────────────────────── +% LASER INDUSTRIAL D18x65mm +%% ───────────────────────────────────────────────────────── +[xl,yl,zl]=cylinder([0.95 0.9],24); +surf(ax3d,xl+laser_pos(1),yl+laser_pos(2),zl*7+laser_pos(3)-3.5,... + 'FaceColor',[0.72 0.72 0.76],'EdgeColor',[0.5 0.5 0.52],... + 'FaceAlpha',0.97,'EdgeAlpha',0.18); +% Anillo de enfoque +[xr,yr,zr]=cylinder([1.05 0.95],24); +surf(ax3d,xr+laser_pos(1),yr+laser_pos(2),zr*1.2+laser_pos(3)+3.2,... + 'FaceColor',[0.14 0.14 0.14],'EdgeColor','none','FaceAlpha',0.97); +% Lente roja + brillo +th_l=linspace(0,2*pi,30); +fill3(ax3d,0.65*cos(th_l)+laser_pos(1),0.65*sin(th_l)+laser_pos(2),... + zeros(1,30)+laser_pos(3)+4.3,... + [0.85 0.08 0.08],'FaceAlpha',0.9,'EdgeColor',[1 0.3 0.3],'LineWidth',0.8); +fill3(ax3d,0.18*cos(th_l)+laser_pos(1)-0.18,0.18*sin(th_l)+laser_pos(2)-0.18,... + zeros(1,30)+laser_pos(3)+4.35,... + [1 0.7 0.7],'FaceAlpha',0.55,'EdgeColor','none'); -h_haz_ref = plot3(ax3d, ... - [P_imp(1) bpw34_pos(1)], ... - [P_imp(2) bpw34_pos(2)], ... - [P_imp(3) bpw34_pos(3)], ... +etiqueta(ax3d,laser_pos(1),laser_pos(2)-2.5,laser_pos(3)-4.5,... + 'Laser 650nm 5mW',[0.28 1.0 0.28],8.5); +etiqueta(ax3d,laser_pos(1),laser_pos(2)-2.5,laser_pos(3)-5.8,... + 'D18x65mm enfocable',[0.22 0.75 0.22],7); + +% Cable laser → protoboard (dupont) +plot3(ax3d,[laser_pos(1) Px+Pw-2],... + [laser_pos(2) Py+5],... + [laser_pos(3)-3.5 Pz+Ph],... + 'Color',[1 0.5 0.1],'LineWidth',1.2,'LineStyle',':'); + +%% ───────────────────────────────────────────────────────── +% HAZ LASER + GLOW + REFLEXION +%% ───────────────────────────────────────────────────────── +% Glow ancho +h_glow=plot3(ax3d,... + [laser_pos(1) P_imp(1)],... + [laser_pos(2) P_imp(2)],... + [laser_pos(3) P_imp(3)],... + '-','Color',[1 0.12 0.12],'LineWidth',9); +h_glow.Color(4)=0.07; + +% Haz principal +h_haz_ida=plot3(ax3d,... + [laser_pos(1) P_imp(1)],... + [laser_pos(2) P_imp(2)],... + [laser_pos(3) P_imp(3)],... + 'r-','LineWidth',2); + +% Reflexion especular +v_inc=(P_imp-laser_pos)/norm(P_imp-laser_pos); +n_vid=[-1 0 0]; +v_ref=v_inc-2*dot(v_inc,n_vid)*n_vid; +bpw34_pos=P_imp+13*v_ref; +% Forzar BPW34 fuera de la caja (x < Cx) +if bpw34_pos(1) >= Cx, bpw34_pos(1)=Cx-5; end + +h_glow_ref=plot3(ax3d,... + [P_imp(1) bpw34_pos(1)],... + [P_imp(2) bpw34_pos(2)],... + [P_imp(3) bpw34_pos(3)],... + '-','Color',[1 0.3 0.3],'LineWidth',5); +h_glow_ref.Color(4)=0.09; + +h_haz_ref=plot3(ax3d,... + [P_imp(1) bpw34_pos(1)],... + [P_imp(2) bpw34_pos(2)],... + [P_imp(3) bpw34_pos(3)],... 'r--','LineWidth',1.8); % Punto de impacto -plot3(ax3d, P_imp(1),P_imp(2),P_imp(3),'y*','MarkerSize',12,'LineWidth',2); +plot3(ax3d,P_imp(1),P_imp(2),P_imp(3),'o',... + 'MarkerSize',18,'MarkerFaceColor',[1 0.9 0.15],... + 'MarkerEdgeColor',[1 1 0.5],'LineWidth',1); +plot3(ax3d,P_imp(1),P_imp(2),P_imp(3),'*',... + 'MarkerSize',10,'Color',[1 1 0.25],'LineWidth',1.5); -% BPW34 (caja negra) -dibujar_caja(ax3d, bpw34_pos(1)-1.2, bpw34_pos(2)-1.2, bpw34_pos(3)-1.2, ... - 2.4, 2.4, 2.4, [0.08 0.08 0.08], 0.92); -text(ax3d, bpw34_pos(1), bpw34_pos(2), bpw34_pos(3)+3.2,'BPW34', ... - 'Color',[1.0 0.85 0.1],'FontSize',9,'FontWeight','bold','HorizontalAlignment','center'); +%% ───────────────────────────────────────────────────────── +% BPW34 + TUBO NEGRO (claramente fuera de la caja) +%% ───────────────────────────────────────────────────────── +% Verificar que bpw34_pos este fuera de la caja +fprintf(' BPW34 pos: [%.1f, %.1f, %.1f] — caja inicia en X=%.0f\n',... + bpw34_pos(1),bpw34_pos(2),bpw34_pos(3),Cx); -% Tubo negro (proteccion de luz ambiente) -[xt,yt,zt] = cylinder(1.5,20); -surf(ax3d, xt+bpw34_pos(1), yt+bpw34_pos(2), zt*5+bpw34_pos(3)-2.5, ... - 'FaceColor',[0.07 0.07 0.07],'EdgeColor','none','FaceAlpha',0.55); +dibujar_caja(ax3d,bpw34_pos(1)-1.4,bpw34_pos(2)-1.4,bpw34_pos(3)-1.4,... + 2.8,2.8,2.8,[0.06 0.06 0.06],0.95,[0.28 0.28 0.28]); +% Ventana azul (cara apuntando al laser) +fill3(ax3d,... + [bpw34_pos(1)+1.4 bpw34_pos(1)+1.4 bpw34_pos(1)+1.4 bpw34_pos(1)+1.4],... + [bpw34_pos(2)-1.2 bpw34_pos(2)+1.2 bpw34_pos(2)+1.2 bpw34_pos(2)-1.2],... + [bpw34_pos(3)-1.2 bpw34_pos(3)-1.2 bpw34_pos(3)+1.2 bpw34_pos(3)+1.2],... + [0.18 0.55 1.0],'FaceAlpha',0.75,'EdgeColor',[0.3 0.65 1.0],'LineWidth',1); +% Tubo negro +[xt,yt,zt]=cylinder(1.6,20); +surf(ax3d,xt+bpw34_pos(1),yt+bpw34_pos(2),zt*5.5+bpw34_pos(3)-2.8,... + 'FaceColor',[0.06 0.06 0.06],'EdgeColor','none','FaceAlpha',0.58); -% Protoboard + LM358 TIA -proto = [37, 14, 4]; -dibujar_caja(ax3d, proto(1), proto(2), proto(3), 9, 5, 0.6, [0.1 0.5 0.1], 0.85); -text(ax3d, proto(1)+4.5, proto(2)+2.5, proto(3)+2,'LM358 TIA', ... - 'Color',[0.4 1.0 0.4],'FontSize',8,'HorizontalAlignment','center'); +etiqueta(ax3d,bpw34_pos(1),bpw34_pos(2),bpw34_pos(3)+4.8,... + 'BPW34',[1.0 0.85 0.1],10.5); +etiqueta(ax3d,bpw34_pos(1),bpw34_pos(2),bpw34_pos(3)+3.4,... + 'Fotodiodo PIN',[0.78 0.65 0.08],7.5); -% Cable BPW34 → TIA -plot3(ax3d,[bpw34_pos(1) proto(1)+4], ... - [bpw34_pos(2) proto(2)+2], ... - [bpw34_pos(3) proto(3)+0.5], ... - 'Color',[1 0.55 0.1],'LineWidth',1.5,'LineStyle',':'); +% Cable BPW34 → protoboard +plot3(ax3d,[bpw34_pos(1) Px+Pw-1],... + [bpw34_pos(2) Py+7],... + [bpw34_pos(3) Pz+Ph],... + 'Color',[1 0.62 0.1],'LineWidth',1.5,'LineStyle',':'); -% MAX9814 -maxp = [37, 21, 4]; -dibujar_caja(ax3d, maxp(1), maxp(2), maxp(3), 7, 4, 1.2, [0.45 0.1 0.55], 0.88); -text(ax3d, maxp(1)+3.5, maxp(2)+2, maxp(3)+2.8,'MAX9814', ... - 'Color',[0.9 0.5 1.0],'FontSize',8,'HorizontalAlignment','center'); +%% ───────────────────────────────────────────────────────── +% PROTOBOARD 830 PUNTOS +%% ───────────────────────────────────────────────────────── +dibujar_caja(ax3d,Px,Py,Pz,Pw,Pd,Ph,[0.10 0.52 0.10],0.92,[0.08 0.42 0.08]); +% Puntos de la protoboard +for xi2=linspace(Px+1.5,Px+Pw-1.5,9) + for yi2=linspace(Py+1.5,Py+Pd-1.5,5) + plot3(ax3d,xi2,yi2,Pz+Ph+0.05,'.',... + 'Color',[0.07 0.33 0.07],'MarkerSize',3.5); + end +end +% Railes +plot3(ax3d,[Px Px+Pw],[Py+0.7 Py+0.7],[Pz+Ph+0.1 Pz+Ph+0.1],... + 'Color',[0.95 0.22 0.22],'LineWidth',3.5); +plot3(ax3d,[Px Px+Pw],[Py+Pd-0.7 Py+Pd-0.7],[Pz+Ph+0.1 Pz+Ph+0.1],... + 'Color',[0.32 0.32 0.95],'LineWidth',3.5); +text(ax3d,Px-0.8,Py+0.7,Pz+Ph+0.6,'+5V',... + 'Color',[0.95 0.28 0.28],'FontSize',7.5,'FontWeight','bold'); +text(ax3d,Px-0.8,Py+Pd-0.7,Pz+Ph+0.6,'GND',... + 'Color',[0.38 0.38 0.95],'FontSize',7.5,'FontWeight','bold'); +etiqueta(ax3d,Px+Pw/2,Py-2.8,Pz+0.5,'Protoboard 830 pts',[0.32 0.82 0.32],8.5); -% Cable TIA → MAX9814 -plot3(ax3d,[proto(1)+4 maxp(1)+3], ... - [proto(2)+5 maxp(2)], ... - [proto(3)+0.5 maxp(3)+0.6], ... - 'Color',[1 0.55 0.1],'LineWidth',1.5,'LineStyle',':'); +%% ───────────────────────────────────────────────────────── +% ESP32 (fuente 5V) +%% ───────────────────────────────────────────────────────── +Ex=Px+1; Ey=Py+1.5; Ez=Pz+Ph; +dibujar_caja(ax3d,Ex,Ey,Ez,5.5,2.2,0.9,[0.08 0.28 0.52],0.95,[0.12 0.42 0.72]); +dibujar_caja(ax3d,Ex+1.5,Ey+0.4,Ez+0.9,2.2,1.3,0.5,[0.10 0.10 0.10],0.95,[0.28 0.28 0.28]); +dibujar_caja(ax3d,Ex-0.35,Ey+0.55,Ez+0.25,0.6,1.1,0.45,[0.28 0.28 0.28],0.9,[0.4 0.4 0.4]); +etiqueta(ax3d,Ex+2.75,Ey+1.1,Ez+1.9,'ESP32',[0.28 0.72 1.0],8.5); +etiqueta(ax3d,Ex+2.75,Ey+1.1,Ez+2.9,'Fuente 5V',[0.2 0.55 0.82],7); +% Cables a railes +plot3(ax3d,[Ex+1 Px+2],[Ey Py+0.7],[Ez Pz+Ph+0.15],... + 'Color',[0.95 0.22 0.22],'LineWidth',2); +plot3(ax3d,[Ex+4 Px+4],[Ey Py+Pd-0.7],[Ez Pz+Ph+0.15],... + 'Color',[0.32 0.32 0.95],'LineWidth',2); +% USB saliendo +plot3(ax3d,[Ex-0.35 Ex-4],[Ey+0.6 Ey+0.6],[Ez+0.45 Ez+0.45],... + 'Color',[0.52 0.52 0.52],'LineWidth',2.5); +text(ax3d,Ex-5,Ey+0.6,Ez+1,'USB','Color',[0.5 0.5 0.5],'FontSize',7,... + 'HorizontalAlignment','center'); -% Laptop -pcp = [46, 14, 4]; -% Pantalla -fill3(ax3d,[pcp(1) pcp(1)+9 pcp(1)+9 pcp(1)], ... - [pcp(2) pcp(2) pcp(2) pcp(2)], ... - [pcp(3) pcp(3) pcp(3)+8 pcp(3)+8], ... - [0.1 0.1 0.16],'EdgeColor',[0.5 0.5 0.5],'FaceAlpha',0.92); -fill3(ax3d,[pcp(1)+0.5 pcp(1)+8.5 pcp(1)+8.5 pcp(1)+0.5], ... - [pcp(2)-0.1 pcp(2)-0.1 pcp(2)-0.1 pcp(2)-0.1], ... - [pcp(3)+0.5 pcp(3)+0.5 pcp(3)+7.5 pcp(3)+7.5], ... - [0.05 0.3 0.4],'EdgeColor','none','FaceAlpha',0.85); -% Base -fill3(ax3d,[pcp(1) pcp(1)+9 pcp(1)+9 pcp(1)], ... - [pcp(2) pcp(2) pcp(2)+4 pcp(2)+4], ... - [pcp(3) pcp(3) pcp(3) pcp(3)], ... - [0.2 0.2 0.2],'EdgeColor',[0.5 0.5 0.5],'FaceAlpha',0.92); -text(ax3d, pcp(1)+4.5, pcp(2)-1.2, pcp(3)+4,'PC + MATLAB', ... - 'Color',[0.3 0.85 1.0],'FontSize',9,'FontWeight','bold','HorizontalAlignment','center'); +%% ───────────────────────────────────────────────────────── +% LM358 TIA +%% ───────────────────────────────────────────────────────── +Lx=Px+8; Ly=Py+1.8; Lz=Pz+Ph; +dibujar_caja(ax3d,Lx,Ly,Lz,2.8,3.4,1.2,[0.08 0.08 0.12],0.95,[0.22 0.22 0.32]); +for pi_i=1:4 + plot3(ax3d,[Lx-0.2 Lx],[Ly+0.4+pi_i*0.55 Ly+0.4+pi_i*0.55],[Lz+0.3 Lz+0.3],... + 'Color',[0.72 0.72 0.72],'LineWidth',0.9); + plot3(ax3d,[Lx+2.8 Lx+3.0],[Ly+0.4+pi_i*0.55 Ly+0.4+pi_i*0.55],[Lz+0.3 Lz+0.3],... + 'Color',[0.72 0.72 0.72],'LineWidth',0.9); +end +etiqueta(ax3d,Lx+1.4,Ly+1.7,Lz+2.1,'LM358',[0.38 1.0 0.38],8.5); +etiqueta(ax3d,Lx+1.4,Ly+1.7,Lz+3.1,'TIA',[0.28 0.82 0.28],7.5); +plot3(ax3d,[Lx+1.4 Lx+1.4],[Ly Py+0.7],[Lz Pz+Ph+0.15],... + 'Color',[0.95 0.22 0.22],'LineWidth',1,'LineStyle',':'); +plot3(ax3d,[Lx+1.4 Lx+1.4],[Ly+3.4 Py+Pd-0.7],[Lz Pz+Ph+0.15],... + 'Color',[0.32 0.32 0.95],'LineWidth',1,'LineStyle',':'); -% Cable MAX9814 → PC -plot3(ax3d,[maxp(1)+7 pcp(1)], ... - [maxp(2)+2 pcp(2)+2], ... - [maxp(3)+0.6 pcp(3)+0.5], ... - 'Color',[0.7 0.7 0.7],'LineWidth',2); +%% ───────────────────────────────────────────────────────── +% MAX9814 +%% ───────────────────────────────────────────────────────── +Mx=Px+13; My=Py+1.8; Mz=Pz+Ph; +dibujar_caja(ax3d,Mx,My,Mz,4.5,3.5,1.5,[0.40 0.08 0.52],0.92,[0.65 0.15 0.82]); +etiqueta(ax3d,Mx+2.25,My+1.75,Mz+2.3,'MAX9814',[0.9 0.5 1.0],8.5); +etiqueta(ax3d,Mx+2.25,My+1.75,Mz+3.3,'AGC 40dB',[0.72 0.35 0.88],7.5); +% Cable LM358 → MAX9814 +plot3(ax3d,[Lx+2.8 Mx],[Ly+1.7 My+1.75],[Lz+0.6 Mz+0.6],... + 'Color',[1 0.62 0.1],'LineWidth',2,'LineStyle',':'); -% Leyenda -legend(ax3d,[h_haz_ida,h_haz_ref], ... - {'Haz laser (650nm)','Reflexion hacia BPW34'}, ... - 'Location','northeast','TextColor','w', ... - 'Color',[0.1 0.1 0.15],'EdgeColor',[0.4 0.4 0.4]); +%% ───────────────────────────────────────────────────────── +% MODULO JACK 3.5mm ShillehTek +%% ───────────────────────────────────────────────────────── +Jx=Px+Pw-3.8; Jy=Py+2.2; Jz=Pz+Ph; +dibujar_caja(ax3d,Jx,Jy,Jz,3.2,2.8,1.0,[0.08 0.38 0.12],0.95,[0.15 0.62 0.22]); +[xj2,yj2,zj2]=cylinder(0.68,16); +surf(ax3d,xj2*0.68+Jx+1.6,yj2*0.68+Jy-0.68,zj2*1.2+Jz+0.4,... + 'FaceColor',[0.28 0.28 0.28],'EdgeColor','none','FaceAlpha',0.9); +etiqueta(ax3d,Jx+1.6,Jy+1.4,Jz+2.2,'Jack 3.5mm',[0.32 0.88 0.45],8); +etiqueta(ax3d,Jx+1.6,Jy+1.4,Jz+3.2,'ShillehTek',[0.22 0.65 0.32],7); +% Cable MAX9814 → Jack +plot3(ax3d,[Mx+4.5 Jx],[My+1.75 Jy+1.4],[Mz+0.75 Jz+0.5],... + 'Color',[0.78 0.78 0.78],'LineWidth',1.8,'LineStyle',':'); +%% ───────────────────────────────────────────────────────── +% LAPTOP (derecha de la caja, bien separada) +%% ───────────────────────────────────────────────────────── +fill3(ax3d,[LPx LPx+11 LPx+11 LPx],... + [LPy LPy LPy LPy],... + [LPz LPz LPz+9 LPz+9],... + [0.08 0.08 0.14],'EdgeColor',[0.45 0.45 0.5],'FaceAlpha',0.95,'LineWidth',1.2); +fill3(ax3d,[LPx+0.5 LPx+10.5 LPx+10.5 LPx+0.5],... + [LPy-0.1 LPy-0.1 LPy-0.1 LPy-0.1],... + [LPz+0.5 LPz+0.5 LPz+8.5 LPz+8.5],... + [0.05 0.28 0.42],'EdgeColor','none','FaceAlpha',0.9); +text(ax3d,LPx+5.5,LPy-0.2,LPz+6.2,'>> MATLAB',... + 'Color',[0.28 0.92 0.48],'FontSize',7,'HorizontalAlignment','center',... + 'FontName','Courier New'); +text(ax3d,LPx+5.5,LPy-0.2,LPz+5.0,'FFT / IFFT',... + 'Color',[0.22 0.72 0.38],'FontSize',6.5,'HorizontalAlignment','center',... + 'FontName','Courier New'); +fill3(ax3d,[LPx LPx+11 LPx+11 LPx],... + [LPy LPy LPy+5 LPy+5],... + [LPz LPz LPz LPz],... + [0.18 0.18 0.2],'EdgeColor',[0.45 0.45 0.5],'FaceAlpha',0.95,'LineWidth',1.2); +etiqueta(ax3d,LPx+5.5,LPy-3.5,LPz+4.5,'PC + MATLAB',[0.28 0.85 1.0],10); + +% Cable jack → PC +plot3(ax3d,[Jx+1.6 LPx],... + [Jy+1.4 LPy+2.5],... + [Jz+0.5 LPz+0.5],... + 'Color',[0.12 0.12 0.12],'LineWidth',3.5); +plot3(ax3d,[Jx+1.6 LPx],... + [Jy+1.4 LPy+2.5],... + [Jz+0.5 LPz+0.5],... + 'Color',[0.38 0.38 0.38],'LineWidth',1.5); +text(ax3d,(Jx+1.6+LPx)/2,(Jy+1.4+LPy+2.5)/2-2.5,LPz+0.8,... + 'Cable 3.5mm UGREEN','Color',[0.42 0.42 0.42],... + 'FontSize',7,'HorizontalAlignment','center'); + +%% ─── LEYENDA ───────────────────────────────────────────── +legend(ax3d,[h_haz_ida,h_haz_ref],... + {'Haz laser 650nm 5mW','Reflexion → BPW34'},... + 'Location','northeast','TextColor','w',... + 'Color',[0.08 0.08 0.10],'EdgeColor',[0.3 0.3 0.3],'FontSize',8.5); + %% ═══════════════════════════════════════════════════════ -% SUBPLOTS INFERIORES DE SENAL +% SUBPLOTS INFERIORES %% ═══════════════════════════════════════════════════════ -c_audio = [1.0 0.7 0.1]; -c_foto = [1.0 0.4 0.3]; -c_tia = [0.3 0.8 1.0]; -c_rec = [0.4 1.0 0.4]; +c_audio=[1.0 0.72 0.08]; c_foto=[1.0 0.38 0.28]; +c_tia=[0.25 0.78 1.0]; c_rec=[0.35 1.0 0.35]; -ax_audio = subplot('Position',[0.02 0.03 0.22 0.28]); -ax_ifoto = subplot('Position',[0.26 0.03 0.22 0.28]); -ax_tia = subplot('Position',[0.50 0.03 0.22 0.28]); -ax_fft = subplot('Position',[0.74 0.03 0.24 0.28]); +ax_audio=subplot('Position',[0.01 0.02 0.22 0.27]); +ax_ifoto=subplot('Position',[0.25 0.02 0.22 0.27]); +ax_tia =subplot('Position',[0.49 0.02 0.22 0.27]); +ax_fft =subplot('Position',[0.73 0.02 0.26 0.27]); -function setup_ax(ax, ttl, col) - set(ax,'Color',[0.05 0.05 0.08],'XColor','w','YColor','w', ... - 'GridColor',[0.15 0.15 0.15],'FontSize',8); - grid(ax,'on'); - title(ax, ttl,'Color',col,'FontWeight','bold','FontSize',9); - xlabel(ax,'Tiempo (s)','Color','w','FontSize',8); -end + function setup_ax2(ax,ttl,col,ylbl,bg) + set(ax,'Color',bg,'XColor',[0.55 0.55 0.55],'YColor',[0.55 0.55 0.55],... + 'GridColor',[0.12 0.12 0.12],'FontSize',8,'LineWidth',0.8); + grid(ax,'on'); box(ax,'off'); + title(ax,ttl,'Color',col,'FontWeight','bold','FontSize',9); + xlabel(ax,'Tiempo (s)','Color',[0.5 0.5 0.5],'FontSize',8); + ylabel(ax,ylbl,'Color',[0.5 0.5 0.5],'FontSize',8); + end -setup_ax(ax_audio,'Audio en la caja', c_audio); -setup_ax(ax_ifoto,'BPW34 — I_{foto} (uA)', c_foto); -setup_ax(ax_tia, 'V_{TIA} + MAX9814 (mV)', c_tia); -setup_ax(ax_fft, 'FFT — Espectro', c_rec); +setup_ax2(ax_audio,'① Audio en la caja', c_audio,'Amplitud', bg); +setup_ax2(ax_ifoto,'② BPW34 I_{foto} (µA)', c_foto, 'µA', bg); +setup_ax2(ax_tia, '③ TIA → MAX9814 (mV)', c_tia, 'mV', bg); +setup_ax2(ax_fft, '④ FFT — Espectro', c_rec, '|Y(f)|', bg); -n_win = round(fs * 0.012); % ventana de 12 ms -t_win = t(1:n_win); +n_win=round(fs*0.012); t_win=t(1:n_win); +h_l_audio=plot(ax_audio,t_win,audio_original(1:n_win),'Color',c_audio,'LineWidth',1.4); +h_l_ifoto=plot(ax_ifoto,t_win,I_foto(1:n_win)*1e6, 'Color',c_foto, 'LineWidth',1.4); +h_l_tia =plot(ax_tia, t_win,V_tia(1:n_win)*1e3, 'Color',c_tia, 'LineWidth',1.4); -h_l_audio = plot(ax_audio, t_win, audio_original(1:n_win), 'Color',c_audio,'LineWidth',1.2); -h_l_ifoto = plot(ax_ifoto, t_win, I_foto(1:n_win)*1e6, 'Color',c_foto, 'LineWidth',1.2); -h_l_tia = plot(ax_tia, t_win, V_tia(1:n_win)*1e3, 'Color',c_tia, 'LineWidth',1.2); +ylim(ax_audio,[-1.35 1.35]); +ylim(ax_ifoto,[min(I_foto)*1e6*1.05 max(I_foto)*1e6*1.05]); +ylim(ax_tia, [min(V_tia)*1e3*1.1 max(V_tia)*1e3*1.1]); -ylim(ax_audio,[-1.3 1.3]); -ylim(ax_ifoto,[min(I_foto)*1e6*1.05 max(I_foto)*1e6*1.05]); -ylim(ax_tia, [min(V_tia)*1e3*1.1 max(V_tia)*1e3*1.1]); - -% FFT estatica -f_vec = (0:floor(N/2)) * fs / N; -mag = abs(Y(1:floor(N/2)+1)) / N; -mag(2:end-1) = 2*mag(2:end-1); -plot(ax_fft, f_vec, mag,'Color',c_rec,'LineWidth',0.9); -xlim(ax_fft,[0 2000]); -set(ax_fft,'Color',[0.05 0.05 0.08],'XColor','w','YColor','w','GridColor',[0.15 0.15 0.15]); -grid(ax_fft,'on'); -title(ax_fft,'FFT — Espectro','Color',c_rec,'FontWeight','bold','FontSize',9); -xlabel(ax_fft,'Frecuencia (Hz)','Color','w','FontSize',8); +f_vec=(0:floor(N/2))*fs/N; +mag=abs(Y(1:floor(N/2)+1))/N; mag(2:end-1)=2*mag(2:end-1); +area(ax_fft,f_vec,mag,'FaceColor',c_rec,'FaceAlpha',0.15,... + 'EdgeColor',c_rec,'LineWidth',1); +xlim(ax_fft,[0 1800]); +set(ax_fft,'Color',bg,'XColor',[0.55 0.55 0.55],'YColor',[0.55 0.55 0.55],... + 'GridColor',[0.12 0.12 0.12]); +grid(ax_fft,'on'); box(ax_fft,'off'); +title(ax_fft,'④ FFT — Espectro','Color',c_rec,'FontWeight','bold','FontSize',9); +xlabel(ax_fft,'Frecuencia (Hz)','Color',[0.5 0.5 0.5],'FontSize',8); hold(ax_fft,'on'); -for fi = [f1 f2 f3] - [~,idx_fi] = min(abs(f_vec - fi)); - plot(ax_fft, fi, mag(idx_fi),'w^','MarkerSize',7,'MarkerFaceColor','w'); - text(ax_fft, fi, mag(idx_fi)*1.12, sprintf('%.0fHz',fi), ... - 'Color','w','FontSize',7,'HorizontalAlignment','center'); +for fi=[f1 f2 f3] + [~,idx_fi]=min(abs(f_vec-fi)); + stem(ax_fft,fi,mag(idx_fi),'Color',[1 1 1],'LineWidth',2,... + 'Marker','^','MarkerFaceColor','w','MarkerSize',7); + text(ax_fft,fi,mag(idx_fi)*1.16,sprintf('%.0fHz',fi),... + 'Color','w','FontSize',7.5,'HorizontalAlignment','center',... + 'FontWeight','bold'); end %% ═══════════════════════════════════════════════════════ % ANIMACION %% ═══════════════════════════════════════════════════════ -fprintf(' Iniciando animacion (presiona Q para salir)...\n\n'); +fprintf(' Animacion iniciada — presiona Q para salir...\n\n'); -paso = round(fs/30); % ~30 fps -n_frm = floor(N / paso); -amp_v = 0.25; % cm vibracion max del vidrio +paso=round(fs/30); n_frm=floor(N/paso); amp_v=0.22; -for k = 1:n_frm +for k=1:n_frm + if ~ishandle(fig)||getappdata(fig,'salir'), break; end + i0=(k-1)*paso+1; idx=i0:min(i0+n_win-1,N); + if length(idx)