Help required for a few tweaks to programming algorithm (BLDC control)

So I already have a 3 phase inverter that I have to use in controlling a high speed bldc motor which basically drives a cryo chamber which further cools a gas.

I have been trying various algorithms to drive the motor using arduino. the thing is, the code ive developed works, but ive only been able to achieve 25 percent of the motor's rated speed. This is a reverse engineering project, so basic details about the motor are not known, so im basically beating around the bush.
the motor is sensored, which makes coding it's drive easier. now, all i'm asking is, is it possible to kick up the frequency of the pwm signals to make it drive faster?

//const int FULL_TIME = 25000;
//const int STEP_TIME = FULL_TIME / 6;
//int count = 0;
const int DEAD_TIME = 10;

int HallState1; //Variables for the three hall sensors (3,2,1)
int HallState2;
int HallState3;
int HallVal = 1; //binary value of all 3 hall sensors

//int mspeed = 0; //speed level of the motor
//int bSpeed = 0; //braking level
int throttle = 0; //this variable is used with analog in to measure the position of the throttle potentiometer


// Pins to write to
const int DRIVER_PIN2 = 7;
const int DRIVER_PIN5 = 8;
const int DRIVER_PIN6 = 9;
const int DRIVER_PIN3 = 10;
const int DRIVER_PIN4 = 11;
const int DRIVER_PIN1 = 12;

void setup() {
//  count = 0;

  pinMode(A2,INPUT);    
  pinMode(A3,INPUT);    
  pinMode(A4,INPUT);      
  pinMode(A0,INPUT);   
  
  pinMode(DRIVER_PIN1, OUTPUT);
  pinMode(DRIVER_PIN2, OUTPUT);
  pinMode(DRIVER_PIN3, OUTPUT);
  pinMode(DRIVER_PIN4, OUTPUT);
  pinMode(DRIVER_PIN5, OUTPUT);
  pinMode(DRIVER_PIN6, OUTPUT);


//  digitalWrite(DRIVER_PIN1, LOW);
//  digitalWrite(DRIVER_PIN2, LOW);
//  digitalWrite(DRIVER_PIN3, LOW);
//  digitalWrite(DRIVER_PIN4, HIGH);
//  digitalWrite(DRIVER_PIN5, HIGH);
//  digitalWrite(DRIVER_PIN6, HIGH);
throttle = analogRead(A0); //value of the throttle potentiometer
 // mspeed = map(throttle, 0, 1023, 0, 255); //motoring is mapped to the top half of potentiometer
   // int prescalerVal = 0x07; //create a variable called prescalerVal and set it equal to the binary number "00000111"                                                       number "00000111"                                                      number "00000111"
  //TCCR1B &= ~prescalerVal; //AND the value in TCCR1B with binary number "11111000"

  //Now set the appropriate prescaler bits:
//  int prescalerVal2 = 1; //set prescalerVal equal to binary number "00000001"
  //TCCR1B |= prescalerVal2; //OR the value in TCCR0B with binary number "00000001"
  
  // Set PWM for pins 3,11 to 32 kHz (Only pin 11 is used in this program)
  //First clear all three prescaler bits:
 // TCCR2B &= ~prescalerVal; //AND the value in TCCR2B with binary number "11111000"
 // TCCR2B |= prescalerVal2; //OR the value in TCCR2B with binary number "00000001"//First clear all three prescaler bits:

 // TCCR4B &= ~prescalerVal; //AND the value in TCCR4B with binary number "11111000"
 // TCCR4B |= prescalerVal2; //OR the value in TCCR4B with binary number "00000001"//First clear all three prescaler bits:


 digitalWrite(DRIVER_PIN4, LOW);
    delayMicroseconds(throttle/6);
    digitalWrite(DRIVER_PIN1,LOW);
    digitalWrite(DRIVER_PIN3, LOW);
    digitalWrite(DRIVER_PIN5, HIGH); // this is mspeed
    digitalWrite(DRIVER_PIN2, LOW);
    digitalWrite(DRIVER_PIN6, HIGH); // this is 255


     //Serial.begin(115200);

  
}

