Center Aligned PWM for Space Vector Modulation?

Is there an easy way to configure an Arduino's PWM outputs to be center aligned for space vector modulation or am I going to have to bit-bang it?

Which arduino?

1 Like

That's a Phase Correct PWM mode, if available on your µC.

1 Like

Preferably on a Teensy 4.X, but I was curious about Arduino's in general.

For now, though, I think I'm just going to use this library

@Power_Broker Can I please get in touch with you. I am a student trying to make the car heads up display. Would me the world!

This project is a little outdated (both software and hardware), but should be a good starting point. Beyond that, please create your own separate forum thread and others should be available to help.

1 Like

Ya, that's what I am attempting to follow. Is there anyway I could connect with you? Really love your work and Youtube

Thanks! I really appreciate it, but I don't connect with strangers online. There are plenty of good engineers here on the forum willing to help. I poke in from time to time, but not very often anymore. Good luck with the project!

As a quick tip: I updated my HUD design to something much simpler (only using a Teensy 4.1 w/ HC-05 BT module). I don't have the ability to use wifi since I axe'd the ESP32, but that was a feature I never really used anyway. Now the HUD is a lot more reliable and is in a smaller form factor. I also moved the PCB (that was miniaturized with SMD components) to the back of the inside of the HUD and bounced the LED lights off a mirror before hitting the combiner. This allows the display to feel more like a real HUD plus increases LED visibility during daylight since the LEDs are always "in the shade" of the HUD enclosure. I've been meaning to update the project GitHub, but haven't gotten around to it since I'm busy with other stuff

A post was split to a new topic: Receiving NODARP with a timeout detected with overflow of 0ms in ArduHUD project

In case anyone is interested, I was able to get center aligned PWM for BLDC motor control working using this youtube video and this sketch running on a Teensy 4.0:

#include "TeensyTimerTool.h"




const int FULL_PERIOD = 50; // 50us -> 20kHz

const int A_PIN = 0;
const int B_PIN = 1;
const int C_PIN = 10;




using namespace TeensyTimerTool;




PeriodicTimer foc_timer;

OneShotTimer a_rise_timer;
OneShotTimer b_rise_timer;
OneShotTimer c_rise_timer;

OneShotTimer a_fall_timer;
OneShotTimer b_fall_timer;
OneShotTimer c_fall_timer;




float alpha = 0;




FASTRUN void a_rise_timer_callback() { digitalWriteFast(A_PIN, HIGH); }
FASTRUN void b_rise_timer_callback() { digitalWriteFast(B_PIN, HIGH); }
FASTRUN void c_rise_timer_callback() { digitalWriteFast(C_PIN, HIGH); }
FASTRUN void a_fall_timer_callback() { digitalWriteFast(A_PIN, LOW);  }
FASTRUN void b_fall_timer_callback() { digitalWriteFast(B_PIN, LOW);  }
FASTRUN void c_fall_timer_callback() { digitalWriteFast(C_PIN, LOW);  }




// https://www.youtube.com/watch?v=nh9TD2M2r-o
FASTRUN void foc_timer_callback()
{
  float V_a = 0.5 + (0.5 * sin(radians(alpha)));
  float V_b = 0.5 + (0.5 * sin(radians(alpha) - radians(120)));
  float V_c = 0.5 + (0.5 * sin(radians(alpha) - radians(240)));

  float V_max;
  float V_min;

  if ((V_a >= V_b) && (V_a >= V_c))
    V_max = V_a;
  else if ((V_b >= V_a) && (V_b >= V_c))
    V_max = V_b;
  else
    V_max = V_c;

  if ((V_a <= V_b) && (V_a <= V_c))
    V_min = V_a;
  else if ((V_b <= V_a) && (V_b <= V_c))
    V_min = V_b;
  else
    V_min = V_c;
  
  float V_cm = -(V_max + V_min) / 2;

  V_a += V_cm;
  V_b += V_cm;
  V_c += V_cm;
  
  V_a *= (2 / sqrt(3));
  V_b *= (2 / sqrt(3));
  V_c *= (2 / sqrt(3));
  
  V_a += 0.5;
  V_b += 0.5;
  V_c += 0.5;
  
  int T_a = round(FULL_PERIOD * V_a);
  int T_b = round(FULL_PERIOD * V_b);
  int T_c = round(FULL_PERIOD * V_c);
  
  a_rise_timer.trigger((FULL_PERIOD - T_a) / 2);
  b_rise_timer.trigger((FULL_PERIOD - T_b) / 2);
  c_rise_timer.trigger((FULL_PERIOD - T_c) / 2);

  a_fall_timer.trigger(((FULL_PERIOD - T_a) / 2) + T_a);
  b_fall_timer.trigger(((FULL_PERIOD - T_b) / 2) + T_b);
  c_fall_timer.trigger(((FULL_PERIOD - T_c) / 2) + T_c);
}




void setup()
{
  Serial.begin(115200);

  foc_timer.begin(foc_timer_callback, FULL_PERIOD);
  
  a_rise_timer.begin(a_rise_timer_callback);
  b_rise_timer.begin(b_rise_timer_callback);
  c_rise_timer.begin(c_rise_timer_callback);

  a_fall_timer.begin(a_fall_timer_callback);
  b_fall_timer.begin(b_fall_timer_callback);
  c_fall_timer.begin(c_fall_timer_callback);

  pinMode(A_PIN, OUTPUT);
  pinMode(B_PIN, OUTPUT);
  pinMode(C_PIN, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  
  digitalWriteFast(3, HIGH);
  digitalWriteFast(4, HIGH);
  digitalWriteFast(5, HIGH);
}




void loop()
{
  if (alpha < 359.9)
    alpha += 0.1;
  else
    alpha = 0;

  delayMicroseconds(20);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.