Skalare Chastotnik für einen einphasigen Asynchronmotor

Zunächst muss jeder Programmierer eine Drehmaschine haben. Nun ... oder zumindest muss ich es haben. Und auch ohne CNC. Das ist mein Traum.

Und der Traum wurde wahr. Die Maschine wurde gekauft, gebracht, auf den Parkplatz gestellt und ... Es wäre notwendig, sie einzuschalten. Und das Einschalten ist nicht so einfach. Und wenn Sie nicht nach einfachen Wegen suchen, dann brauchen Sie einen "Chastotnik", aber auf wissenschaftliche Weise: einen Frequenzumrichter. Und lassen Sie mich ein Laie sein, aber ich habe es getan.



Und mit dem Anschluss des Motors beginnt der Spaß. Ich selbst bin in solch einem Ignoranten, es gibt einige allgemeine Kenntnisse, aber wie es wirklich funktioniert, hatte ich keine Ahnung. Und als ich anstelle der erwarteten 3 Schlussfolgerungen der 3 Phaser 4 und nicht einmal 3 Wicklungen mit einem gemeinsamen Punkt sah, sondern getrennte 2 und sogar mit unterschiedlichem Widerstand ... Nun, ähm, sagen wir das - "überrascht".

Also die Motoren. Sie sind dreiphasig, dreiphasig und durch ein Dreieck durch Kondensatoren und ... einphasigen Kondensator verbunden.

Dreiphasig - "voll" asynchron. 3 Wicklungen, in guter Weise von einem Stern eingeschlossen und in vollen 3 Phasen aufgehängt. Na ja, oder ein 3-Phasen-Chastotnik, davon eine Welle auf Ali.

Dreiphasen + Dreieck + Kondensatoren. Hier verlieren wir bereits an Effizienz, Leistung und Drehmoment. Wenn es keine drei Phasen gibt, haben wir eine Lösung für uns. Billig, einfach, zuverlässig, fröhlich.

Einphasenkondensator

Hier werden wir darüber sprechen. Im Allgemeinen sind solche Motoren sehr verbreitet. Dies sind Lüfter von Projektormotoren und -antrieben einiger Uhren sowie Motoren für kleine Schmirgel- und andere Anwendungen, bei denen keine hohe Leistung benötigt wird, aber Pluspunkte von Asynchronisierern erforderlich sind: enorme Zuverlässigkeit + Geschwindigkeit, abhängig nur von der Frequenz der Versorgungsspannung.

Das grundlegende Schema der Inklusion (das Bild ist nicht meins, ehrlich gesagt im Internet zu finden):



Im Allgemeinen lautet das Prinzip ungefähr so: Es gibt eine Starterwicklung, die eine EMF in einem Käfigläufer induziert. Bei einer Phasenverschiebung wird die Arbeitswicklung eingeschaltet. Sie "drückt" den magnetisierten Anker, die Rotation beginnt. Wenn Sie sich zu einem bestimmten Winkel drehen, wiederholt sich alles. Der Motor beginnt sich zu drehen.

Insgesamt - Sie benötigen 2 Phasen, die auf einen bestimmten Winkel verschoben sind. Normalerweise sind es 90 Grad. Dies wird durch den Startkondensator bereitgestellt. Nun, nach einer Reihe von Umdrehungen beginnt der Anker von der sehr funktionierenden Wicklung aus zu arbeiten und die Starterwicklung kann sogar ganz ausgeschaltet werden. Nun, oder von einem Arbeitskondensator angetrieben, eine viel kleinere Kapazität.

Aber das ist alles eine Theorie. Aber was willst du in der Praxis? Ich möchte einen Chastotnik. Was würde es sich beschleunigen, verlangsamen, in beide Richtungen drehen, na ja, natürlich mit unterschiedlichen Geschwindigkeiten! Und hier wird es etwas komplizierter. Tatsache ist, dass solche Chastotnikov manchmal weniger zum Verkauf stehen. Und sie kosten ein Vielfaches mehr. Im Allgemeinen - exotisch.

Aber wenn Sie so denken, dann ist der Unterschied zur 3-Phase nicht so groß. Und Sie können sogar die gleiche Schaltung verwenden. Zur gleichen Zeit gibt es die gleichen 3 Abgriffe: gemeinsam, Starterwicklung, Arbeitswicklung. Und alles dreht sich um die Firmware. Also - das kann man machen. Und lassen Sie es nicht eine Vektorsteuerung mit einer Menge Mathematik sein, sondern einen einfachen Skalar, aber ... wie ich kann.

Also - was ist erforderlich. Schauen wir uns zunächst die Diagramme von Sinus und Cosinus an (wir haben einen Versatz von 90 Grad). ÜBEREINKOMMEN es sieht folgendermaßen aus:



Das heißt, Die Aufgabe ist elementar: Wir „ziehen“ den General zu Boden, speisen ein Paket positiver Impulse in die Starterwicklung ein, speisen ein Paket Impulse in den Arbeiter. Dann ziehen wir den General zum Plus und führen dem Starter eine Packung negativer Impulse und dann der Arbeitswicklung zu. T.O. grob erhalten wir eine Nachahmung einer Polaritätsänderung und einer Phasenverschiebung. Wie oft wir dies tun werden, hängt von der „Frequenz“ ab.