void loop() {


  throttle = analogRead(A0); //value of the throttle potentiometer
  
  int delay = map(throttle, 0, 1023, 0, 50); 
 
  HallState1 = digitalRead(A2);  
  HallState2  = digitalRead(A3); 
  HallState3  = digitalRead(A4); 
 
   
  HallVal = (HallState1*4) + (2*HallState2) + (HallState3);
  
  delayMicroseconds(delay/6);
  switch(HallVal) {
  case 4:
 //   analogWrite(DRIVER_PIN4, 0);
    delayMicroseconds(DEAD_TIME);
    digitalWrite(DRIVER_PIN1, LOW);//0
   // analogWrite(DRIVER_PIN3, 0);
    digitalWrite(DRIVER_PIN5, HIGH); //mspeed
//    analogWrite(DRIVER_PIN2, 0);
//    analogWrite(DRIVER_PIN6, 255);
    break;
  case 6:
     digitalWrite(DRIVER_PIN4, HIGH);//255
delayMicroseconds(DEAD_TIME);
 //   analogWrite(DRIVER_PIN1, mspeed);
 //   analogWrite(DRIVER_PIN3, 255);
//    analogWrite(DRIVER_PIN5, 255);
//    analogWrite(DRIVER_PIN2, 0);
    digitalWrite(DRIVER_PIN6, LOW);//0
    break;
  case 2:
    delayMicroseconds(DEAD_TIME);
//    analogWrite(DRIVER_PIN1, 255);
    digitalWrite(DRIVER_PIN3, HIGH);//mspeed
    digitalWrite(DRIVER_PIN5, LOW);//0
 //   analogWrite(DRIVER_PIN4, 255);
//    analogWrite(DRIVER_PIN6, mspeed);
 //   analogWrite(DRIVER_PIN2, 255);
    break;
  case 3:
      delayMicroseconds(DEAD_TIME);
//    analogWrite(DRIVER_PIN1, 255);
 //   analogWrite(DRIVER_PIN3, mspeed);
 //   analogWrite(DRIVER_PIN5, 255);
   digitalWrite(DRIVER_PIN4, LOW);//0
 //   analogWrite(DRIVER_PIN6, 255);
    digitalWrite(DRIVER_PIN2, HIGH); //255
    break;
  case 1:
      delayMicroseconds(DEAD_TIME);
   digitalWrite(DRIVER_PIN1, HIGH); //mspeed
    digitalWrite(DRIVER_PIN3, LOW); //0
//    analogWrite(DRIVER_PIN5, 0);
//    analogWrite(DRIVER_PIN4, mspeed);
//    analogWrite(DRIVER_PIN6, 255);
//    analogWrite(DRIVER_PIN2, 255);
    break;
  case 5:
      delayMicroseconds(DEAD_TIME);
//     analogWrite(DRIVER_PIN1, 255);
//    analogWrite(DRIVER_PIN3, 255);
//    analogWrite(DRIVER_PIN5, mspeed);
//    analogWrite(DRIVER_PIN4, 255);
    digitalWrite(DRIVER_PIN6, HIGH); // 255
    digitalWrite(DRIVER_PIN2, LOW); //0
    break;
  }
  //count = (count + 1) % 6;
}

Ignore the commented out stuff.
Also, is it possible to generate the sgnals using timers? because syncing 3 timers together with a difference of exactly 120 degrees in angle looks impossible. I cant seem to wrap my head around it. Any help would be appreciated. I'll code it myself obviously, I just need more options. especially when it comes to algorithm. Is there a better way to do this?

Basic objective here, kicking up the frequency!
this code works btw

Bump!! I really need lots of help with this guys!!!!

musanaqvi110:
Ignore the commented out stuff.

No. It's up to you to remove it.

Well then, don't ignore it. Any chances of improving the algorithm? Is there any possibility of using timers? is it possible to drive the motor at frequencies greater than 20 k?

What is the output to the motor now? Are you using an oscilloscope to check the frequency you are sending now?

edit: Why are you using a 3 phase inverter? Can you be more specific about the BLDC motor?

The images of the schematic are attached. The modeled motor is 3 poled. This code should work with it. The issue is, no matter what i do, the motor's speed doesnt change. It should atleast achieve a speed closer to it's rated rpm. It is just stuck at 300 rpm. This is just a model. The hardware works with the motor that i'm using it with.
The algorithm may be faulty, in which case, do suggest a better one.

