VB Tutor VB2022 VB2019 VB6 VB Sample Code About Us
Simple Harmonic Motion Simulation

Simple Harmonic Motion Simulation

Interactive simulation of oscillatory motion with VB6 and VB.NET code examples


Understanding Simple Harmonic Motion

Simple harmonic motion (SHM) is a type of periodic motion where the restoring force is directly proportional to the displacement and acts in the direction opposite to that of displacement. It can serve as a mathematical model for a variety of motions, such as the oscillation of a spring.

The motion is characterized by its:

  • Amplitude (A) - the maximum displacement from equilibrium
  • Frequency (f) - number of oscillations per unit time
  • Period (T) - time for one complete oscillation (T = 1/f)
  • Phase (φ) - determines the starting point of the motion

The equation for simple harmonic motion is:

x = A × cos(2πft + φ)

Simple Harmonic Motion Diagram

Interactive SHM Simulation

100
3
0
0

Implementation Code

VB6 Code
VB.NET Code
JavaScript Code
' VB6 Simple Harmonic Motion Simulation
Dim t As Integer
Dim amplitude As Double
Dim frequency As Double
Dim phase As Double

Private Sub Form_Load()
    amplitude = 100
    frequency = 0.05
    phase = 0
    Timer1.Interval = 50
End Sub

Private Sub cmdStart_Click()
    Timer1.Enabled = True
End Sub

Private Sub cmdPause_Click()
    Timer1.Enabled = False
End Sub

Private Sub cmdReset_Click()
    t = 0
    Timer1.Enabled = False
    DrawPosition
End Sub

Private Sub Timer1_Timer()
    t = t + 1
    DrawPosition
End Sub

Private Sub DrawPosition()
    ' Calculate position using SHM equation
    Dim x As Double
    x = amplitude * Cos(2 * 3.14159 * frequency * t + phase)
    
    ' Draw the oscillator at position x
    Shape1.Left = (Me.ScaleWidth / 2) + x - (Shape1.Width / 2)
    
    ' Optional: Draw the motion path
    If chkShowPath.Value = 1 Then
        DrawPath
    End If
End Sub

Private Sub DrawPath()
    ' Code to draw the oscillation path
    ' This would typically use Line or Circle methods
    ' on a PictureBox control
End Sub
' VB.NET Simple Harmonic Motion Simulation
Public Class SHMForm
    Private t As Integer = 0
    Private amplitude As Double = 100
    Private frequency As Double = 0.05
    Private phase As Double = 0
    Private isRunning As Boolean = False
    Private points As New List(Of PointF)

    Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
        isRunning = True
        Timer1.Start()
    End Sub

    Private Sub PauseButton_Click(sender As Object, e As EventArgs) Handles PauseButton.Click
        isRunning = False
        Timer1.Stop()
    End Sub

    Private Sub ResetButton_Click(sender As Object, e As EventArgs) Handles ResetButton.Click
        t = 0
        isRunning = False
        Timer1.Stop()
        points.Clear()
        PictureBox1.Invalidate()
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        t += 1
        DrawOscillator()
    End Sub

    Private Sub DrawOscillator()
        ' Calculate position using SHM equation
        Dim x As Double = amplitude * Math.Cos(2 * Math.PI * frequency * t + phase)
        
        ' Position the oscillator
        Dim centerX As Integer = PictureBox1.Width / 2
        Dim centerY As Integer = PictureBox1.Height / 2
        Dim ballX As Integer = centerX + CInt(x) - (Ball.Width / 2)
        Ball.Left = ballX
        
        ' Store point for path drawing
        If chkShowPath.Checked Then
            points.Add(New PointF(ballX + (Ball.Width / 2), centerY))
            If points.Count > 200 Then points.RemoveAt(0)
        End If
        
        ' Redraw the PictureBox
        PictureBox1.Invalidate()
    End Sub

    Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
        ' Draw equilibrium line
        Dim centerY As Integer = PictureBox1.Height / 2
        e.Graphics.DrawLine(Pens.Gray, 0, centerY, PictureBox1.Width, centerY)
        
        ' Draw motion path if enabled
        If chkShowPath.Checked AndAlso points.Count > 1 Then
            e.Graphics.DrawCurve(Pens.Blue, points.ToArray())
        End If
    End Sub
End Class
// JavaScript SHM Simulation
const canvas = document.getElementById('simulation-canvas');
const ctx = canvas.getContext('2d');
const graphCanvas = document.getElementById('graph-canvas');
const graphCtx = graphCanvas.getContext('2d');

// Initialize canvas dimensions
function initCanvas() {
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;
    graphCanvas.width = graphCanvas.offsetWidth;
    graphCanvas.height = graphCanvas.offsetHeight;
}

// Simulation variables
let amplitude = 100;
let frequency = 0.05;
let phase = 0;
let damping = 0;
let time = 0;
let isRunning = false;
let animationId;
const positions = [];

// Get control elements
const amplitudeSlider = document.getElementById('amplitude');
const frequencySlider = document.getElementById('frequency');
const phaseSlider = document.getElementById('phase');
const dampingSlider = document.getElementById('damping');
const startBtn = document.getElementById('start-btn');
const pauseBtn = document.getElementById('pause-btn');
const resetBtn = document.getElementById('reset-btn');

// Update value displays
amplitudeSlider.addEventListener('input', () => {
    amplitude = parseInt(amplitudeSlider.value);
    document.getElementById('amplitude-value').textContent = amplitude;
});

