📜 ⬆️ ⬇️

Scalar chastotnik for single-phase asynchronous motor

To begin with, each programmer must have a lathe. Well ... Or, at least, I should have it. And even without CNC. This is my dream.

And the dream came true. Machine bought, brought, put in the parking lot and ... We should turn it on. And turn it on is not so easy. And if you do not look for simple ways, then you need a "chastotnik", but scientifically: a frequency converter. And let me in this layman, but I did it.



And with the connection of the engine and start interesting. By myself, I'm in such a layman, there is some general knowledge, but I really had no idea how it really works. And when, instead of the expected 3 pins of 3 rhythms, I saw 4, and not even 3 windings with a common point, but some 2, and even with different resistance ... Well, I, ahem, let's say - "surprised."
')
So, the engines. They are three-phase, three-phase, triangle-connected through capacitors and ... single-phase capacitor.

Three-phase - "full" asynchronous. 3 windings, in a good way included by a star and hung on full 3 phases. Well, or 3-phase chastotnik, of which the shaft on Ali.

Three-phase + triangle + capacitors. Here we are already losing in efficiency, power and torque, well, yes, if there are no 3 phases, then there is quite a solution. Cheap, easy, reliable, angry.

Single phase capacitor

Here about them that will be discussed. In general, such engines are very common. These are the fans of the projectors' motors and drives of some watches, and motors for small sandpaper and other applications where high power is not needed, but the advantages of asynchronous units are needed: great reliability + speed, depending only on the frequency of the supply voltage.

The basic scheme of inclusion (the picture is not mine, honestly found on the Internet):



In general, roughly, the principle is as follows: There is a starter winding, it induces an emf in a closed-loop rotor. With a phase shift, the work winding is turned on. It "pushes away" the magnetized anchor, rotation begins. When you turn at a certain angle, everything repeats. The motor starts spinning.

Total - you need 2 phases shifted to a certain angle. Usually it is 90 degrees. This is provided by the starting capacitor. Well, after a set of turns - the anchor starts working from the working winding itself and the starter winding can even be turned off altogether. Well, or power from the working capacitor, significantly less capacity.

But this is all theory. But in practice, what do you want? I want chastotnik. What would itself accelerated, braked, spinning in both directions, well, with different speeds, of course! And here it becomes more complicated. The fact that such chastotnikov on sale at times less. And they cost many times more. In general - exotic.

But if you think so, then the difference from the 3 phase is not so great. And you can even use the same circuitry. At the same time, there are the same 3 branches: common, starter winding, working winding. And it's all about the firmware. And that means it can be done. And let it be not vector control with a bunch of math, but a simple scalar, but ... as I can.

So - what is required. First, let's look at the sine and cosine graphs (we have the same 90 degree offset) CONDITIONALLY, it will look like this:



Those. The task is elementary: we “pull” a common ground to the ground, feed a pack of positive impulses into the starter winding, feed a pack of impulses into the working one. Then we pull up the common one to the plus and feed a pack of negative impulses to the starter, and then to the working winding. So roughly we get an imitation of polarity reversal and phase shift. The frequency will depend on how often we do this.

In general, the theory is simple. As an ATMega 328 controller with an Arduin bootloader (yes, in fact, Arduin itself, just without any extra binding), as an IR2132 driver (old, but not with IR2136) and IRG4BC30 output keys. For my 1.1kW-th motor is more than enough.

(If you repeat the scheme, then the board is simply made, a sketch is poured into the Arduino Duemilanove, then the Mega328 is pulled out and soldered into the board. Done.)

But further ... Then I plunged into the wonderful world of inductances and power electronics. And everything turned out to be not so simple as it was thought at the beginning:

1. The speed of opening and closing keys is important. Deadtime is VERY important.
2. Turning on the ballast - always using a diode turned positive on the power filter capacitor. Otherwise, overshoot when removing the load from the inductance just disrupts power IGBTs.
3. Cooling. On the board, small radiators are bad. Either overheat, or need to blow. But if to blow, then all metal suspension from the machine, sooner or later, will short out something and it will be bang.
3+. Mica, or rather VERY THIN mica, is bad. It breaks through and it turns out that in the title of the article. At the same time, silicone thermal pads are worse than thermal conductivity. Well, pottery ... I do not have it.
4. Braking by the method of a long pack of pulses of one polarity per winding, quickly overheats the transistors and they burn. And also, the motor springs up and turns up to 3 thousand revolutions and stopped for 0.3 seconds to 0 very fun jumping.
5. When everything works for you and you relax, turn on the circuit without ballast and press start - it will be bang. This also leads to driver replacement.