Logically, as the potentiometer value changes, the delay routine should help change the frequency. But it just doesnt work. As soon as the simulation is run, the motor runs up to 300 rpm, and then it's value doesnt change.
I havent used timers because i simply cant understand why people would use them. Obv the timers should help bring more to the table by amping up the frequency, but how? what I understand is, that as soon as a smaller value is put into the timer count register, and as soon as the interrupt flag is be raised, digitalwrite would be used to set the values high or low according to the lookup table but that too in the ISR. Wouldnt that make the effort pointless? As the delays incurred with each instruction cycle would add up and render the frequency lower than what's required.

The maximum frequency would then be generated if the routine is called after every count of the timer, or the timer's interrupt flag is raised after every count.

In the ISR, I would first check the hall effect sensor state, look up the table, and assign values to the port pins.

Would this approach bring more frequency to the table? I.e. using a single timer.

I have read articles where people have used multiple timers, but how would they sync them for the signals to be 120 degrees in phase apart?

motor.JPG

1 Like

Depending on the number of poles in the motor, and the inverter outputs 60Hz, then 300 rpm sounds about right. Normally you want to use a DC power supply.

Yeah, but, is it possible to kick the speed up? That's what required. What would you suggest I do with the code to kick it up, atleast near to 80 to 90 percent of the rated rpm?

I think you need a BADCPS (Big Ass DC Power Supply). What voltage/currentl is the motor rated at?

12v. In the proteus model atleast. Is it possible to increase the frequency from 60 hz? Changing the pot values arent helping me. What would you suggest?

Amp rating on motor?

1000 RPM. Single pair of poles. 12v rated voltage.

12v is the voltage rating. What amperage does the motor require?

If this was my project, maybe a r/c ESC?

I guess I'll have to delve into the details. The objective was to reverse engineer a crygenic chamber. It includes a small but powerful 3 pair pole motor. Information regarding it's rated RPM is not known, which I'll probably get to know after developing a speed calculator based on the motor's hall effect sensors. I have been able to run the motor, but only at 30 percent. The motor literally roars when it's run by the manufacturers circuitry and the sound is very feeble when I run it using my circuit. I have been able to tell that the drive is given at frequencies of 3.5 to 5 kHz, and the voltage levels measured are around 30 to 36 volts. I already have a snubber circuit inplace to cater for the back emf or any current spikes for that matter. I can control the speed, from 0 percent to about 30 percent, which is based on the proteus model. So I'm just testing it out on a model first, and if I'm able to get it to run faster, the code would be able to run on the said motor as well.

I've already tested out various esc's. They were my primary option. For some reason, they ran outrunners and inrunners just fine, but they were never able to run the motor in the chamber. We tried everything and that's why we opted to design our very own drive circuitry.

All I want is for the inverter to give more frequency, atleast upto 10 kilohertz. With my current code, is it possible? Or would I have to use timers?

When I asked you about the voltage rating on the motor, you replied 12v. Then you post this:

I have been able to tell that the drive is given at frequencies of 3.5 to 5 kHz, and the voltage levels measured are around 30 to 36 volts.

Is there no ID plate on the motor?

Nope. Shady stuff right?
All I want to do is kick up the frequency. It's all hit and trial after. Is that possible?

With the correct equipment, I can.

Not knowing anything about the equipment you are using, I don't know.

Do you have any info on the inverter? Is it a DC to AC 60Hz inverter?

Depends on the code brother. Im writing the code myself right now. The inverter can handle higher frequencies. With an IGBT, I can basically juice higher frequencies out as well. It's just a 3 phase bridge. Not an inverter. An inverter would need a boost circuit, which obv isnt part of the schematics.

Trust me, the motor runs atleast at around 9000 rpms. It has to cool down a thermal detector that is installed inside a thermal imaging device.

It's the code that's making the inverter run at 60 Hz. I just came across a very simple timer1 library, and putting the lookup table within the timer1.interrupt() routine. The potentiometer value gets read during each interrupt and the value is read as the timer's period, with the timer being initialized accordingly in the isr.

Basically, making the bit transitions faster should make the inverter put out more frequency.

You say you can "juice" higher frequencies out of it, and that will increase the rpm. If you can do that, then what is your problem?

Your answers are too cryptic. I don't think i can help you. Maybe someone else can figure out what you are doing.

Shouldnt that be the only way?

heres the motor info,

three pairs of poles

Power= 13W

That's all I have.

Is any more information necessary? I can post the commutation sequence necessary as well.