Microorganism in a drop of water
1:42
Generator Rotor Removal
2:13
3 ай бұрын
3D Transformer Disassembly
2:14
3 ай бұрын
Power Dam Discharge
1:02
4 ай бұрын
Amazing Projects Around The World
2:02
T-62A Tank Model  #T62A
1:35
Жыл бұрын
Пікірлер
@140289EP
@140289EP 11 күн бұрын
Man, how did you achieve the canvas effect on the top of the cab?!
@KepaAlonso
@KepaAlonso 11 күн бұрын
The canvas effect on top of the cab was achieved using a combination of washes, oil paints, and dry brushing. First, I applied a base color to the canvas. Then, I used a darker wash to enhance the folds and details, simulating shadows and grime. After that, I used oil paints to add subtle stains and blend colors for a more weathered look. Finally, I dry-brushed lighter tones onto the raised areas and edges to highlight the fabric's wear and tear, giving it a realistic, aged appearance.
@KepaAlonso
@KepaAlonso 29 күн бұрын
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Generador de Onda</title> <style> body { text-align: center; font-family: Arial, sans-serif; } canvas { border: 1px solid black; display: block; margin: 20px auto; } input[type="range"] { width: 1200px; } </style> </head> <body> <h1>Generador de Onda</h1> <label for="frequency">Frecuencia: <span id="freqValue">50</span> Hz</label> <br> <input type="range" id="frequency" min="1" max="2000" step="1" value="50"> <br><br> <label for="waveType">Tipo de Onda:</label> <select id="waveType"> <option value="sine">Sinusoidal</option> <option value="square">Cuadrada</option> <option value="sawtooth">Diente de sierra</option> <option value="triangle">Triangular</option> </select> <br><br> <button id="playButton">Reproducir/Pausar</button> <canvas id="waveCanvas" width="800" height="400"></canvas> <script> // Configuración de Web Audio API const AudioContext = window.AudioContext || window.webkitAudioContext; const audioCtx = new AudioContext(); let oscillator = null; // Oscilador para generar la onda let isPlaying = false; // Estado de reproducción let isDrawing = false; // Estado de animación const frequencySlider = document.getElementById('frequency'); const freqValueDisplay = document.getElementById('freqValue'); const playButton = document.getElementById('playButton'); const waveTypeSelect = document.getElementById('waveType'); // Nuevo selector de tipo de onda // Configuración para el canvas const canvas = document.getElementById('waveCanvas'); const ctx = canvas.getContext('2d'); let frequency = 440; // Frecuencia inicial let amplitude = 100; // Amplitud de la onda let offsetX = 0; // Para animar la onda let waveType = 'sine'; // Tipo de onda inicial // Función para iniciar el oscilador function startOscillator(frequency) { oscillator = audioCtx.createOscillator(); oscillator.type = waveType; // Tipo de onda según la selección oscillator.frequency.setValueAtTime(frequency, audioCtx.currentTime); oscillator.connect(audioCtx.destination); oscillator.start(); } // Función para detener el oscilador function stopOscillator() { if (oscillator) { oscillator.stop(); oscillator.disconnect(); oscillator = null; } } // Función para dibujar la onda en el canvas function drawWave() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.moveTo(0, canvas.height / 2); for (let x = 0; x < canvas.width; x++) { let y = canvas.height / 2; let t = (x + offsetX) / canvas.width; switch (waveType) { case 'sine': y += amplitude * Math.sin(2 * Math.PI * frequency * t); break; case 'square': y += amplitude * (Math.sin(2 * Math.PI * frequency * t) > 0 ? 1 : -1); break; case 'sawtooth': y += amplitude * (2 * (t * frequency - Math.floor(0.5 + t * frequency))); break; case 'triangle': y += amplitude * (2 * Math.abs(2 * (t * frequency - Math.floor(0.5 + t * frequency))) - 1); break; } ctx.lineTo(x, y); } ctx.strokeStyle = 'blue'; ctx.lineWidth = 2; ctx.stroke(); offsetX += 5; // Ajusta la velocidad de la animación if (isPlaying) { requestAnimationFrame(drawWave); // Solo continua animando si está sonando } } // Actualizar frecuencia cuando se mueve el deslizador frequencySlider.addEventListener('input', function() { frequency = parseFloat(this.value); freqValueDisplay.textContent = frequency.toFixed(0); if (oscillator) { oscillator.frequency.setValueAtTime(frequency, audioCtx.currentTime); // Actualiza la frecuencia del sonido } if (!isPlaying) { // Si el oscilador está parado, redibuja la onda para reflejar la nueva frecuencia ctx.clearRect(0, 0, canvas.width, canvas.height); drawWave(); } }); // Actualizar el tipo de onda cuando se selecciona un tipo diferente waveTypeSelect.addEventListener('change', function() { waveType = this.value; if (oscillator) { stopOscillator(); // Detener el oscilador actual startOscillator(frequency); // Iniciar un nuevo oscilador con el nuevo tipo de onda } if (!isPlaying) { // Si no está reproduciendo, redibuja la onda con el nuevo tipo ctx.clearRect(0, 0, canvas.width, canvas.height); drawWave(); } }); // Reproducir o pausar la onda playButton.addEventListener('click', function() { if (!isPlaying) { startOscillator(frequency); playButton.textContent = 'Pausar'; isPlaying = true; drawWave(); // Comienza la animación } else { stopOscillator(); playButton.textContent = 'Reproducir'; isPlaying = false; } }); // Dibuja la onda inicialmente sin animación drawWave(); </script> </body> </html>
@tommarekcz
@tommarekcz Ай бұрын
that is interesting
@IOSALive
@IOSALive Ай бұрын
Kepa Alonso, great content it was really good
@KepaAlonso
@KepaAlonso Ай бұрын
To understand DC motor control via PWM, watch video : studio.kzbin.infosXi1ZD4eogw/edit
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@KepaAlonso
@KepaAlonso Ай бұрын
You can download the code along with more resources on this website: kalonso9.wixsite.com/kalo/connectcode
@acidbubblebath77
@acidbubblebath77 Ай бұрын
"Get this reservoir filled dam it!"
@KepaAlonso
@KepaAlonso Ай бұрын
HTML code (copy in a notepad txt file and save as PWM.html): <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DC MOTOR CONTROL</title> <style> body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; background-color: #f4f4f4; color: #333; } .slider-container { margin: 20px; } .slider-container label { font-weight: bold; margin-right: 10px; } .slider-container input[type="range"] { width: 300px; } canvas { border: 2px solid #007BFF; border-radius: 10px; background-color: #ffffff; margin-top: 20px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } h1 { color: #007BFF; } </style> </head> <body> <h1>DC MOTOR CONTROL</h1> <div class="slider-container"> <label for="frequencySlider">Frequency (Hz):</label> <input type="range" id="frequencySlider" min="1" max="20" value="4"> <span id="frequencyValue">4</span> Hz </div> <div class="slider-container"> <label for="dutyCycleSlider">Duty Cycle (%):</label> <input type="range" id="dutyCycleSlider" min="0" max="100" value="50"> <span id="dutyCycleValue">50</span> % </div> <div class="slider-container"> <label for="volumeSlider">Amplitude:</label> <input type="range" id="volumeSlider" min="0" max="1" step="0.01" value="0.5"> <span id="volumeValue">0.5</span> </div> <canvas id="pwmCanvas" width="600" height="300"></canvas> <script> const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); const pwmGain = audioCtx.createGain(); const frequencySlider = document.getElementById("frequencySlider"); const dutyCycleSlider = document.getElementById("dutyCycleSlider"); const volumeSlider = document.getElementById("volumeSlider"); const frequencyValue = document.getElementById("frequencyValue"); const dutyCycleValue = document.getElementById("dutyCycleValue"); const volumeValue = document.getElementById("volumeValue"); const canvas = document.getElementById("pwmCanvas"); const ctx = canvas.getContext("2d"); let pwmInterval = null; // Función para actualizar la frecuencia, el ciclo de trabajo y el volumen function updatePWM() { const frequency = parseFloat(frequencySlider.value); const dutyCycle = parseFloat(dutyCycleSlider.value) / 100; const volume = parseFloat(volumeSlider.value); frequencyValue.textContent = frequency; dutyCycleValue.textContent = Math.round(dutyCycle * 100); volumeValue.textContent = volume; // Limpiar cualquier intervalo anterior clearInterval(pwmInterval); // Controlar la señal en función del ciclo de trabajo if (dutyCycle >= 1) { // Señal siempre alta pwmGain.gain.setValueAtTime(volume, audioCtx.currentTime); } else if (dutyCycle <= 0) { // Señal siempre baja pwmGain.gain.setValueAtTime(0, audioCtx.currentTime); } else { // Modulación PWM para otros ciclos de trabajo const period = 1 / frequency; const highTime = period * dutyCycle; pwmInterval = setInterval(() => { pwmGain.gain.setValueAtTime(volume, audioCtx.currentTime); pwmGain.gain.setValueAtTime(0, audioCtx.currentTime + highTime); }, period * 1000); } drawPWMWave(frequency, dutyCycle, volume); } // Función para dibujar la señal PWM en el canvas function drawPWMWave(frequency, dutyCycle, volume) { const width = canvas.width; const height = canvas.height; ctx.clearRect(0, 0, width, height); const period = width / frequency; const highTime = period * dutyCycle; const amplitude = height * (1 - volume); // Escala la altura de la onda según el volumen ctx.beginPath(); ctx.strokeStyle = "#007BFF"; ctx.lineWidth = 2; if (dutyCycle >= 1) { ctx.moveTo(0, amplitude); ctx.lineTo(width, amplitude); } else if (dutyCycle <= 0) { ctx.moveTo(0, height); ctx.lineTo(width, height); } else { for (let x = 0; x < width; x += period) { ctx.lineTo(x, amplitude); ctx.lineTo(x + highTime, amplitude); ctx.lineTo(x + highTime, height); ctx.lineTo(x + period, height); } } ctx.stroke(); } // Inicializar el contexto de audio const pwmOscillator = audioCtx.createOscillator(); pwmOscillator.type = 'square'; pwmOscillator.frequency.value = frequencySlider.value; pwmOscillator.connect(pwmGain); pwmGain.connect(audioCtx.destination); pwmOscillator.start(); // Eventos de los deslizadores frequencySlider.addEventListener("input", updatePWM); dutyCycleSlider.addEventListener("input", updatePWM); volumeSlider.addEventListener("input", updatePWM); // Inicializar la señal PWM updatePWM(); // Activar el contexto de audio con un click del usuario document.body.addEventListener('click', () => { if (audioCtx.state === 'suspended') { audioCtx.resume(); } }); </script> </body> </html>
@KepaAlonso
@KepaAlonso 2 ай бұрын
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> /* Reset de márgenes y padding */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #1a1a2e; color: #ffffff; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; } .container { background-color: #16213e; padding: 30px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); max-width: 800px; width: 100%; display: flex; flex-direction: column; align-items: center; } canvas { margin-top: 20px; border-radius: 10px; width: 100%; height: 200px; } label { font-size: 14px; font-weight: 500; color: #a0a5ba; margin-bottom: 8px; display: block; text-align: left; width: 100%; max-width: 100px; } select, input[type="range"], input[type="text"] { font-size: 14px; padding: 10px; border: 1px solid #3e497a; border-radius: 5px; margin-top: 8px; width: 100%; max-width: 100px; background-color: #0f3460; color: #ffffff; transition: border-color 0.3s ease, box-shadow 0.3s ease; } select:focus, input:focus { border-color: #00adb5; box-shadow: 0 0 8px rgba(0, 173, 181, 0.5); outline: none; } #controls { display: flex; flex-direction: column; align-items: center; gap: 20px; margin-top: 25px; width: 100%; } #controls > div { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 300px; } #controls input[type="text"] { background-color: #1a1a2e; cursor: not-allowed; color: #a0a5ba; } </style> </head> <body> <div class="container"> <canvas id="oscilloscope" width="1024" height="200"></canvas> <div id="controls"> <div> <label for="dominantFrequency">Frequency (Hz): </label> <input type="text" id="dominantFrequency" readonly> </div> </div> </div> <div> <input type="range" id="gainControl" min="0" max="20" step="0.1" value="10"> </div> <div> <select id="audioSource"></select> </div> <script> const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); const gainNode = audioContext.createGain(); const canvas = document.getElementById("oscilloscope"); const canvasCtx = canvas.getContext("2d"); const dominantFrequencyField = document.getElementById("dominantFrequency"); const gainControl = document.getElementById("gainControl"); let source; let audioInputSelect = document.getElementById('audioSource'); navigator.mediaDevices.enumerateDevices().then(gotDevices); function gotDevices(deviceInfos) { for (let i = 0; i < deviceInfos.length; i++) { const deviceInfo = deviceInfos[i]; if (deviceInfo.kind === 'audioinput') { const option = document.createElement('option'); option.value = deviceInfo.deviceId; option.text = deviceInfo.label || `Input ${i + 1}`; audioInputSelect.appendChild(option); } } } audioInputSelect.onchange = function() { startAudioProcessing(this.value); } function startAudioProcessing(deviceId) { if (source) { source.disconnect(); } navigator.mediaDevices.getUserMedia({ audio: { deviceId: deviceId ? { exact: deviceId } : undefined } }).then(stream => { source = audioContext.createMediaStreamSource(stream); source.connect(gainNode); gainNode.connect(analyser); gainNode.gain.value = gainControl.value * 10; // Multiplica por 10 la ganancia visualize(); calculateDominantFrequency(); }).catch(err => { console.error('Error al acceder al micrófono: ', err); }); gainControl.oninput = function() { gainNode.gain.value = gainControl.value * 10; // Multiplica por 10 la ganancia }; } function visualize() { setTimeout(() => requestAnimationFrame(visualize), 100); // Actualiza cada 0.1 segundos analyser.getByteTimeDomainData(dataArray); canvasCtx.clearRect(0, 0, canvas.width, canvas.height); canvasCtx.lineWidth = 2; canvasCtx.strokeStyle = '#00adb5'; canvasCtx.beginPath(); let sliceWidth = canvas.width * 1.0 / bufferLength; let x = 0; for (let i = 0; i < bufferLength; i++) { let v = (dataArray[i] / 128.0 - 1.0); let y = v * (canvas.height / 2.5) + canvas.height / 2; // Ajuste para más apariencia sinusoidal if (i === 0) { canvasCtx.moveTo(x, y); } else { canvasCtx.lineTo(x, y); } x += sliceWidth; } canvasCtx.lineTo(canvas.width, canvas.height / 2); canvasCtx.stroke(); } function calculateDominantFrequency() { const frequencyData = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(frequencyData); let maxIndex = 0; let maxValue = -Infinity; for (let i = 0; i < frequencyData.length; i++) { if (frequencyData[i] > maxValue) { maxValue = frequencyData[i]; maxIndex = i; } } const nyquist = audioContext.sampleRate / 2; const dominantFrequency = (maxIndex / bufferLength) * nyquist; dominantFrequencyField.value = `${dominantFrequency.toFixed(2)} Hz`; setTimeout(calculateDominantFrequency, 100); // Actualiza cada 0.1 segundos } </script> </body> </html>
@KepaAlonso
@KepaAlonso 2 ай бұрын
<!DOCTYPE html> <html> <head> <title>Medidor de RPM</title> <style> body { background-color: black; color: white; text-align: center; font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; flex-direction: column; align-items: center; height: 100vh; } input[type=range] { -webkit-appearance: none; width: 80%; margin: 10px; } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 8.4px; cursor: pointer; animate: 0.2s; background: #3071a9; border-radius: 1.3px; box-shadow: 0px 0px 0.9px #000000; } input[type=range]::-webkit-slider-thumb { border: 1px solid #000000; height: 36px; width: 16px; border-radius: 3px; background: #ffffff; cursor: pointer; -webkit-appearance: none; margin-top: -14px; } .slider-container { display: flex; flex-direction: column; align-items: center; margin-top: 20px; } canvas { border: none; margin-top: 20px; } .rpm-container { position: relative; top: -120px; transform: translateY(-50%); width: 100px; display: flex; flex-direction: column; align-items: center; background-color: gray; padding: 10px; border-radius: 5px; } .rpm-number { font-size: 24px; font-weight: bold; } .rpm-text { font-size: 16px; } </style> </head> <body> <canvas id="rpmGauge" width="600" height="600"></canvas> <div class="rpm-container"> <div class="rpm-number" id="rpm">0</div> <div class="rpm-text">RPM</div> </div> <select id="microphoneSelect"></select> <p><button onclick="startRecording()">Iniciar</button></p> <div class="slider-container"> <label for="bufferDuration">Duración del buffer (ms): </label> <input type="range" id="bufferDuration" name="bufferDuration" min="20" max="1000" value="20" oninput="updateBufferDuration(this.value)"> <span id="bufferDurationValue">20</span> <p></p> <label for="updateInterval">Intervalo de actualización (ms): </label> <input type="range" id="updateInterval" name="updateInterval" min="20" max="1000" value="20" oninput="updateUpdateInterval(this.value)"> <span id="updateIntervalValue">20</span> <p></p> <label for="fftSize">FFT Size: </label> <input type="range" id="fftSize" name="fftSize" min="32" max="32768" value="2048" step="32" oninput="updateFftSize(this.value)"> <span id="fftSizeValue">2048</span> <p></p> </div> <script> // Inicialización del contexto de audio y el analizador let audioContext = new (window.AudioContext || window.webkitAudioContext)(); let analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; let bufferLength = analyser.frequencyBinCount; let dataArray = new Uint8Array(bufferLength); let mediaStreamSource; // Configuración inicial const sampleRate = audioContext.sampleRate; let updateInterval = 20; // Intervalo de actualización en milisegundos let frequencyBuffer = []; let bufferDuration = 20; // Duración inicial del buffer en milisegundos let maxBufferLength = Math.floor(bufferDuration / updateInterval); let intervalId; let rpm = 0; let targetRpm = 0; let lastRpm = 0; let lastUpdateTime = 0; let rpmStabilityThreshold = 2; // Umbral de cambio de RPM para considerar velocidad cero let stableTimeThreshold = 100; // Tiempo en ms para considerar RPM estable y poner a cero let smoothingFactor = 0.1; // Factor de suavizado para la EMA // Inicialización del canvas y su contexto var canvas = document.getElementById("rpmGauge"); var context = canvas.getContext("2d"); var centerX = canvas.width / 2; var centerY = canvas.height / 2; var radius = 250; var startAngle = -230 * Math.PI / 180; // Posición inicial del medidor var endAngle = 50 * Math.PI / 180; // Posición final del medidor // Función para dibujar el medidor function drawGauge() { context.clearRect(0, 0, canvas.width, canvas.height); context.fillStyle = "black"; context.fillRect(0, 0, canvas.width, canvas.height); context.beginPath(); context.arc(centerX, centerY, radius, startAngle, endAngle, false); context.fillStyle = "black"; context.fill(); context.lineWidth = 5; context.strokeStyle = "white"; context.stroke(); // Dibujar los números de las RPM context.fillStyle = "white"; context.font = "bold 16px Arial"; context.textAlign = "center"; context.textBaseline = "middle"; for (var i = 0; i <= 12; i++) { var angle = startAngle + (i * (endAngle - startAngle) / 12); var x = centerX + (radius - 60) * Math.cos(angle); var y = centerY + (radius - 60) * Math.sin(angle); context.fillText(i * 100, x, y); } // Dibujar las líneas de las marcas y subdivisiones context.lineWidth = 2; for (var i = 0; i <= 120; i += 10) { var angle = startAngle + (i * (endAngle - startAngle) / 120); var x1 = centerX + (radius - 20) * Math.cos(angle); var y1 = centerY + (radius - 20) * Math.sin(angle); var x2 = centerX + (radius - 30) * Math.cos(angle); var y2 = centerY + (radius - 30) * Math.sin(angle); context.beginPath(); context.moveTo(x1, y1); context.lineTo(x2, y2); context.strokeStyle = "white"; context.stroke(); } // Dibujar subdivisiones más pequeñas context.lineWidth = 1; for (var i = 0; i <= 120; i += 2) { var angle = startAngle + (i * (endAngle - startAngle) / 120); var x1 = centerX + (radius - 20) * Math.cos(angle); var y1 = centerY + (radius - 20) * Math.sin(angle); var x2 = centerX + (radius - 25) * Math.cos(angle); var y2 = centerY + (radius - 25) * Math.sin(angle); context.beginPath(); context.moveTo(x1, y1); context.lineTo(x2, y2); context.strokeStyle = "white"; context.stroke(); } } // Función para dibujar la aguja del medidor function drawNeedle() { var angle = startAngle + (rpm * (endAngle - startAngle) / 12000); var x = centerX + (radius - 50) * Math.cos(angle); var y = centerY + (radius - 50) * Math.sin(angle); context.beginPath(); context.moveTo(centerX, centerY); context.lineTo(x, y); context.strokeStyle = "red"; context.lineWidth = 5; context.stroke(); } // Función para calcular la Media Móvil Exponencial (EMA) function calculateEMA(currentValue, previousEMA, smoothingFactor) { return (currentValue * smoothingFactor) + (previousEMA * (1 - smoothingFactor)); } // Función para iniciar la grabación del audio function startRecording() { let selectedDeviceId = document.getElementById('microphoneSelect').value; let constraints = { audio: { deviceId: selectedDeviceId ? { exact: selectedDeviceId } : undefined } }; navigator.mediaDevices.getUserMedia(constraints) .then(stream => { mediaStreamSource = audioContext.createMediaStreamSource(stream); mediaStreamSource.connect(analyser); intervalId = setInterval(analyze, updateInterval); }) .catch(err => { console.error('Error accessing audio stream', err); }); }
@KepaAlonso
@KepaAlonso 2 ай бұрын
// Función para analizar los datos de audio function analyze() { analyser.getByteFrequencyData(dataArray); let maxVal = 0; let maxIndex = 0; for (let i = 0; i < bufferLength; i++) { if (dataArray[i] > maxVal) { maxVal = dataArray[i]; maxIndex = i; } } let frequency = maxIndex * sampleRate / analyser.fftSize; frequencyBuffer.push(frequency); // Mantener el buffer dentro de la longitud máxima if (frequencyBuffer.length > maxBufferLength) { frequencyBuffer.shift(); } // Calcular la frecuencia media let sumFrequency = frequencyBuffer.reduce((sum, freq) => sum + freq, 0); let avgFrequency = sumFrequency / frequencyBuffer.length; // Convertir la frecuencia media a RPM let newTargetRpm = avgFrequency * 10; // Aplicar la suavización mediante EMA targetRpm = calculateEMA(newTargetRpm, targetRpm, smoothingFactor); let currentTime = Date.now(); if (Math.abs(targetRpm - lastRpm) <= rpmStabilityThreshold) { if (currentTime - lastUpdateTime > stableTimeThreshold) { targetRpm = 0; } } else { lastUpdateTime = currentTime; } lastRpm = targetRpm; document.getElementById('rpm').innerText = isNaN(targetRpm) ? '0' : Math.round(targetRpm / 10); // Dibujar el medidor y la aguja drawGauge(); drawNeedle(); } // Actualizar la duración del buffer function updateBufferDuration(value) { bufferDuration = parseInt(value); maxBufferLength = Math.floor(bufferDuration / updateInterval); document.getElementById('bufferDurationValue').innerText = value; frequencyBuffer = []; // Limpiar el buffer al cambiar la duración } // Actualizar el intervalo de actualización function updateUpdateInterval(value) { updateInterval = parseInt(value); clearInterval(intervalId); intervalId = setInterval(analyze, updateInterval); maxBufferLength = Math.floor(bufferDuration / updateInterval); document.getElementById('updateIntervalValue').innerText = value; } // Actualizar el tamaño de la FFT function updateFftSize(value) { analyser.fftSize = parseInt(value); bufferLength = analyser.frequencyBinCount; dataArray = new Uint8Array(bufferLength); document.getElementById('fftSizeValue').innerText = value; } // Animar la aguja del medidor function animateNeedle() { if (Math.abs(rpm - targetRpm) > 1) { rpm += (targetRpm - rpm) * 0.05; drawGauge(); drawNeedle(); } requestAnimationFrame(animateNeedle); } // Población de la lista de micrófonos disponibles function populateMicrophoneList() { navigator.mediaDevices.enumerateDevices() .then(devices => { let microphoneSelect = document.getElementById('microphoneSelect'); devices.forEach(device => { if (device.kind === 'audioinput') { let option = document.createElement('option'); option.value = device.deviceId; option.text = device.label || `Microphone ${microphoneSelect.length + 1}`; microphoneSelect.appendChild(option); } }); }) .catch(err => { console.error('Error enumerating devices', err); }); } // Inicializar la lista de micrófonos al cargar la página populateMicrophoneList(); // Dibujar el medidor y la aguja al cargar la página drawGauge(); drawNeedle(); animateNeedle(); </script> </body> </html>
@haiduy7627
@haiduy7627 2 ай бұрын
🌺🌸🌾💕💯🌹🌻❤
@haiduy7627
@haiduy7627 2 ай бұрын
👍💪🌾💕💯🌹
@haiduy7627
@haiduy7627 2 ай бұрын
😊❤
@rubenkvz4673
@rubenkvz4673 2 ай бұрын
😮 Which 3D, CAD software is ?
@KepaAlonso
@KepaAlonso 2 ай бұрын
Intregraph SmartPlant 3D
@लोककला
@लोककला 2 ай бұрын
please give me 1 second auto on off code
@Jay-yz7wm
@Jay-yz7wm 2 ай бұрын
So cool, where is this?
@tharki_insaan699
@tharki_insaan699 3 ай бұрын
3D PRINTED DAM😂😂😂😂
@KepaAlonso
@KepaAlonso 3 ай бұрын
Html code to control cam and relay: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; background-color: #f0f0f0; margin: 0; color: #333; } h1 { color: #333; } .container { background: #fff; border-radius: 10px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); padding: 20px; width: 60%; max-width: 1000px; text-align: center; border: 1px solid #ccc; } button { margin: 10px; padding: 10px 20px; font-size: 16px; cursor: pointer; border: none; border-radius: 5px; transition: background-color 0.3s; } button:disabled { background-color: #ccc; cursor: not-allowed; } #connectButton { background-color: #007bff; color: white; } #detectButton { background-color: #ccc; } input[type="range"] { width: 100%; } video, canvas { margin: 10px; border: 1px solid #ccc; } .status { font-size: 18px; margin: 5px 0; } #popup { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #ff0000; color: #fff; padding: 40px; border-radius: 10px; z-index: 1000; text-align: center; animation: blink 1.5s infinite; } #popup img { width: 100px; height: 100px; } #popup p { font-size: 48px; font-weight: bold; text-transform: uppercase; } #popup button { margin-top: 20px; background-color: #007bff; color: white; padding: 10px 20px; font-size: 16px; } @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } } #log { margin-top: 20px; background: #fff; border: 1px solid #ccc; border-radius: 10px; padding: 0px; width: 100%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } #log table { width: 100%; border-collapse: collapse; } #log th, #log td { border: 1px solid #ccc; padding: 5px; text-align: left; } #exportButton, #clearButton { background-color: #007bff; color: white; } footer { margin-top: 20px; } a { color: #007bff; text-decoration: none; font-weight: bold; } </style> </head> <body> <div class="container"> <button id="connectButton">Conectar</button> <br> <input type="range" id="sensitivitySlider" min="0" max="100" value="50"> <div class="status">Sensibilidad: <span id="sensitivityValue">50</span></div> <br> <button id="detectButton" disabled>Activar Deteccion de Movimiento</button> <br> <video id="video" width="960" height="720" autoplay></video> <canvas id="canvas" width="960" height="720" style="display:none;"></canvas> <div id="popup"> <img src="img.icons8.com/color/96/000000/error.png" alt="Alerta"> <p>INTRUSO DETECTADO!</p> <button id="dismissButton">Desactivar Alarma</button> </div> <div id="log"> <table> <thead> <tr> <th>Fecha</th> <th>Hora</th> <th>Video</th> </tr> </thead> <tbody id="logBody"> </tbody> </table> <button id="exportButton">Exportar</button> <button id="clearButton">Borrar Datos</button> </div> </div> <script> let port; let isRunning = false; let video = document.getElementById('video'); let canvas = document.getElementById('canvas'); let sensitivity = 50; let prevFrame = null; let threshold = 6000000; let intruderDetected = false; let mediaRecorder; let recordedChunks = []; let currentTimestamp; let downloadDirectory; let downloadDirectoryPath; document.getElementById('connectButton').addEventListener('click', async () => { try { port = await navigator.serial.requestPort(); await port.open({ baudRate: 9600 }); document.getElementById('detectButton').disabled = false; document.getElementById('connectButton').disabled = true; console.log('Conectado al puerto serial'); startCamera(); } catch (error) { console.error('Error al conectar al puerto serial:', error); alert('Error al conectar al puerto serial. Verifique que el dispositivo esté conectado y vuelva a intentarlo.'); } });
@KepaAlonso
@KepaAlonso 3 ай бұрын
function startCamera() { navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { video.srcObject = stream; video.play(); mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0) { recordedChunks.push(event.data); } }; mediaRecorder.onstop = () => { saveRecording(); }; }) .catch(error => { console.error('Error al acceder a la cámara:', error); alert('Error al acceder a la cámara. Verifique que la cámara esté conectada y vuelva a intentarlo.'); }); } function captureFrame() { let context = canvas.getContext('2d'); context.drawImage(video, 0, 0, canvas.width, canvas.height); return context.getImageData(0, 0, canvas.width, canvas.height); } function calculateDifference(frame1, frame2) { let diff = 0; for (let i = 0; i < frame1.data.length; i += 4) { let r = Math.abs(frame1.data[i] - frame2.data[i]); let g = Math.abs(frame1.data[i + 1] - frame2.data[i + 1]); let b = Math.abs(frame1.data[i + 2] - frame2.data[i + 2]); diff += r + g + b; } return diff; } async function monitorMovement() { if (!prevFrame) { prevFrame = captureFrame(); return; } let currentFrame = captureFrame(); let diff = calculateDifference(prevFrame, currentFrame); let changedPixels = diff; threshold = 3000000 + sensitivity * 240000; if (changedPixels > threshold && !intruderDetected) { intruderDetected = true; currentTimestamp = new Date().getTime(); document.getElementById('popup').style.display = 'block'; sendCommand([0xA0, 0x01, 0x01, 0xA2]); mediaRecorder.start(); logAlert(currentTimestamp); } prevFrame = currentFrame; } document.getElementById('sensitivitySlider').addEventListener('input', (event) => { sensitivity = event.target.value; document.getElementById('sensitivityValue').innerText = sensitivity; }); async function sendCommand(command) { try { const writer = port.writable.getWriter(); const data = new Uint8Array(command); await writer.write(data); writer.releaseLock(); } catch (error) { console.error('Error al enviar comando:', error); alert('Error al enviar comando. Verifique la conexión.'); } } document.getElementById('detectButton').addEventListener('click', () => { isRunning = !isRunning; if (isRunning) { document.getElementById('detectButton').style.backgroundColor = 'lightgreen'; monitorMovementLoop(); } else { document.getElementById('detectButton').style.backgroundColor = 'lightgray'; } }); function monitorMovementLoop() { if (isRunning) { monitorMovement(); requestAnimationFrame(monitorMovementLoop); } } document.getElementById('dismissButton').addEventListener('click', () => { document.getElementById('popup').style.display = 'none'; intruderDetected = false; isRunning = false; document.getElementById('detectButton').disabled = true; document.getElementById('detectButton').style.backgroundColor = 'lightgray'; sendCommand([0xA0, 0x01, 0x00, 0xA1]); mediaRecorder.stop(); setTimeout(() => { document.getElementById('detectButton').disabled = false; }, 2000); }); function logAlert(timestamp) { const now = new Date(); const date = now.toLocaleDateString(); const time = now.toLocaleTimeString(); const row = `<tr><td>${date}</td><td>${time}</td><td id="video-link-${timestamp}"></td></tr>`; document.getElementById('logBody').insertAdjacentHTML('beforeend', row); } async function saveRecording() { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const now = new Date(currentTimestamp); const fileName = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}_${now.getHours()}-${now.getMinutes()}-${now.getSeconds()}.webm`; // Create the file handle const fileHandle = await downloadDirectory.getFileHandle(fileName, { create: true }); // Create a writable stream for the file const writableStream = await fileHandle.createWritable(); // Write the contents of the blob to the file await writableStream.write(blob); // Close the file and release the writable stream await writableStream.close(); // Generate the file path using the downloadDirectoryPath const filePath = `${downloadDirectoryPath}/${fileName}`; // Update the table cell with the file link const videoCell = document.getElementById(`video-link-${currentTimestamp}`); videoCell.innerHTML = `<a href="${filePath}" target="_blank">${fileName}</a>`; // Clear the recorded chunks recordedChunks = []; } document.getElementById('exportButton').addEventListener('click', () => { const rows = Array.from(document.querySelectorAll('#log table tr')); const csvContent = rows.map(row => { const cells = Array.from(row.querySelectorAll('th, td')); return cells.map(cell => cell.innerText).join(','); }).join(' '); const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'log_alertas.csv'; document.body.appendChild(a); a.click(); document.body.removeChild(a); }); document.getElementById('clearButton').addEventListener('click', () => { document.getElementById('logBody').innerHTML = ''; }); async function selectDownloadDirectory() { try { const directoryHandle = await window.showDirectoryPicker(); downloadDirectory = directoryHandle; downloadDirectoryPath = directoryHandle.name; // Save the directory path } catch (error) { console.error('Error al seleccionar el directorio de descarga:', error); alert('Error al seleccionar el directorio de descarga. Inténtelo de nuevo.'); } } document.getElementById('connectButton').insertAdjacentHTML('afterend', '<button id="selectDirectoryButton">Seleccionar Carpeta de Descargas</button>'); document.getElementById('selectDirectoryButton').addEventListener('click', selectDownloadDirectory); </script> </body> </html>
@michaelmejiamoreno5521
@michaelmejiamoreno5521 3 ай бұрын
Es posible utilizar la camara del Pc como activador de on / off? es decir cuando yo estoy frente al pc active el relay
@KepaAlonso
@KepaAlonso 3 ай бұрын
es posible, tambien se podria usar el microfono y activar el rele si se detecta un ruido
@Srbrx
@Srbrx 3 ай бұрын
Uhaa, esta interesante esto, gracias por compartir!
@KepaAlonso
@KepaAlonso 4 ай бұрын
MORSE BEEP DECODER - HTML CODE <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>INTERPRETAR CODIGO MORSE</title> <style> body { font-family: Arial, sans-serif; text-align: center; margin: 50px; } canvas { border: 1px solid black; margin-top: 20px; } textarea { width: 80%; height: 100px; margin-top: 20px; } .slider-container { margin-top: 20px; } </style> </head> <body> <h1>Interpretar Codigo Morse</h1> <button id="startButton">Iniciar</button> <button id="stopButton" disabled>Detener</button> <button id="convertButton" disabled>Convertir a Texto</button> <button id="clearButton">Borrar Texto</button> <div class="slider-container"> <label for="sensitivitySlider">Sensibilidad del Volumen: <span id="sensitivityValue">10</span></label> <input type="range" id="sensitivitySlider" min="0.01" max="0.2" step="0.01" value="10"> </div> <h2>Audio</h2> <canvas id="waveformCanvas" width="400" height="200"></canvas> <h2>Beep Detectado</h2> <canvas id="beepCanvas" width="1600" height="50"></canvas> <h2>Texto Interpretado:</h2> <textarea id="outputText" readonly></textarea> <script> const morseCode = { '.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F', '--.': 'G', '....': 'H', '..': 'I', '.---': 'J', '-.-': 'K', '.-..': 'L', '--': 'M', '-.': 'N', '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R', '...': 'S', '-': 'T', '..-': 'U', '...-': 'V', '.--': 'W', '-..-': 'X', '-.--': 'Y', '--..': 'Z', '-----': '0', '.----': '1', '..---': '2', '...--': '3', '....-': '4', '.....': '5', '-....': '6', '--...': '7', '---..': '8', '----.': '9' }; const startButton = document.getElementById('startButton'); const stopButton = document.getElementById('stopButton'); const convertButton = document.getElementById('convertButton'); const clearButton = document.getElementById('clearButton'); const outputText = document.getElementById('outputText'); const sensitivitySlider = document.getElementById('sensitivitySlider'); const sensitivityValue = document.getElementById('sensitivityValue'); const waveformCanvas = document.getElementById('waveformCanvas'); const waveformCtx = waveformCanvas.getContext('2d'); const beepCanvas = document.getElementById('beepCanvas'); const beepCtx = beepCanvas.getContext('2d'); let audioContext; let analyser; let microphone; let javascriptNode; let listening = false; let morseInput = ''; let lastSignalTime = 0; let capturingSymbol = false; let beepTimes = []; const dotDuration = 0.1; // 0.1 seconds (100 milliseconds) const dashDuration = 0.3; // 0.3 seconds (300 milliseconds) const symbolGap = 0.1; // 0.1 seconds (100 milliseconds) const characterPauseDuration = 0.6; // 0.6 seconds (600 milliseconds) const wordPauseDuration = 2.0; // 2.0 seconds (2000 milliseconds) let sensitivityThreshold = 10; sensitivitySlider.addEventListener('input', () => { sensitivityThreshold = parseFloat(sensitivitySlider.value); sensitivityValue.textContent = sensitivitySlider.value; }); startButton.addEventListener('click', () => { startButton.disabled = true; stopButton.disabled = false; convertButton.disabled = true; startListening(); }); stopButton.addEventListener('click', () => { startButton.disabled = false; stopButton.disabled = true; convertButton.disabled = false; stopListening(); }); convertButton.addEventListener('click', translateMorseToText); clearButton.addEventListener('click', () => { outputText.value = ''; }); function startListening() { audioContext = new (window.AudioContext || window.webkitAudioContext)(); analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; analyser.smoothingTimeConstant = 0.8; navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { microphone = audioContext.createMediaStreamSource(stream); javascriptNode = audioContext.createScriptProcessor(2048, 1, 1); microphone.connect(analyser); analyser.connect(javascriptNode); javascriptNode.connect(audioContext.destination); javascriptNode.onaudioprocess = processAudio; listening = true; drawWaveform(); drawBeepDetection(); }) .catch(error => { console.error('Error accessing microphone:', error); }); } function stopListening() { if (microphone) microphone.disconnect(); if (analyser) analyser.disconnect(); if (javascriptNode) javascriptNode.disconnect(); if (audioContext) audioContext.close(); listening = false; } function processAudio(event) { const buffer = new Float32Array(analyser.fftSize); analyser.getFloatTimeDomainData(buffer); const now = audioContext.currentTime; const signalDetected = buffer.some(sample => Math.abs(sample) > sensitivityThreshold); if (signalDetected) { if (!capturingSymbol) { capturingSymbol = true; lastSignalTime = now; } } else if (capturingSymbol) { capturingSymbol = false; const duration = now - lastSignalTime; if (duration < dotDuration * 1.5) { morseInput += '.'; beepTimes.push({ time: now, type: 'dot' }); } else if (duration >= dotDuration * 1.5 && duration < dashDuration * 1.5) { morseInput += '-'; beepTimes.push({ time: now, type: 'dash' }); } lastSignalTime = now; console.log(`Detected Morse Input: ${morseInput}`); } else { const silenceDuration = now - lastSignalTime; if (silenceDuration >= characterPauseDuration && silenceDuration < wordPauseDuration) { morseInput += ' '; lastSignalTime = now; console.log(`Character Pause Detected: ${morseInput}`); } else if (silenceDuration >= wordPauseDuration) { morseInput += ' '; lastSignalTime = now; console.log(`Word Pause Detected: ${morseInput}`); } } } function drawWaveform() { if (!listening) return; const buffer = new Float32Array(analyser.fftSize); analyser.getFloatTimeDomainData(buffer); waveformCtx.clearRect(0, 0, waveformCanvas.width, waveformCanvas.height); waveformCtx.beginPath(); const sliceWidth = waveformCanvas.width * 1.0 / buffer.length; let x = 0; for (let i = 0; i < buffer.length; i++) { const v = buffer[i] * 200.0; const y = waveformCanvas.height / 2 + v; if (i === 0) { waveformCtx.moveTo(x, y); } else { waveformCtx.lineTo(x, y); } x += sliceWidth; } waveformCtx.lineTo(waveformCanvas.width, waveformCanvas.height / 2); waveformCtx.stroke(); requestAnimationFrame(drawWaveform); } function drawBeepDetection() { if (!listening) return; beepCtx.clearRect(0, 0, beepCanvas.width, beepCanvas.height); beepCtx.beginPath(); beepTimes.forEach(beep => { const x = (beep.time % 30) / 30 * beepCanvas.width; // Escala ajustada beepCtx.moveTo(x, 0); beepCtx.lineTo(x, beep.type === 'dot' ? 10 : 30); }); beepCtx.stroke(); requestAnimationFrame(drawBeepDetection); } function translateMorseToText() { const words = morseInput.trim().split(' '); const text = words.map(word => { return word.split(' ').map(symbol => morseCode[symbol] || '').join(''); }).join(' '); outputText.value = text; console.log(`Translated Text: ${text}`); morseInput = ''; beepTimes = []; } </script> </body> </html>
@KepaAlonso
@KepaAlonso 4 ай бұрын
MORSE SENDER - POWERSELL USB CONTROL CODE: Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Crear formulario $form = New-Object System.Windows.Forms.Form $form.Text = 'USB RELAY CONTROL' $form.Size = New-Object System.Drawing.Size(400, 500) $form.StartPosition = 'CenterScreen' # Crear fuente para los cuadros de texto $fontTextBox = New-Object System.Drawing.Font("Arial", 14) # Crear etiqueta para puerto USB $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(15, 250) $label.Size = New-Object System.Drawing.Size(180, 40) $label.Text = 'NÚMERO DE PUERTO USB:' $form.Controls.Add($label) # Crear cuadro combinado para puerto USB $comboBox = New-Object System.Windows.Forms.ComboBox $comboBox.Location = New-Object System.Drawing.Point(200, 250) $comboBox.Size = New-Object System.Drawing.Size(160, 40) $ports = [System.IO.Ports.SerialPort]::getportnames() $comboBox.Items.AddRange($ports) $form.Controls.Add($comboBox) # Crear objeto para el puerto serie (se inicializará más tarde) $KEPAALONSORELAY = $null # Crear cuadro de texto para la entrada $inputBox = New-Object System.Windows.Forms.TextBox $inputBox.Location = New-Object System.Drawing.Point(15, 20) $inputBox.Size = New-Object System.Drawing.Size(360, 40) $inputBox.Font = $fontTextBox $form.Controls.Add($inputBox) # Crear botón para convertir y enviar código Morse $sendButton = New-Object System.Windows.Forms.Button $sendButton.Location = New-Object System.Drawing.Point(15, 70) $sendButton.Size = New-Object System.Drawing.Size(360, 40) $sendButton.Text = 'Enviar' $sendButton.Enabled = $true # Inicialmente habilitado $form.Controls.Add($sendButton) # Crear cuadro de texto para la salida de código Morse $outputBox = New-Object System.Windows.Forms.TextBox $outputBox.Location = New-Object System.Drawing.Point(15, 120) $outputBox.Size = New-Object System.Drawing.Size(360, 100) $outputBox.Multiline = $true $outputBox.Font = $fontTextBox $form.Controls.Add($outputBox) # Diccionario de código Morse $morseCode = @{ 'A' = '.-'; 'B' = '-...'; 'C' = '-.-.'; 'D' = '-..'; 'E' = '.'; 'F' = '..-.'; 'G' = '--.'; 'H' = '....'; 'I' = '..'; 'J' = '.---'; 'K' = '-.-'; 'L' = '.-..'; 'M' = '--'; 'N' = '-.'; 'O' = '---'; 'P' = '.--.'; 'Q' = '--.-'; 'R' = '.-.'; 'S' = '...'; 'T' = '-'; 'U' = '..-'; 'V' = '...-'; 'W' = '.--'; 'X' = '-..-'; 'Y' = '-.--'; 'Z' = '--..'; '1' = '.----'; '2' = '..---'; '3' = '...--'; '4' = '....-'; '5' = '.....'; '6' = '-....'; '7' = '--...'; '8' = '---..'; '9' = '----.'; '0' = '-----'; ' ' = ' ' # Espacio para separar palabras } # Función para enviar un solo carácter en código Morse a través del relé y pitido por altavoz function SendCharMorse { param ($char) $dotDuration = 100 # Duración del punto en milisegundos $dashDuration = $dotDuration * 3 $symbolGap = $dotDuration $char = $char.ToString().ToUpper().Trim() # Asegurarse de que el carácter esté en mayúsculas y sin espacios en blanco if ($morseCode.ContainsKey($char)) { $morse = $morseCode[$char] foreach ($symbol in $morse.ToCharArray()) { switch ($symbol) { '.' { $KEPAALONSORELAY.Write($ON, 0, $ON.Length) [System.Console]::Beep(1000, $dotDuration) # Pitido para punto Start-Sleep -Milliseconds $dotDuration $KEPAALONSORELAY.Write($OFF, 0, $OFF.Length) } '-' { $KEPAALONSORELAY.Write($ON, 0, $ON.Length) [System.Console]::Beep(1000, $dashDuration) # Pitido para raya Start-Sleep -Milliseconds $dashDuration $KEPAALONSORELAY.Write($OFF, 0, $OFF.Length) } } Start-Sleep -Milliseconds $symbolGap } Start-Sleep -Milliseconds ($symbolGap * 6) # Espacio entre letras } } $sendButton.Add_Click({ $text = $inputBox.Text.ToUpper() if ($comboBox.Text -ne "" -and $KEPAALONSORELAY -eq $null) { $KEPAALONSORELAY = New-Object System.IO.Ports.SerialPort $comboBox.Text, 9600, None, 8, One $KEPAALONSORELAY.Open() } $outputBox.Text = "" # Limpiar el cuadro de salida foreach ($char in $text.ToCharArray()) { $charString = $char.ToString().Trim() # Convertir el carácter a cadena y eliminar espacios en blanco if ($morseCode.ContainsKey($charString)) { $morse = $morseCode[$charString] $outputBox.AppendText($morse + " ") # Añadir el código Morse del carácter actual al cuadro de salida $form.Refresh() # Refrescar el formulario para actualizar la pantalla SendCharMorse -char $charString } } [System.Windows.Forms.MessageBox]::Show("MENSAJE ENVIADO") }) # Crear matrices de bytes para encender y apagar [BYTE[]] $ON = 0xA0, 0x01, 0x01, 0xA2 [BYTE[]] $OFF = 0xA0, 0x01, 0x00, 0xA1 # Crear LinkLabel para autor $LinkLabelAuthor = New-Object System.Windows.Forms.LinkLabel $LinkLabelAuthor.Location = New-Object System.Drawing.Point(75, 300) $LinkLabelAuthor.Size = New-Object System.Drawing.Size(250, 20) $LinkLabelAuthor.LinkColor = 'BLUE' $LinkLabelAuthor.ActiveLinkColor = 'RED' $LinkLabelAuthor.Text = 'KEPA ALONSO GOIKOETXEA' $LinkLabelAuthor.Add_Click({ [System.Diagnostics.Process]::Start('kalonso9.wixsite.com/kalo') }) $form.Controls.Add($LinkLabelAuthor) # Crear LinkLabel para Wikipedia $LinkLabelWiki = New-Object System.Windows.Forms.LinkLabel $LinkLabelWiki.Location = New-Object System.Drawing.Point(75, 330) $LinkLabelWiki.Size = New-Object System.Drawing.Size(250, 20) $LinkLabelWiki.LinkColor = 'BLUE' $LinkLabelWiki.ActiveLinkColor = 'RED' $LinkLabelWiki.Text = 'MORSE CODE' $LinkLabelWiki.Add_Click({ [System.Diagnostics.Process]::Start('en.wikipedia.org/wiki/Morse_code') }) $form.Controls.Add($LinkLabelWiki) # Mostrar el formulario $form.ShowDialog() # Cerrar el puerto serie si está abierto if ($KEPAALONSORELAY -ne $null -and $KEPAALONSORELAY.IsOpen) { $KEPAALONSORELAY.Write($OFF, 0, $OFF.Length) $KEPAALONSORELAY.Close() }
@RicardoTerrazav2
@RicardoTerrazav2 5 ай бұрын
las matematicas por sí mismas y como tales son hermosas
@KepaAlonso
@KepaAlonso 5 ай бұрын
Mandelbrot Set <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Conjunto de Mandelbrot</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: black; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth; const height = canvas.height = window.innerHeight; let magnificationFactor = 300; // Factor de magnificación inicial const centerReal = -0.5; // Coordenada real del centro const centerImaginary = 0; // Coordenada imaginaria del centro const maxIterations = 1000; // Número máximo de iteraciones const animationDuration = 10000; // Duración de la animación en milisegundos (10 minutos) // Función para determinar si un punto pertenece al conjunto de Mandelbrot function mandelbrot(c_real, c_imaginary) { let real = 0; let imaginary = 0; for (let i = 0; i < maxIterations; i++) { const tempReal = real * real - imaginary * imaginary + c_real; const tempImaginary = 2 * real * imaginary + c_imaginary; real = tempReal; imaginary = tempImaginary; if (real * imaginary > 5) { return (i / maxIterations * 250); } } return 0; } // Función para dibujar el conjunto de Mandelbrot centrado en la pantalla function drawMandelbrot() { const offsetX = width / 2; const offsetY = height / 2; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { const c_real = (x - offsetX) / magnificationFactor + centerReal; const c_imaginary = (y - offsetY) / magnificationFactor + centerImaginary; const intensity = mandelbrot(c_real, c_imaginary); const color = intensity > 0 ? `hsl(0, 100%, ${intensity}%)` : 'black'; ctx.fillStyle = color; ctx.fillRect(x, y, 1, 1); } } } // Función para iniciar la animación function animate() { const startTime = Date.now(); function drawFrame() { const elapsedTime = Date.now() - startTime; ctx.clearRect(0, 0, width, height); const progress = Math.min(0.01, elapsedTime / animationDuration); magnificationFactor += progress * 30; // Aumentar el factor de magnificación gradualmente drawMandelbrot(); if (progress < 1) { requestAnimationFrame(drawFrame); } } drawFrame(); } // Iniciar la animación después de un breve retraso setTimeout(animate, 10); </script> </body> </html>
@KepaAlonso
@KepaAlonso 5 ай бұрын
Barnsley Fern <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Fractal tipo Ola</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: black; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth+20; const height = canvas.height = window.innerHeight; const scale = height / 10; // Escala para el tamaño del helecho (ajustado para cubrir la altura de la pantalla) const initialX = width / 2; const initialY = height / 2 + 380; // Coordenada inicial Y con una separación de 50 píxeles arriba const animationDuration = 600; // Duración de la animación en milisegundos (10 minutos) // Función para dibujar el helecho function drawFern(x, y, iterations) { for (let i = 0; i < iterations; i++) { const rand = Math.random(); let newX, newY; if (rand < 0.01) { newX = 0; newY = 0.16 * y; } else if (rand < 0.86) { newX = 0.85 * x + 0.04 * y; newY = -0.04 * x + 0.85 * y + 1.6; } else if (rand < 0.93) { newX = 0.2 * x - 0.26 * y; newY = 0.23 * x + 0.22 * y + 1.6; } else { newX = -0.15 * x + 0.28 * y; newY = 0.26 * x + 0.24 * y + 0.44; } ctx.fillStyle = 'green'; ctx.fillRect(initialX + newX * scale, initialY - newY * scale, 1, 1); x = newX; y = newY; } } // Función para iniciar la animación function animate() { const startTime = Date.now(); function drawFrame() { const elapsedTime = Date.now() - startTime; ctx.clearRect(0, 0, width, height); const progress = Math.min(0.1, elapsedTime / animationDuration); drawFern(0, 0, 1000000 * progress); // Incremento en el número de iteraciones if (progress < 1) { requestAnimationFrame(drawFrame); } } drawFrame(); } // Iniciar la animación después de un breve retraso setTimeout(animate, 10); </script> </body> </html>
@KepaAlonso
@KepaAlonso 5 ай бұрын
Julia Fractal <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Conjunto de Julia Animado</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: black; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth; const height = canvas.height = window.innerHeight; const maxIterations = 1000; // Número inicial de iteraciones const maxTotalIterations = 1000; // Número máximo total de iteraciones let cx = -0.7; let cy = 0.27015; let totalIterations = 0; // Función para determinar si un punto pertenece al conjunto de Julia function julia(x, y, iterations) { let zx = x / width * 3.5 - 1.8; let zy = y / height * 2 - 1; for (let i = 0; i < iterations; i++) { let temp = zx * zx - zy * zy + cx; zy = 2 * zx * zy + cy; zx = temp; if (zx * zx + zy * zy > 4) { return i / iterations * 90; } } return 0; } // Función para dibujar el conjunto de Julia progresivamente function drawJulia() { const iterationsIncrement = 5; // Incremento en el número de iteraciones por cuadro const maxFrames = maxTotalIterations / iterationsIncrement; const frameTime = 1000; // Tiempo entre cuadros en milisegundos let currentIterations = 0; function drawFrame() { ctx.clearRect(0, 0, width, height); for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const intensity = julia(x, y, currentIterations); const color = intensity > 0 ? intensity * 2.55 : 0; // Convertir a valor de 0 a 255 ctx.fillStyle = `rgb(0, 0, ${color})`; ctx.fillRect(x, y, 1, 1); } } currentIterations += iterationsIncrement; if (currentIterations <= maxIterations) { requestAnimationFrame(drawFrame); } } drawFrame(); } // Iniciar el dibujo progresivo del conjunto de Julia drawJulia(); </script> </body> </html>
@ahmadabosrea8865
@ahmadabosrea8865 5 ай бұрын
can be used to get a feedback signal from a sensor to the computer through the USB?
@KepaAlonso
@KepaAlonso 5 ай бұрын
No, only digital output
@georhodiumgeo9827
@georhodiumgeo9827 6 ай бұрын
Dam...
@KepaAlonso
@KepaAlonso 6 ай бұрын
goo.gl/maps/mTK97bLx3eJiQGLZ9
@kylobensolo5655
@kylobensolo5655 6 ай бұрын
Ich lade der mg-08/15 Ich höre Eindringlinge
@bill9540
@bill9540 6 ай бұрын
Great work on the weathering and shading…very nice👍
@Blackcat-do7wo
@Blackcat-do7wo 6 ай бұрын
Very nice 👏
@marccxxshammer6643
@marccxxshammer6643 8 ай бұрын
@selimcelik3494
@selimcelik3494 10 ай бұрын
I'm guessing, like me, that most people were wondering if they started building in the water or if the water was diverted afterwards. I'm glad to know the answer now.
@KepaAlonso
@KepaAlonso 9 ай бұрын
Appreciate the observation. Initially, the flow was diverted before intercepting the channel. This unique process presented a distinctive challenge. Thanks for tuning in and showing interest.
@nazarbulatov2122
@nazarbulatov2122 11 ай бұрын
Что за цвет был использован при покраске кузова?!
@KepaAlonso
@KepaAlonso 11 ай бұрын
Дело в том, что я использую 5 банок акриловой краски основных цветов: белого, черного, красного, желтого и синего по 500 мл каждая. Путем их смешивания я получаю все необходимые цвета для моей модели. Затем я покрываю поверхность глянцевым лаком, наношу масляные краски и в завершение использую матовый лак.
@nazarbulatov2122
@nazarbulatov2122 11 ай бұрын
@@KepaAlonso спасибо за ответ! А военный автомобиль Зис5В . Покрытый только глянцевым лаком будет смотреться не очень?! И кстати салон двигатель и колеса надо покрывать лаком? И если да то по окончанию сборке? Задаю сразу все вопросы которые интересуют, так как новичок и это моя первая модель, а другие блогеры не отвечают;) Буду рад ответу!)
@nazarbulatov2122
@nazarbulatov2122 11 ай бұрын
Так то у меня ещё много вопросов, но на Ютубе точных ответов найти не могу)
@KepaAlonso
@KepaAlonso 11 ай бұрын
Перед началом покраски тщательно очистите модель мылом и водой. Важно, чтобы поверхность была чистой от жира, так как это обеспечит хорошее сцепление краски. Наношу базовый слой серой краски с добавлением нескольких капель жидкого мыла. Важно, чтобы краска хорошо зафиксировалась; если на модели есть следы жира, например, от рук, краска может плохо держаться. Глянцевый лак используется для того, чтобы при нанесении масляных красок с растворителем, такого как агуаррас, они хорошо распределялись, создавая различные оттенки. Это можно сделать кистью и ватными тампонами, а затем убрать излишки. Обязательно наносите глянцевый лак после покрытия разноцветными слоями краски, особенно если вы собираетесь использовать наклейки. Дайте несколько дней для полного высыхания перед применением масляных красок. Будьте осторожны с избыточным использованием растворителя при нанесении масляных красок, чтобы избежать поднятия глянцевого лака. Завершающий матовый слой придаст модели более реалистичный вид, что особенно подходит для моделей военной техники, таких как танки.
@KepaAlonso
@KepaAlonso 11 ай бұрын
Я новичок и провожу эксперименты с моделями, и, из всего, что я пробовал, наилучший, более удовлетворительный и реалистичный результат я получил, нанося масляные краски поверх акрила, как я вам говорю. Речь идет о моделях типа танков и военной техники; для самолетов и гражданских транспортных средств ситуация отличается.
@KiKi-pn7is
@KiKi-pn7is Жыл бұрын
👍👍👍👍
@dvdw_graphics_crafts
@dvdw_graphics_crafts Жыл бұрын
Love the dust effect, looking realistic! ; )
@KepaAlonso
@KepaAlonso 9 ай бұрын
Thank you! I'm glad you noticed and appreciate the dust effect. Achieving realism was a key goal, so I'm thrilled that it came across effectively. Your positive feedback means a lot! 😊
@dvdw_graphics_crafts
@dvdw_graphics_crafts 9 ай бұрын
dust and mud, that's also the most fun part :D​
@jimmytwizzle7836
@jimmytwizzle7836 Жыл бұрын
Hardly jaw dropping was it. In fact it was pretty uninteresting I thought. Thumbs down.
@KepaAlonso
@KepaAlonso Жыл бұрын
😱
@TheBebelehaut
@TheBebelehaut 11 ай бұрын
Jaw scratching he meant. I think.
@MICHALMALACHOVSKY
@MICHALMALACHOVSKY Жыл бұрын
WOW WOW WOW WOW WOW
@Hyper-Tv
@Hyper-Tv Жыл бұрын
which dam it is
@slshusker
@slshusker Жыл бұрын
Those are / were excellent f er uppers.