commit - 9ed0fcb7ca4c03d53491326b279520821be6fff7
commit + 3a1a479850af3cb443dd4d7f0c1d8f7ee1c80a8d
blob - /dev/null
blob + 72e6e079375bb030552e2d4c12b4dbc53bf8e8d5 (mode 644)
--- /dev/null
+++ simulacion_3d_laser.m
+%% SIMULACION 3D — MICROFONO LASER
+% Visualizacion 3D animada del experimento completo:
+% Caja insonorizada → vidrio vibrante → laser → BPW34 →
+% TIA (LM358) → MAX9814 → PC → FFT → reconstruccion
+%
+% Autor: Alejandro B. E. — Fisica 2do Semestre
+
+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');
+
+%% ═══════════════════════════════════════════════════════
+% PARAMETROS
+%% ═══════════════════════════════════════════════════════
+
+% Audio simulado (acorde La mayor: 440 + 880 + 660 Hz)
+f1 = 440; f2 = 880; f3 = 660;
+fs = 8000; % Hz
+duracion = 3.0; % s
+
+t = (0 : 1/fs : duracion - 1/fs)';
+N = length(t);
+
+% 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
+
+% 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
+
+%% ─── 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
+%% ═══════════════════════════════════════════════════════
+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');
+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]);
+lighting(ax3d,'gouraud');
+light(ax3d,'Position',[60 60 60],'Style','infinite');
+
+% 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);
+ end
+
+Lc = 20; % tamaño caja (cm)
+
+% 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');
+
+% 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);
+
+% 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]);
+end
+text(ax3d, Lc/2-5, Lc/2, Lc/2+5.5,'Audifono', ...
+ 'Color',[0.7 0.7 0.7],'FontSize',8);
+
+% 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');
+
+% Punto de impacto en vidrio
+P_imp = [Lc, 10, 10];
+
+% 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);
+
+% 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;
+
+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);
+
+% 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');
+
+% 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);
+
+% 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');
+
+% 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',':');
+
+% 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');
+
+% 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',':');
+
+% 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');
+
+% 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);
+
+% 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]);
+
+%% ═══════════════════════════════════════════════════════
+% SUBPLOTS INFERIORES DE SENAL
+%% ═══════════════════════════════════════════════════════
+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];
+
+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]);
+
+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
+
+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);
+
+n_win = round(fs * 0.012); % ventana de 12 ms
+t_win = t(1:n_win);
+
+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.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);
+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');
+end
+
+%% ═══════════════════════════════════════════════════════
+% ANIMACION
+%% ═══════════════════════════════════════════════════════
+fprintf(' Iniciando animacion (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
+
+for k = 1:n_frm
+
+ if ~ishandle(fig) || getappdata(fig,'salir'), break; end
+
+ i0 = (k-1)*paso + 1;
+ i1 = min(i0 + n_win - 1, N);
+ idx = i0:i1;
+
+ if length(idx) < n_win, break; end
+
+ % Vibracion del vidrio
+ desp = amp_v * audio_original(i0);
+ set(h_vidrio,'XData',(Lc + desp)*ones(size(yv)));
+
+ % Haz laser sigue el punto de impacto
+ P_imp_k = [Lc + desp, P_imp(2), P_imp(3)];
+ set(h_haz_ida,'XData',[laser_pos(1) P_imp_k(1)], ...
+ 'YData',[laser_pos(2) P_imp_k(2)], ...
+ 'ZData',[laser_pos(3) P_imp_k(3)]);
+ set(h_haz_ref,'XData',[P_imp_k(1) bpw34_pos(1)], ...
+ 'YData',[P_imp_k(2) bpw34_pos(2)], ...
+ 'ZData',[P_imp_k(3) bpw34_pos(3)]);
+
+ % Actualizar graficas
+ tw = t(idx);
+ set(h_l_audio,'XData',tw,'YData',audio_original(idx));
+ set(h_l_ifoto,'XData',tw,'YData',I_foto(idx)*1e6);
+ set(h_l_tia, 'XData',tw,'YData',V_tia(idx)*1e3);
+ xlim(ax_audio,[tw(1) tw(end)]);
+ xlim(ax_ifoto,[tw(1) tw(end)]);
+ xlim(ax_tia, [tw(1) tw(end)]);
+
+ title(ax3d, sprintf('Montaje 3D — t = %.3f s | P_{laser} = %.5f W', ...
+ t(i0), P_luz(i0)), ...
+ 'Color',[1 0.7 0.1],'FontWeight','bold','FontSize',11);
+
+ drawnow limitrate;
+end
+
+%% ═══════════════════════════════════════════════════════
+% FIGURA FINAL: RECONSTRUCCION
+%% ═══════════════════════════════════════════════════════
+fprintf(' Animacion terminada.\n\n');
+
+figure('Name','Reconstruccion FFT','NumberTitle','off', ...
+ 'Position',[80 80 1300 750],'Color',[0.05 0.05 0.08]);
+
+subplot(3,1,1);
+plot(t, audio_original,'Color',c_audio,'LineWidth',0.8);
+set(gca,'Color',[0.05 0.05 0.08],'XColor','w','YColor','w','GridColor',[0.15 0.15 0.15]);
+grid on;
+title('Audio original dentro de la caja','Color',c_audio,'FontWeight','bold','FontSize',11);
+xlabel('Tiempo (s)','Color','w'); ylabel('Amplitud','Color','w');
+xlim([0 duracion]);
+
+subplot(3,1,2);
+plot(t, V_max,'Color',c_tia,'LineWidth',0.8);
+set(gca,'Color',[0.05 0.05 0.08],'XColor','w','YColor','w','GridColor',[0.15 0.15 0.15]);
+grid on;
+title('Senal capturada (MAX9814 out)','Color',c_tia,'FontWeight','bold','FontSize',11);
+xlabel('Tiempo (s)','Color','w'); ylabel('V (V)','Color','w');
+xlim([0 duracion]);
+
+subplot(3,1,3);
+plot(t, V_rec_escalado,'Color',c_rec,'LineWidth',0.8);
+set(gca,'Color',[0.05 0.05 0.08],'XColor','w','YColor','w','GridColor',[0.15 0.15 0.15]);
+grid on;
+title(sprintf('Senal reconstruida (IFFT) — correlacion: %.4f', rho), ...
+ 'Color',c_rec,'FontWeight','bold','FontSize',11);
+xlabel('Tiempo (s)','Color','w'); ylabel('Amplitud','Color','w');
+xlim([0 duracion]);
+
+V_play = V_rec_escalado / max(abs(V_rec_escalado) + 1e-10);
+fprintf(' Reproduciendo senal reconstruida...\n');
+sound(V_play, fs);
+
+fprintf('\n╔══════════════════════════════════════════════════════╗\n');
+fprintf('║ Simulacion completada ║\n');
+fprintf('║ Correlacion original / reconstruido: %.4f ║\n', rho);
+fprintf('╚══════════════════════════════════════════════════════╝\n');
\ No newline at end of file