Sketch: Now implemented rotation in both directions with a smooth tuning of the frequency of 25-75Hz with a step of 0.25. There was an idea with a brake. Now commented out and it will be necessary to change the scheme. Namely, the idea is this: I correctly gave impulses of one polarity, BUT. This should be done through the ballast resistance of a separate key.

The power part: the scheme will still be refined, but at the moment the machine is in an unheated room and it is extremely difficult to work with it because of the freezing of oil.

Sketch
#define Hi_ST 10 // #define Hi_WK 11 // #define Hi_M 12 // #define Lo_ST 7 #define Lo_WK 8 #define Lo_M 9 #define SoftStart 6 //    #define RelBrake 1 #define LedFwd 4 // "" #define LedRew 5 // "" #define LedStp 13 //  #define CmdFwd 2 // "" #define CmdRew 3 // ""   - . #define ValFwd 4 // "" 720 #define ValRew 5 // "" 450 #define RemoteVal 0 //720 + 450 .   . 1.2         750,  1.5 int nn = 0; //  (    " ") byte WkState = 0; byte OldRemVal = 0; //    int SoftStartMotor = 0; //     . void setup() { pinMode(CmdFwd, INPUT); pinMode(CmdRew, INPUT); pinMode(Hi_ST, OUTPUT); pinMode(Hi_WK, OUTPUT); pinMode(Hi_M, OUTPUT); pinMode(Lo_ST, OUTPUT); pinMode(Lo_WK, OUTPUT); pinMode(Lo_M, OUTPUT); pinMode(SoftStart, OUTPUT); pinMode(RelBrake, OUTPUT); pinMode(LedFwd, OUTPUT); pinMode(LedRew, OUTPUT); pinMode(LedStp, OUTPUT); digitalWrite(RelBrake, LOW); AllOff(); delay(1500); digitalWrite(SoftStart, HIGH); Indicate(); } void loop() { byte CurRemVal = 0; int RemVal = analogRead(RemoteVal); if (RemVal > 380 && RemVal < 520) { CurRemVal = 2; } if (RemVal > 600 && RemVal < 800) { CurRemVal = 1; } // bool cmdF = digitalRead(CmdFwd); bool cmdR = digitalRead(CmdRew); if (CurRemVal != OldRemVal) { OldRemVal = CurRemVal; if (CurRemVal == 0) {cmdF = true; cmdR = true;} if (CurRemVal == 1) {cmdF = true; cmdR = false;} if (CurRemVal == 2) {cmdF = false; cmdR = true;} } if (cmdF && !cmdR) { if(WkState != 1 && nn > 0) { WkState = 1; //  .     ,     . Indicate(); Brake(); // } WkState = 1; //       .   . Indicate(); } if (!cmdF && cmdR) { if(WkState != 2 && nn > 0) { WkState = 2; Indicate(); Brake(); // } WkState = 2; Indicate(); } if (cmdF && cmdR) { if(WkState != 0) { WkState = 0; Indicate(); Brake(); // } Indicate(); WkState = 0; } // if (WkState == 0) // { SoftStartMotor = 0; nn = 0; delay(50); return; } nn ++; //  (    " ") SoftStartMotor += 15; //  ,   . if (nn > 30000) nn = 30000; if (SoftStartMotor > 1200) SoftStartMotor = 1200; if (WkState == 1) // { int delays = GetDelayByVal(min(1024-analogRead(ValFwd),SoftStartMotor)); //   . , ...  RotateFwd(delays-400); } else // { int delays = GetDelayByVal(min(analogRead(ValRew),SoftStartMotor)); RotateRew(delays-400 ); } } // .   void RotateFwd(int delays) { digitalWrite(Lo_M, !HIGH); //   SendPosST(delays); delayMicroseconds(100); SendPosWK(delays); digitalWrite(Lo_M, !LOW); //  . delayMicroseconds(100); //  digitalWrite(Hi_M, !HIGH); SendNegST(delays); delayMicroseconds(100); SendNegWK(delays); digitalWrite(Hi_M, !LOW); delayMicroseconds(60); } // .   void RotateRew(int delays) { digitalWrite(Lo_M, !HIGH); //   SendPosST(delays); digitalWrite(Lo_M, !LOW); //  . delayMicroseconds(100); digitalWrite(Hi_M, !HIGH); SendNegWK(delays); delayMicroseconds(100); SendNegST(delays); digitalWrite(Hi_M, !LOW); delayMicroseconds(100); digitalWrite(Lo_M, !HIGH); //   SendPosWK(delays); digitalWrite(Lo_M, !LOW); //  . delayMicroseconds(60); } //   void SendPulse(int pin, int delays) { /* digitalWrite(pin, !HIGH); MyDelay(delays); digitalWrite(pin, !LOW); */ byte pwrCycle = 0; while(delays > 0) //  ,       { pwrCycle ++; if (delays < 0) return; if (delays < 300) //   300,   . { delayMicroseconds(delays); return; } if (pwrCycle < 5){ digitalWrite(pin, !HIGH);} delayMicroseconds(min(1200,delays)); // . 1200 digitalWrite(pin, !LOW); if (delays < 300)//   300,   . { delayMicroseconds(delays); return; } delayMicroseconds(200); delays -= 1400; //   } } void SendPosWK(int delays) { SendPulse(Hi_WK,delays); } void SendNegWK(int delays) { SendPulse(Lo_WK,delays); } void SendPosST(int delays) { if (nn < 100) //  { SendPulse(Hi_ST,delays); } else { if (delays > 2000) //   -    25%  { SendPulse(Hi_ST,2000); delayMicroseconds(delays - 2000); } else { SendPulse(Hi_ST,delays); //delayMicroseconds(delays); //  ,   100%   -     1-2   } } } void SendNegST(int delays) { if (nn < 100) //  { SendPulse(Lo_ST,delays); } else { if (delays > 2000) { SendPulse(Lo_ST,2000); delayMicroseconds(delays - 2000); } else { SendPulse(Hi_ST,delays); } } } //    .       ,      . void Brake() { digitalWrite(LedStp, 1); AllOff(); digitalWrite(RelBrake, HIGH); delay(1600); digitalWrite(RelBrake, LOW); delay(300); return; //Serial.println("Brake"); } void AllOff() { digitalWrite(Hi_ST, !LOW); digitalWrite(Hi_WK, !LOW); digitalWrite(Hi_M, !LOW); digitalWrite(Lo_ST, !LOW); digitalWrite(Lo_WK, !LOW); digitalWrite(Lo_M, !LOW); delayMicroseconds(300); } void Indicate() { digitalWrite(LedStp, (WkState == 0 ? 1:0)); digitalWrite(LedFwd, (WkState == 1 ? 1:0)); digitalWrite(LedRew, (WkState == 2 ? 1:0)); } // 25  75   0.25  511 ( ) = 50 int GetDelayByVal(int val) { if (val < 5) return 10000; if (val < 10) return 9900; if (val < 15) return 9803; if (val < 20) return 9708; if (val < 25) return 9615; if (val < 30) return 9523; if (val < 35) return 9433; if (val < 40) return 9345; if (val < 45) return 9259; if (val < 50) return 9174; if (val < 55) return 9090; if (val < 60) return 9009; if (val < 65) return 8928; if (val < 70) return 8849; if (val < 76) return 8771; if (val < 81) return 8695; if (val < 86) return 8620; if (val < 91) return 8547; if (val < 96) return 8474; if (val < 101) return 8403; if (val < 106) return 8333; if (val < 111) return 8264; if (val < 116) return 8196; if (val < 121) return 8130; if (val < 126) return 8064; if (val < 131) return 8000; if (val < 136) return 7936; if (val < 141) return 7874; if (val < 147) return 7812; if (val < 152) return 7751; if (val < 157) return 7692; if (val < 162) return 7633; if (val < 167) return 7575; if (val < 172) return 7518; if (val < 177) return 7462; if (val < 182) return 7407; if (val < 187) return 7352; if (val < 192) return 7299; if (val < 197) return 7246; if (val < 202) return 7194; if (val < 207) return 7142; if (val < 212) return 7092; if (val < 217) return 7042; if (val < 223) return 6993; if (val < 228) return 6944; if (val < 233) return 6896; if (val < 238) return 6849; if (val < 243) return 6802; if (val < 248) return 6756; if (val < 253) return 6711; if (val < 258) return 6666; if (val < 263) return 6622; if (val < 268) return 6578; if (val < 273) return 6535; if (val < 278) return 6493; if (val < 283) return 6451; if (val < 288) return 6410; if (val < 294) return 6369; if (val < 299) return 6329; if (val < 304) return 6289; if (val < 309) return 6250; if (val < 314) return 6211; if (val < 319) return 6172; if (val < 324) return 6134; if (val < 329) return 6097; if (val < 334) return 6060; if (val < 339) return 6024; if (val < 344) return 5988; if (val < 349) return 5952; if (val < 354) return 5917; if (val < 359) return 5882; if (val < 364) return 5847; if (val < 370) return 5813; if (val < 375) return 5780; if (val < 380) return 5747; if (val < 385) return 5714; if (val < 390) return 5681; if (val < 395) return 5649; if (val < 400) return 5617; if (val < 405) return 5586; if (val < 410) return 5555; if (val < 415) return 5524; if (val < 420) return 5494; if (val < 425) return 5464; if (val < 430) return 5434; if (val < 435) return 5405; if (val < 441) return 5376; if (val < 446) return 5347; if (val < 451) return 5319; if (val < 456) return 5291; if (val < 461) return 5263; if (val < 466) return 5235; if (val < 471) return 5208; if (val < 476) return 5181; if (val < 481) return 5154; if (val < 486) return 5128; if (val < 491) return 5102; if (val < 496) return 5076; if (val < 501) return 5050; if (val < 506) return 5025; if (val < 512) return 5000; if (val < 517) return 4975; if (val < 522) return 4950; if (val < 527) return 4926; if (val < 532) return 4901; if (val < 537) return 4878; if (val < 542) return 4854; if (val < 547) return 4830; if (val < 552) return 4807; if (val < 558) return 4784; if (val < 563) return 4761; if (val < 568) return 4739; if (val < 573) return 4716; if (val < 578) return 4694; if (val < 583) return 4672; if (val < 588) return 4651; if (val < 593) return 4629; if (val < 599) return 4608; if (val < 604) return 4587; if (val < 609) return 4566; if (val < 614) return 4545; if (val < 619) return 4524; if (val < 624) return 4504; if (val < 629) return 4484; if (val < 634) return 4464; if (val < 640) return 4444; if (val < 645) return 4424; if (val < 650) return 4405; if (val < 655) return 4385; if (val < 660) return 4366; if (val < 665) return 4347; if (val < 670) return 4329; if (val < 675) return 4310; if (val < 680) return 4291; if (val < 686) return 4273; if (val < 691) return 4255; if (val < 696) return 4237; if (val < 701) return 4219; if (val < 706) return 4201; if (val < 711) return 4184; if (val < 716) return 4166; if (val < 721) return 4149; if (val < 727) return 4132; if (val < 732) return 4115; if (val < 737) return 4098; if (val < 742) return 4081; if (val < 747) return 4065; if (val < 752) return 4048; if (val < 757) return 4032; if (val < 762) return 4016; if (val < 768) return 4000; if (val < 773) return 3984; if (val < 778) return 3968; if (val < 783) return 3952; if (val < 788) return 3937; if (val < 793) return 3921; if (val < 798) return 3906; if (val < 803) return 3891; if (val < 808) return 3875; if (val < 814) return 3861; if (val < 819) return 3846; if (val < 824) return 3831; if (val < 829) return 3816; if (val < 834) return 3802; if (val < 839) return 3787; if (val < 844) return 3773; if (val < 849) return 3759; if (val < 855) return 3745; if (val < 860) return 3731; if (val < 865) return 3717; if (val < 870) return 3703; if (val < 875) return 3690; if (val < 880) return 3676; if (val < 885) return 3663; if (val < 890) return 3649; if (val < 896) return 3636; if (val < 901) return 3623; if (val < 906) return 3610; if (val < 911) return 3597; if (val < 916) return 3584; if (val < 921) return 3571; if (val < 926) return 3558; if (val < 931) return 3546; if (val < 936) return 3533; if (val < 942) return 3521; if (val < 947) return 3508; if (val < 952) return 3496; if (val < 957) return 3484; if (val < 962) return 3472; if (val < 967) return 3460; if (val < 972) return 3448; if (val < 977) return 3436; if (val < 983) return 3424; if (val < 988) return 3412; if (val < 993) return 3401; if (val < 998) return 3389; if (val < 1003) return 3378; if (val < 1008) return 3367; if (val < 1013) return 3355; if (val < 1018) return 3344; if (val < 1024) return 3333; } 


