📜 ⬆️ ⬇️

Work with a three-phase synchronous motor

It happened to me, by the nature of my activity, to write a program for overclocking the promotion and control of a three-phase synchronous motor . Next, I will try to describe in detail how I implemented it.

The engine spin chart looks like this:

image
')
As you can see, it is necessary not only to increase the frequency, but also the amplitude, and it does not grow from zero, but from 4 volts and at a frequency of 80 Hz, should reach its maximum. Well, because it is a three-phase motor, then there should be 3 sinusoids, moreover, shifted relative to each other by 120 degrees. Also, an additional condition was that at 80 Hz the engine would exit no less than 30s, so I decided to use a second per hertz (100 Hz is achieved for 100s).

In the controller with which I work there is just 3 PWMs and I decided to use them, and not bother to mess with external DACs.

The first problem I encountered is that the signal from the PWM output will only be positive, i.e. the sinusoid will be above zero, for this it was necessary to break it into half-waves and build them separately. This is what a sine wave will look like with a minimum amplitude.

image
image

But at the maximum.

image
image

to get a positive half wave:
DCH = sin[ptrA]; DCH = DCH + 128; 

negative:
 DCH = sin[ptrA]; DCH = 128 - DCH; 

As can be seen from the following figure, now my sine wave is spinning near the value 128, now it is enough to shift the signal by hardware and set the zero to 128 and it will become bipolar.

image

Sinusoid consists of 128 points, this is more than enough. After the low-pass filter is almost perfectly smooth. The amplitude also grows rather smoothly (the coefficient table consists of 80 values), multiply by the value from the table and discard the low byte:

 ampS = amp[fctr]; DCH = DCH*ampS; DCH = DCH>>8; 

To increase the frequency, I used the 16-bit timer TMR0, the value of its period is taken from a table that consists of 100 values ​​(from 1 to 100 Hz). The formula for the calculation is as follows: 65535-sec / clk / smpl / Hz , where Hz varies from 1 to 100.

The program was developed for the PIC17 microcontroller using the CC7A compiler of the Norwegian company B Knudsen Data.

Here, in fact, a table of values ​​for the timer.

  #define CDATA_START 0x300 #pragma cdata[CDATA_START] #pragma cdata[] = 0x153B, 0x8A9D, 0xB1BE, 0xC54E, 0xD10B, 0xD8DE, 0xDE75, 0xE2A7, 0xE5E9, 0xE885, 0xEAA7, 0xEC6F, 0xEDF0, 0xEF3A, 0xF058, 0xF153, 0xF230, 0xF2F4, 0xF3A4, 0xF442, 0xF4D1, 0xF553, 0xF5CA, 0xF637, 0xF69B, 0xF6F7, 0xF74D, 0xF79D, 0xF7E7, 0xF82C, 0xF86C, 0xF8A9, 0xF8E2, 0xF917, 0xF94A, 0xF97A, 0xF9A7, 0xF9D1, 0xF9FA, 0xFA21, 0xFA45, 0xFA68, 0xFA89, 0xFAA9, 0xFAC7, 0xFAE4, 0xFB00, 0xFB1B, 0xFB34, 0xFB4D, 0xFB65, 0xFB7B, 0xFB91, 0xFBA6, 0xFBBA, 0xFBCE, 0xFBE1, 0xFBF3, 0xFC04, 0xFC15, 0xFC26, 0xFC36, 0xFC45, 0xFC54, 0xFC62, 0xFC70, 0xFC7E, 0xFC8B, 0xFC98, 0xFCA4, 0xFCB1, 0xFCBC, 0xFCC8, 0xFCD3, 0xFCDE, 0xFCE8, 0xFCF2, 0xFCFC, 0xFD06, 0xFD10, 0xFD19, 0xFD22, 0xFD2B, 0xFD34, 0xFD3C, 0xFD44, 0xFD4C, 0xFD54, 0xFD5C, 0xFD63, 0xFD6B, 0xFD72, 0xFD79, 0xFD80, 0xFD86, 0xFD8D, 0xFD93, 0xFD9A, 0xFDA0, 0xFDA6 