Im Allgemeinen ist die Theorie einfach. Als ATMega 328-Controller mit Bootloader sind die Arduins (ja, tatsächlich die Arduina selbst, nur ohne zu viel Umreifung), der IR2132-Treiber (alt, aber mit IR2136 hat es nicht funktioniert) und die IRG4BC30-Ausgabetasten. Für meinen 1,1 kW Motor ist das mehr als genug.

(Wenn Sie das Diagramm wiederholen, ist nur die Platine fertig, eine Skizze wird in den Arduino Duemilanove gegossen, dann wird der Mega328 herausgezogen und in die Platine eingelötet. Fertig.)

Und im Folgenden ... Außerdem tauchte ich in die wunderbare Welt der Induktivitäten und der Leistungselektronik ein. Und alles stellte sich als nicht so einfach heraus, wie es am Anfang gedacht wurde:

1. Die Geschwindigkeit des Öffnens und Schließens von Tasten ist wichtig. Totzeit ist sehr wichtig.
2. Einschalten des Vorschaltgeräts - obligatorisch mit einer Diode, die dem Pluszeichen des Leistungsfilterkondensators zugewandt ist. Andernfalls deaktivieren Entladungen während des Entladens der Induktivität manchmal die Leistungs-IGBTs.
3. Abkühlen. Kleine Heizkörper auf der Platine sind schlecht. Entweder überhitzt es sich oder du musst es blasen. Aber wenn Sie es blasen, wird die gesamte Metallfederung der Maschine früher oder später etwas kurzschließen und es wird einen Knall geben.
3+.Glimmer oder besser gesagt SEHR DÜNNER Glimmer ist schlecht. Es macht seinen Weg und es stellt sich heraus, dass im Titel des Artikels. Gleichzeitig weisen Silikon-Wärmeleitpads eine schlechtere Wärmeleitfähigkeit auf. Aber Keramik ... ich habe es nicht.
4. Beim Bremsen nach der Methode eines langen Impulsstoßes gleicher Polarität an einer Wicklung überhitzen sich die Transistoren schnell und brennen aus. Außerdem springt der Motor mit viel Spaß, dreht sich mit bis zu dreitausend Umdrehungen und stoppt für 0,3 Sekunden bis 0.
5. Wenn alles funktioniert und Sie sich entspannen, schalten Sie den Stromkreis ohne Ballast ein und drücken Sie Start - es wird einen Knall geben. Dies führt auch zu einem Treiberwechsel.

Skizze:Nun wird eine Drehung in beide Richtungen mit einer sanften Abstimmung der Frequenz von 25-75 Hz mit einem Schritt von 0,25 implementiert. Es gab eine Idee mit einer Bremse. Jetzt ist es auskommentiert und es wird notwendig sein, das Schema zu ändern. Die Idee ist nämlich folgende: Ich habe Impulse der gleichen Polarität korrekt angewendet, ABER. Dies muss durch Vorschaltgerät mit einem separaten Schlüssel erfolgen.

Leistungsteil: Der Stromkreis wird noch fertiggestellt, aber im Moment befindet sich die Maschine in einem unbeheizten Raum und es ist aufgrund des Gefrierens des Öls äußerst schwierig, damit zu arbeiten.

Skizze
#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;
}


Schema:
Bild
Im Allgemeinen fast ein Klassiker, aber zusammengesetzt aus 5 verschiedenen Schemata. Dioden auf den "hohen" Schultern sind im Allgemeinen bei Verwendung von IGBT-Transistoren nicht erforderlich, aber ich habe es zuerst getan und dann nur gedacht:

Als Ergebnis: es funktioniert. Es muss noch viel erledigt werden, zum Beispiel eine externe „Fernbedienung“, eine Bremse. Es kann sich lohnen, mit der Pulsdauer zu experimentieren oder eine vollwertige PWM zu erstellen, die einen Sinus simuliert, anstatt einen konstanten Arbeitszyklus. Aber im Moment ist das so. Vielleicht wird jemand nützlich sein.

Und am Ende möchte ich fragen: Anstelle von Ballast habe ich eine Drossel eingesetzt, die von Dioden "geklemmt" wird. Wie falsch bin ich bei einer solchen Entscheidung? Choke, ich weiß nicht mal welche Induktivität. Entnommen aus dem ATX-Netzteil, wo es in der Blindleistungskompensationseinheit stand.

Nun, die Erfahrung ... Die Erfahrung ist sehr interessant. Ich hätte nie gedacht, dass es so schwierig sein könnte. Und diese 30V und 300V sind ein großer Unterschied. Ich respektiere wirklich Leute, die solche Dinge entwerfen.
Und das ist der Preis für meine Fehler: Sie



können das Video des gesamten Prozesses hier ansehen: 1 2 3

Fragen für sachkundigere, ich würde gerne die Kommentare sehen:

1. Das Gas, das auf der +310-Rennstrecke steht. Soll ich ihn loswerden? Ich habe es in der Hoffnung eingestellt, dass der Anstieg des Stroms im Fall des Durchstroms langsamer ist und der Fahrer Zeit hat, sich mit dem Stromschutz zu befassen.

2. Ich erhalte Impulse mit demselben Arbeitszyklus. Ist das kritisch? Verlassen oder noch etwas „sinusabhängiges“ im Arbeitszyklus tun?

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


All Articles