Three Phase Inverter with Home-Built Motor

While trying to teach myself more about three phase power I built a three phase generator which was just about as simple as is possible to build. As a generator it only produces about 2 Volts, but it is enough to light up LEDs and wiring it up was a great exercise for understanding three phase power. The design and construction of the generator is outlined here: Rambling on Topics I Know Little About: An upgraded simple three phase generator design.

When I got my Arduino I realized that a great project would be to try and build a three phase inverter which can run this generator as a motor. After several failed attempts I finally got this to run. It is hooked up to a potentiometer which controls the speed of rotation and can also change the direction of rotation. It doesn't run very smoothly probably because I did not take enough care when positioning the coils but I at least can control direction of rotation fairly well and have some control over the speed of rotation.

Here is a blog post with a description of the circuit and a copy of the code I ran. Rambling on Topics I Know Little About: Three Phase 6 Pulse Inverter

Youtube video 1: Simple Three Phase Pancake Motor Video #1 - YouTube
Youtube video 2: Simple Three Phase Pancake Motor Video #2 - YouTube
Youtube video 3: Simple Three Phase Pancake Motor Video #3 - YouTube

Great work! Three phase motors are very tricky to work with. I've been wanting to develop a good start-up algorithm for BLDC motors for a while.

I found a Brushless DC motor off of a CD drive and ran it with this Arduino. It makes a much more interesting demonstration for most people since this type of motor is difficult to work with. Still, the added complexity of my inverter means that anyone seriously planning to control brushless motors should purchase an electronic speed controller https://store.diydrones.com/ArduCopter_ESC_20_Amp_p/ac-0004-08.htm. Still, using the Arduino directly does make a good way to learn how these operate.

Here is my youtube video of the cd motor running:

Here is the code being ran in the video:

int PhaseA1 =  5;     // the number of the pin controlling the High side of Phase 1
int PhaseA2 =  6;     // the number of the pin controlling the Low side of Phase 1
int PhaseB1 =  7;     // the number of the pin controlling the High side of Phase 2
int PhaseB2 =  8;     // the number of the pin controlling the Low side of Phase 2
int PhaseC1 =  9;     // the number of the pin controlling the High side of Phase 3
int PhaseC2 =  10;    // the number of the pin controlling the Low side of Phase 3

int ledStateA1 = LOW;              // ledState used to set whether that MOSFET is on or off
int ledStateA2 = LOW;             // LOW side MOSFETS are on with a HIGH
int ledStateB1 = HIGH;             // HIGH side MOSFETS are on with a LOW
int ledStateB2 = HIGH;             // At any given time 2 MOSFETS should be ON, 4 OFF
int ledStateC1 = LOW; 
int ledStateC2 = LOW; 
long previousMillis = 0;        // will store last time a cycle finished was updated
int sensorPin = A0;            // Pin which reads output from the switch controlling phase rotation
int sensorValue = 0;            // Initial sensor value

long wavelength = 100;         // wavelength of the output


void setup() {
  // set the digital pin as output:

  pinMode(PhaseA1, OUTPUT);
  pinMode(PhaseA2, OUTPUT);
  pinMode(PhaseB1, OUTPUT);
  pinMode(PhaseB2, OUTPUT);
  pinMode(PhaseC1, OUTPUT);
  pinMode(PhaseC2, OUTPUT);
}