2 more tables with sine values ​​and amplitude coefficients, respectively.

 const unsigned char sin[128]= { 0, 7, 13, 18, 24, 31, 37, 43, 50, 54, 60, 65, 71, 76, 80, 85, 90, 94, 99, 101, 105, 109, 112, 115, 118, 119, 121, 123, 125, 126, 126, 127, 127, 127, 126, 126, 125, 123, 121, 119, 117, 115, 112, 109, 105, 101, 99, 94, 90, 85, 80, 76, 71, 65, 60, 54, 48, 43, 37, 31, 24, 18, 13, 7, 0, 7, 13, 18, 24, 31, 37, 43, 50, 54, 60, 65, 71, 76, 80, 85, 90, 94, 99, 101, 105, 109, 112, 115, 118, 119, 121, 123, 125, 126, 126, 127, 127, 127, 126, 126, 125, 123, 121, 119, 117, 115, 112, 109, 105, 101, 99, 94, 90, 85, 80, 76, 71, 65, 60, 54, 48, 43, 37, 31, 24, 18, 13, 7 }; const unsigned char amp[80]= { 86, 88, 90, 93, 95, 97, 99, 101, 103, 105, 108, 110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 131, 133, 136, 138, 140, 142, 144, 146, 148, 151, 153, 155, 157, 159, 161, 164, 166, 168, 170, 172, 174, 176, 179, 181, 183, 185, 187, 189, 192, 194, 196, 198, 200, 202, 204, 207, 209, 211, 213, 215, 217, 220, 222, 224, 226, 228, 230, 232, 235, 237, 239, 241, 243, 245, 247, 250, 252, 254, 255 }; 


The timer interrupt handler looks like this.

 TMR0_service: { T0IF = 0; //    sPRODL = PRODL; sPRODH = PRODH; sTBLPTRH = TBLPTRH; sTBLPTRL = TBLPTRL; sFSR0 = FSR0; sFSR1 = FSR1; if (herz < 100) { if (ptrA == 127) TMR0_inc(); } TMR0_set(); if (ptrA == 127) ptrA = 0; if (ptrB == 127) ptrB = 0; if (ptrC == 127) ptrC = 0; ptrA++; //   .  1-  ptrB++; //   .  2-  ptrC++; //   .  3-  if (herz>=79) { if (ptrA < 64) { DCH = sin[ptrA]; //   DCH = DCH + 128; } else { DCH = sin[ptrA]; //   DCH = 128 - DCH; } PW1DCH = DCH; if (ptrB < 64) { DCH = sin[ptrB]; //   DCH = DCH + 128; } else { DCH = sin[ptrB]; //   DCH = 128 - DCH; } PW2DCH = DCH; if (ptrC < 64) { DCH = sin[ptrC]; //   DCH = DCH + 128; } else { DCH = sin[ptrC]; //   DCH = 128 - DCH; } PW3DCH = DCH; } else { fctr = herz-1; //   ampS = amp[fctr]; //   if (ptrA < 64) { DCH = sin[ptrA]; //   DCH = DCH*ampS; DCH = DCH>>8; DCH = DCH + 128; } else { DCH = sin[ptrA]; //   DCH = DCH*ampS; DCH = DCH>>8; DCH = 128 - DCH; } PW1DCH = DCH; if (ptrB < 64) { DCH = sin[ptrB]; //   DCH = DCH*ampS; DCH = DCH>>8; DCH = DCH + 128; } else { DCH = sin[ptrB]; //   DCH = DCH*ampS; DCH = DCH>>8; DCH = 128 - DCH; } PW2DCH = DCH; if (ptrC < 64) { DCH = sin[ptrC]; //   DCH = DCH*ampS; DCH = DCH>>8; DCH = DCH + 128; } else { DCH = sin[ptrC]; //   DCH = DCH*ampS; DCH = DCH>>8; DCH = 128 - DCH; } PW3DCH = DCH; } TBLPTRH = sTBLPTRH; TBLPTRL = sTBLPTRL; PRODL = sPRODL; PRODH = sPRODH; FSR0 = sFSR0; FSR1 = sFSR1; } 

The main program.

 void main() { GLINTD = 1; //   // --    --> TBLPTRL = 0; TBLPTRH = 3; // 0x300 #asm TABLRD 0,1,WREG ;      TLRD 1,sTMR0H ;       TABLRD 0,1,sTMR0L ;       #endasm // <-- // --  TMR0 --> T0IE = 1; //     TMR0 T0STA = 32; //   , 1:1 // <-- // --   --> PR1 = 253; //   = 32000000 / 4 / 253 = 31620  PW1DCL = PW2DCL = PW3DCL = 0; PW1DCH = 64; //   1-  PW2DCH = 46; //   2-  PW3DCH = 83; //   3-  // <-- // --   --> rtc = 0; herz = 1; //   1  ptrA = 0; //   1-  ptrB = 85; //   2-  ptrC = 42; //   3-  TMR1ON = 1; //  TMR1 PWM1ON = PWM2ON = PWM3ON = 1; //   TMR0_set(); //  TMR0 // <-- GLINTD = 0; //   while(1); } 


Two subroutines for working with a timer.

 void TMR0_set() { TMR0L = sTMR0L; TMR0H = sTMR0H; } void TMR0_inc() { rtc++; //    if (rtc == herz) { rtc = 0; herz++; TBLPTRL = TBLPTRL - 1; #asm TABLRD 0,1,WREG ;      TLRD 1,sTMR0H ;       TABLRD 0,1,sTMR0L ;       #endasm sTBLPTRH = TBLPTRH; sTBLPTRL = TBLPTRL; } } 

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


All Articles