Scheme:

In general, it is almost a classic, but assembled from 5 different schemes. Diodes on "high" shoulders in general when using IGBT transistors are not necessary, but at first I did, and then I just thought

In summary: it works. Much more is worth completing, such as a remote "pultik" brake. Maybe you should experiment with the duration of the pulses or make a full-fledged PWM simulating the sine, rather than a constant duty cycle. But for now it is. Maybe someone will come in handy.

And in the end, I would like to ask: instead of the ballast, I put a choke, "clamped" diodes. How wrong am I in this decision? Choke, I do not even know what kind of inductance. Taken from the ATX PSU, where he stood in the reactive power compensation unit.

Well, the experience ... The experience is very interesting. I would never have thought that this could be so difficult. And that 30V and 300V is a huge difference. I was very respectful of the people who are designing such things.
And this is the price of my mistakes:



Video of the whole process can be viewed here: 1 2 3

Questions more knowledgeable, the answers I would like in the comments:

1. Choke that is on the chain +310. Should I get rid of him? I put it in the hope that the increase in current, in the case of through current, will be slower and the driver will have time to go to the protection of current.

2. I get pulses of the same duty ratio. Is this critical? Leave, or is it still doing something "sine-dependent" in the duty ratio?

Source: https://habr.com/ru/post/399357/


All Articles