0
0
Raspberry-piHow-ToBeginner · 4 min read

How to Generate SPWM Signal: Simple Steps Explained

To generate a SPWM (Sinusoidal Pulse Width Modulation) signal, compare a high-frequency triangular carrier wave with a low-frequency sinusoidal reference wave. The output pulse width varies according to the sinusoidal wave, producing a PWM signal that approximates a sine wave.
📐

Syntax

Generating an SPWM signal involves these key parts:

  • Carrier Wave: A high-frequency triangular or sawtooth waveform.
  • Reference Wave: A low-frequency sinusoidal waveform representing the desired output frequency.
  • Comparator: Compares the instantaneous values of the reference and carrier waves.
  • Output: A PWM signal where pulse widths vary according to the sinusoidal reference.

The basic operation is: SPWM output = (reference wave > carrier wave) ? HIGH : LOW.

javascript
function generateSPWM(carrierFreq, refFreq, sampleRate, duration) {
  const samples = sampleRate * duration;
  const spwmSignal = [];
  for (let i = 0; i < samples; i++) {
    const t = i / sampleRate;
    const carrier = Math.abs(2 * ((carrierFreq * t) % 1) - 1); // Triangular wave from 0 to 1
    const reference = 0.5 * (1 + Math.sin(2 * Math.PI * refFreq * t)); // Sin wave normalized 0 to 1
    spwmSignal.push(reference > carrier ? 1 : 0);
  }
  return spwmSignal;
}
💻

Example

This example generates an SPWM signal array for a 50 Hz sine wave modulated by a 1 kHz triangular carrier wave over 0.02 seconds. The output is a sequence of 1s and 0s representing the PWM pulses.

javascript
function generateSPWM(carrierFreq, refFreq, sampleRate, duration) {
  const samples = sampleRate * duration;
  const spwmSignal = [];
  for (let i = 0; i < samples; i++) {
    const t = i / sampleRate;
    const carrier = Math.abs(2 * ((carrierFreq * t) % 1) - 1); // Triangular wave
    const reference = 0.5 * (1 + Math.sin(2 * Math.PI * refFreq * t)); // Sin wave
    spwmSignal.push(reference > carrier ? 1 : 0);
  }
  return spwmSignal;
}

const carrierFreq = 1000; // 1 kHz carrier
const refFreq = 50;       // 50 Hz sine
const sampleRate = 10000; // 10 kHz sampling
const duration = 0.02;    // 20 ms duration

const spwm = generateSPWM(carrierFreq, refFreq, sampleRate, duration);
console.log(spwm.slice(0, 100));
Output
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
⚠️

Common Pitfalls

Common mistakes when generating SPWM signals include:

  • Using a carrier frequency too low, which causes poor sine wave approximation.
  • Incorrect normalization of the reference or carrier wave, leading to distorted PWM pulses.
  • Sampling frequency too low, causing aliasing and inaccurate PWM timing.
  • Not synchronizing the carrier and reference wave phases properly.

Always ensure the carrier frequency is much higher than the reference frequency and normalize waveforms between 0 and 1 before comparison.

javascript
/* Wrong: Carrier and reference not normalized */
function wrongSPWM(carrierFreq, refFreq, sampleRate, duration) {
  const samples = sampleRate * duration;
  const spwmSignal = [];
  for (let i = 0; i < samples; i++) {
    const t = i / sampleRate;
    const carrier = (carrierFreq * t) % 1; // Not triangular, not normalized 0-1
    const reference = Math.sin(2 * Math.PI * refFreq * t); // -1 to 1 range
    spwmSignal.push(reference > carrier ? 1 : 0);
  }
  return spwmSignal;
}

/* Correct: Normalize both waves between 0 and 1 */
function correctSPWM(carrierFreq, refFreq, sampleRate, duration) {
  const samples = sampleRate * duration;
  const spwmSignal = [];
  for (let i = 0; i < samples; i++) {
    const t = i / sampleRate;
    const carrier = Math.abs(2 * ((carrierFreq * t) % 1) - 1); // Triangular 0-1
    const reference = 0.5 * (1 + Math.sin(2 * Math.PI * refFreq * t)); // Sin 0-1
    spwmSignal.push(reference > carrier ? 1 : 0);
  }
  return spwmSignal;
}
📊

Quick Reference

  • Carrier Frequency: Must be much higher than reference frequency (e.g., 20x or more).
  • Reference Wave: Sinusoidal wave representing desired output frequency.
  • Normalization: Both waves scaled between 0 and 1 for proper comparison.
  • Comparator Logic: Output HIGH when reference > carrier, else LOW.
  • Sampling Rate: Should be high enough to capture waveform details accurately.

Key Takeaways

Generate SPWM by comparing a high-frequency triangular carrier wave with a low-frequency sinusoidal reference wave.
Normalize both carrier and reference waves between 0 and 1 before comparison to get accurate PWM pulses.
Use a carrier frequency at least 20 times higher than the reference frequency for smooth sine wave approximation.
Ensure the sampling rate is high enough to capture the waveform details and avoid distortion.
Common errors include improper normalization and low carrier frequency causing poor signal quality.