void loop()
{
unsigned long currentMillis = millis();
sensorValue = analogRead(sensorPin);  

if(sensorValue>500){
  PhaseA1 =  5;      // the number of the LED pin
  PhaseA2 =  6; 
  PhaseB1 =  7; 
  PhaseB2 =  8; 
}
else{
  PhaseA1 =  7;      // the number of the LED pin
  PhaseA2 =  8; 
  PhaseB1 =  5; 
  PhaseB2 =  6; 
}

  int sensorValueMap =map(sensorValue, 150, 850, 1, 11);  // maps sensorValues into 11 different cases. 
                                                          // If the potentiometer did not have resistors 
                                                          // than the second two numbers would be 0 and 1024
 
 
  
switch(sensorValueMap){              // switches wavelength depending on value sent by potentiometer. 
  case 1:
    wavelength = 15;                // if the sensorValue is in case 1, than the wavelength is 15ms. 
    break;
  case 2:
    wavelength = 30;                // if the sensorValue is in case 2, than the wavelength is 30ms...
    break;
  case 3:
    wavelength = 100;
    break;
  case 4:
    wavelength = 500;
    break;
  case 5:
    wavelength = 1000;
    break;
  case 6:
    wavelength = 5000;
    break;
  case 7:
    wavelength = 1000;
    break;
  case 8:
    wavelength = 500;
    break;
  case 9:
    wavelength = 100;
    break;
  case 10:
    wavelength = 30;
    break;
   case 11:
    wavelength = 15;
    break;

}


  

unsigned long elapsed = currentMillis - previousMillis;  // elapsed is the time since the end of the last cycle
  int pulses =map(elapsed, 0, 2*wavelength, 0, 12);      // maps the elapsed time into 13 possible cases
switch (pulses){
  case 0:
  ledStateA1=HIGH;      // Sets the state for the A MOSFETs so the output from the inverter follows the correct waveform
  ledStateA2=LOW;       // Case 0 is time = 0
  ledStateB1=HIGH;      // From time=0 to time=wavelength/12 phase A is 0, phase B is Negative, phase C is Positive 
  ledStateB2=HIGH;
  ledStateC1=LOW;  
  ledStateC2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2);
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break;
  case 1:                  // Case 1 is time = wavelength/12
  ledStateA1=LOW;          // Phase A is switching to Pos
  ledStateA2=LOW;         
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateC1=HIGH;        // Phase C is switching to 0
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break;
  case 3:                  // Case 3 is time = 3*wavelength/12
  ledStateB1=HIGH;          // phase B is switching to 0
  ledStateB2=LOW;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  ledStateC1=HIGH;          //Phase C is switching to negative
  ledStateC2=HIGH;  
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break; 
  case 5:                       // Case 5 is time = 5*wavelength/12
  ledStateB1=LOW;                // Phase B is switching to positive
  ledStateB2=LOW;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  ledStateA1=HIGH;              // Phase A is switching to 0
  ledStateA2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2);            
  break;
  case 7:               // Case 7 is time = 7*wavelength/12
  ledStateA1=HIGH;       // Phase A is switching to negative
  ledStateA2=HIGH;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateC1=HIGH;      // Phase C is switching to 0
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break; 
  case 9:               // Case 9 is time = 9*wavelength/12
  ledStateC1=LOW;        // phase C is switching to positive
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  ledStateB1=HIGH;      // phase B is switching to negative
  ledStateB2=HIGH;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  break; 
  case 11:               // Case 11 is time = 11*wavelength/12
  ledStateA1=HIGH;       //Phase A is switching to 0
  ledStateA2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateB1=HIGH;      // Phase B is switching to negative
  ledStateB2=HIGH;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  break; 
  case 12:                 // Case 12 is time = 12*wavelength/12 or the end of the program
  previousMillis = currentMillis;
  break; 
}
if(pulses>12){
    previousMillis = currentMillis;          // prevents program from crashing if it misses case 12
}
}

I switched to using switch case instead of a lot of if statements which rather mysteriously allowed the motor to spin the motor at a notably higher speed. Unfortunately the speed control programming makes it run a little choppy. The Arduino seems to need to stop and think at regular intervals.

This code, without the speed control, runs faster. I can get a wavelength as short as 15ms to work, which means that the motor is spinning something around 1800 rpm.

This is the faster code, ran into a length limit on the last post:

int PhaseA1 =  5;     // the number of the pin controlling the High side of Phase 1
int PhaseA2 =  6;     // the number of the pin controlling the Low side of Phase 1
int PhaseB1 =  7;     // the number of the pin controlling the High side of Phase 2
int PhaseB2 =  8;     // the number of the pin controlling the Low side of Phase 2
int PhaseC1 =  9;     // the number of the pin controlling the High side of Phase 3
int PhaseC2 =  10;    // the number of the pin controlling the Low side of Phase 3

int ledStateA1 = LOW;              // ledState used to set whether that MOSFET is on or off
int ledStateA2 = LOW;             // LOW side MOSFETS are on with a HIGH
int ledStateB1 = HIGH;             // HIGH side MOSFETS are on with a LOW
int ledStateB2 = HIGH;             // At any given time 2 MOSFETS should be ON, 4 OFF
int ledStateC1 = LOW; 
int ledStateC2 = LOW; 
long previousMillis = 0;        // will store last time a cycle finished was updated
int sensorPin = A0;            // Pin which reads output from the switch controlling phase rotation
int sensorValue = 0;            // Initial sensor value

long wavelength = 15;           // wavelength of the output


void setup() {
  // set the digital pin as output:
  pinMode(PhaseA1, OUTPUT);
  pinMode(PhaseA2, OUTPUT);
  pinMode(PhaseB1, OUTPUT);
  pinMode(PhaseB2, OUTPUT);
  pinMode(PhaseC1, OUTPUT);
  pinMode(PhaseC2, OUTPUT);
}