frequencySlider.addEventListener('input', () => {
    frequency = parseInt(frequencySlider.value) / 100;
    document.getElementById('frequency-value').textContent = frequencySlider.value;
});

phaseSlider.addEventListener('input', () => {
    phase = parseInt(phaseSlider.value) / 100;
    document.getElementById('phase-value').textContent = phase.toFixed(2);
});

dampingSlider.addEventListener('input', () => {
    damping = parseInt(dampingSlider.value) / 1000;
    document.getElementById('damping-value').textContent = dampingSlider.value;
});

// Button event handlers
startBtn.addEventListener('click', () => {
    if (!isRunning) {
        isRunning = true;
        animate();
    }
});

pauseBtn.addEventListener('click', () => {
    isRunning = false;
    if (animationId) {
        cancelAnimationFrame(animationId);
    }
});

resetBtn.addEventListener('click', () => {
    isRunning = false;
    time = 0;
    positions.length = 0;
    if (animationId) {
        cancelAnimationFrame(animationId);
    }
    draw();
});

// Initialize canvas
initCanvas();
window.addEventListener('resize', initCanvas);

// Main animation function
function animate() {
    if (!isRunning) return;
    
    time += 0.05;
    draw();
    animationId = requestAnimationFrame(animate);
}

// Draw the simulation
function draw() {
    const width = canvas.width;
    const height = canvas.height;
    const centerX = width / 2;
    const centerY = height / 2;
    
    // Clear canvas
    ctx.clearRect(0, 0, width, height);
    
    // Draw equilibrium line
    ctx.beginPath();
    ctx.moveTo(0, centerY);
    ctx.lineTo(width, centerY);
    ctx.strokeStyle = '#aaa';
    ctx.stroke();
    
    // Calculate position with damping
    const effectiveAmplitude = amplitude * Math.exp(-damping * time);
    const x = effectiveAmplitude * Math.cos(2 * Math.PI * frequency * time + phase);
    const ballX = centerX + x;
    const ballY = centerY;
    
    // Draw spring
    drawSpring(centerX, centerY, ballX, ballY);
    
    // Draw oscillator (ball)
    ctx.beginPath();
    ctx.arc(ballX, ballY, 20, 0, Math.PI * 2);
    ctx.fillStyle = '#5c6bc0';
    ctx.fill();
    ctx.strokeStyle = '#1a237e';
    ctx.lineWidth = 2;
    ctx.stroke();
    
    // Draw graph
    drawGraph();
}

// Draw spring between two points
function drawSpring(x1, y1, x2, y2) {
    const dx = x2 - x1;
    const dy = y2 - y1;
    const distance = Math.sqrt(dx * dx + dy * dy);
    const segments = 16;
    const segmentLength = distance / segments;
    
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    
    for (let i = 1; i <= segments; i++) {
        const x = x1 + (dx * i) / segments;
        let y;
        
        if (i % 2 === 0) {
            // Bottom of coil
            y = y1 + (dy * i) / segments - 10;
        } else {
            // Top of coil
            y = y1 + (dy * i) / segments + 10;
        }
        
        ctx.lineTo(x, y);
    }
    
    ctx.strokeStyle = '#888';
    ctx.lineWidth = 2;
    ctx.stroke();
}

// Draw position graph
function drawGraph() {
    const width = graphCanvas.width;
    const height = graphCanvas.height;
    const centerY = height / 2;
    
    // Clear graph
    graphCtx.clearRect(0, 0, width, height);
    
    // Draw time axis
    graphCtx.beginPath();
    graphCtx.moveTo(0, centerY);
    graphCtx.lineTo(width, centerY);
    graphCtx.strokeStyle = '#aaa';
    graphCtx.stroke();
    
    // Add current position to history
    const effectiveAmplitude = amplitude * Math.exp(-damping * time);
    const x = effectiveAmplitude * Math.cos(2 * Math.PI * frequency * time + phase);
    positions.push({time, x});
    
    // Keep only the most recent points
    if (positions.length > 200) {
        positions.shift();
    }
    
    // Draw graph line
    if (positions.length > 1) {
        graphCtx.beginPath();
        const startIndex = Math.max(0, positions.length - width / 2);
        
        for (let i = startIndex; i < positions.length; i++) {
            const point = positions[i];
            const graphX = width - (positions.length - i) * 2;
            const graphY = centerY - point.x * 0.5;
            
            if (i === startIndex) {
                graphCtx.moveTo(graphX, graphY);
            } else {
                graphCtx.lineTo(graphX, graphY);
            }
        }
        
        graphCtx.strokeStyle = '#e91e63';
        graphCtx.lineWidth = 2;
        graphCtx.stroke();
    }
}

// Initial draw
draw();

The Physics Behind SHM

Key Concepts

  • Hooke's Law: The restoring force F is proportional to the displacement x: F = -kx
  • Equation of Motion: Applying Newton's second law: m(d²x/dt²) = -kx
  • Solution: x(t) = A cos(ωt + φ), where ω = √(k/m)
  • Energy: Total energy E = ½kA² remains constant in ideal SHM

Real-World Applications

  • Pendulum clocks
  • Musical instruments (vibrating strings, air columns)
  • Seismometers for detecting earthquakes
  • Automobile suspension systems
  • Atomic vibrations in crystals
SHM Applications

Learning Exercise

Modify the simulation to include:

  1. A mass parameter that affects the oscillation frequency
  2. A spring constant parameter
  3. An energy display showing kinetic and potential energy

Observe how changing these parameters affects the motion according to the equations:

ω = √(k/m)
T = 2π√(m/k)