DEV Community

Hedy
Hedy

Posted on

How to measure phase difference with STM32?

Measuring phase difference between two signals (e.g., voltage and current) with an STM32 microcontroller involves capturing timing or zero-crossing events using its built-in peripherals like timers, ADCs, or comparators. Here’s a step-by-step guide:

Methods to Measure Phase Difference
1. Zero-Crossing Detection (Digital Input)
Principle: Measure time difference between zero-crossings of two signals.

Hardware Setup:

  • Condition signals to 0–3.3V (use op-amp comparators or Schmitt triggers).
  • Connect signals to GPIO pins (e.g., PA0, PA1) with interrupt support.

STM32 Peripherals:

  • TIM (Timer): Capture timestamps of zero-crossing edges.
  • EXTI (External Interrupt): Trigger on rising/falling edges.

Code Example (HAL Library)

c
// Configure GPIO and EXTI for zero-crossing detection
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
  static uint32_t time1, time2;
  if (GPIO_Pin == GPIO_PIN_0) { // Signal 1
    time1 = TIM2->CNT;
  } else if (GPIO_Pin == GPIO_PIN_1) { // Signal 2
    time2 = TIM2->CNT;
    uint32_t phase_diff = abs(time2 - time1); // Timer ticks
    float phase_deg = (phase_diff * 360.0) / TIM_PERIOD; // Convert to degrees
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Analog Cross-Correlation (ADC + Timer)
Principle: Sample both signals with ADC and compute phase shift mathematically.

Hardware Setup:

  • Use dual ADC mode (STM32F3/F4/H7) or simultaneous sampling.
  • Feed signals to ADC channels (e.g., PA0, PA1).

Algorithm:

Apply cross-correlation or FFT to find time delay.

Code Example (Dual ADC)

c
// Configure ADC in dual mode
ADC_HandleTypeDef hadc1, hadc2;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc1_buffer, BUFFER_SIZE);
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc2_buffer, BUFFER_SIZE);

// Process buffers (e.g., find peak delay)
void Process_ADC_Data() {
  int max_corr = 0;
  int best_lag = 0;
  for (int lag = -BUFFER_SIZE/2; lag < BUFFER_SIZE/2; lag++) {
    int corr = 0;
    for (int i = 0; i < BUFFER_SIZE; i++) {
      if (i + lag >= 0 && i + lag < BUFFER_SIZE) {
        corr += adc1_buffer[i] * adc2_buffer[i + lag];
      }
    }
    if (corr > max_corr) {
      max_corr = corr;
      best_lag = lag;
    }
  }
  float phase_deg = (best_lag * 360.0) / BUFFER_SIZE;
}
Enter fullscreen mode Exit fullscreen mode

3. Timer Input Capture (High-Frequency Signals)
Principle: Use timer input capture to measure pulse timing.

Hardware Setup:

Connect signals to timer channels (e.g., TIM1_CH1, TIM2_CH2).

STM32 Peripherals:

Input Capture Mode: Records timestamps on rising/falling edges.

Code Example (PWM Phase Difference)

c
// Configure TIM1 in input capture mode
TIM_HandleTypeDef htim1;
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // Signal 1
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2); // Signal 2

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
  static uint32_t time1, time2;
  if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
    time1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
  } else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
    time2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
    uint32_t phase_diff = abs(time2 - time1);
    float phase_deg = (phase_diff * 360.0) / htim->Instance->ARR;
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Considerations
1. Signal Conditioning:

  • For AC signals, use op-amp circuits to scale and clamp voltages.
  • Add low-pass filters to reduce noise.

2. Timer Resolution:

Higher timer clock = better accuracy (e.g., 72 MHz on STM32F4).

3. Frequency Range:

  • Zero-crossing: Best for 50/60 Hz power lines.
  • ADC + FFT: Suitable for higher frequencies (1 kHz–10 kHz).

4. STM32 Peripherals:

  • High-end models (H7): Use hardware accelerators (e.g., HRTIM, FD CAN) for precision.
  • Low-end models (F0): Rely on basic timers/ADC.

Example Calculation
If timer period = 1000 ticks and phase difference = 200 ticks:

Phase (degrees)=(200/1000)×360=72∘

Troubleshooting

  • Noisy Signals: Increase hysteresis in comparators or use software debouncing.
  • ADC Overflow: Adjust sampling rate or buffer size.
  • Timer Overflow: Use 32-bit timers (e.g., TIM2 on STM32F4) for long intervals.

Conclusion
For low-frequency signals (50/60 Hz), zero-crossing detection is simple and effective. For higher frequencies, use ADC + FFT or timer input capture. The STM32’s flexible peripherals make it ideal for precise phase measurements.

Top comments (0)