void loop()
{
unsigned long currentMillis = millis();
sensorValue = analogRead(sensorPin);  
if(sensorValue>500){
  PhaseA1 =  5;      // the number of the LED pin
  PhaseA2 =  6; 
  PhaseB1 =  7; 
  PhaseB2 =  8; 
}
else{
  PhaseA1 =  7;      // the number of the LED pin
  PhaseA2 =  8; 
  PhaseB1 =  5; 
  PhaseB2 =  6; 
}
unsigned long elapsed = currentMillis - previousMillis;  // elapsed is the time since the end of the last cycle
  int pulses =map(elapsed, 0, 2*wavelength, 0, 12);



switch (pulses){
  case 0:
  ledStateA1=HIGH;      // Sets the state for the A MOSFETs so the output from the inverter follows the correct waveform
  ledStateA2=LOW;       // Case 0 is time = 0
  ledStateB1=HIGH;      // From time=0 to time=wavelength/12 phase A is 0, phase B is Negative, phase C is Positive 
  ledStateB2=HIGH;
  ledStateC1=LOW;  
  ledStateC2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2);
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break;
  case 1:                  // Case 1 is time = wavelength/12
  ledStateA1=LOW;          // Phase A is switching to Pos
  ledStateA2=LOW;         
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateC1=HIGH;        // Phase C is switching to 0
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break;
  case 3:                  // Case 3 is time = 3*wavelength/12
  ledStateB1=HIGH;          // phase B is switching to 0
  ledStateB2=LOW;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  ledStateC1=HIGH;          //Phase C is switching to negative
  ledStateC2=HIGH;  
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break; 
  case 5:                       // Case 5 is time = 5*wavelength/12
  ledStateB1=LOW;                // Phase B is switching to positive
  ledStateB2=LOW;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  ledStateA1=HIGH;              // Phase A is switching to 0
  ledStateA2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2);            
  break;
  case 7:               // Case 7 is time = 7*wavelength/12
  ledStateA1=HIGH;       // Phase A is switching to negative
  ledStateA2=HIGH;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateC1=HIGH;      // Phase C is switching to 0
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break; 
  case 9:               // Case 9 is time = 9*wavelength/12
  ledStateC1=LOW;        // phase C is switching to positive
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  ledStateB1=HIGH;      // phase B is switching to negative
  ledStateB2=HIGH;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  break; 
  case 11:               // Case 11 is time = 11*wavelength/12
  ledStateA1=HIGH;       //Phase A is switching to 0
  ledStateA2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateB1=HIGH;      // Phase B is switching to negative
  ledStateB2=HIGH;
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  break; 
  case 12:                 // Case 12 is time = 12*wavelength/12 or the end of the program
  previousMillis = currentMillis;
  break; 
}
}

9 poles and 6 magnets would work better for 3 phase. But then when I look at your code you are building a stepper motor, not a 3 phase motor. Phases A & B are changing state and phase C is always off?

No, it is three phase.

The reason you are getting confused is that right at the start of the code I have a part which switches it between an ABC rotation and an ACB rotation. This just changes the direction of rotation for the motor. Once you actually get to the part of the code which is switching states, phase C switches along with A and B.

Here is just the part of the code which switches phase C the first time it switches. The MOSFETs labeled C1 and C2 switch from both receiving a LOW signal to one being HIGH the other being LOW:

case 0:
  ledStateA1=HIGH;      // Sets the state for the A MOSFETs so the output from the inverter follows the correct waveform
  ledStateA2=LOW;       // Case 0 is time = 0
  ledStateB1=HIGH;      // From time=0 to time=wavelength/12 phase A is 0, phase B is Negative, phase C is Positive 
  ledStateB2=HIGH;
  ledStateC1=LOW;  
  ledStateC2=LOW;
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2);
  digitalWrite(PhaseB1, ledStateB1);
  digitalWrite(PhaseB2, ledStateB2);
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break;
  case 1:                  // Case 1 is time = wavelength/12
  ledStateA1=LOW;          // Phase A is switching to Pos
  ledStateA2=LOW;         
  digitalWrite(PhaseA1, ledStateA1);
  digitalWrite(PhaseA2, ledStateA2); 
  ledStateC1=HIGH;        // Phase C is switching to 0
  ledStateC2=LOW;
  digitalWrite(PhaseC1, ledStateC1);
  digitalWrite(PhaseC2, ledStateC2);
  break;

As for the 9 coils and 6 magnets or 12 coils and 8 magnets, it is somewhat arbitrary. You can get higher speeds with the lower number of poles which I suppose is an advantage. I would guess I could get higher torque with the larger number of magnets and coils though. The reason I ended up doing 12 and 8 was simply that I was building it primarily to understand three phase generators. Only later did I decide to see if I could run it as a brushless dc motor. I was pretty much copying the basic design of the coils and magnets that this person used: Polyphase Motor/Generator Page he just happened to have used 12 coils and 8 magnets so I copied that design.