02.实现逆帕克变换和逆克拉克变换
小于 1 分钟
02.实现逆帕克变换和逆克拉克变换
使用定点数实现
u_d
- 类型:
int16_t
- 映射关系:
[-32768,32767]
表示[-1,1]
- 精度:1/32768 = 0.0000305
- 类型:
e_angle
- 类型:
uint16_t
- 映射关系:
[0,65535]
表示[0,2PI]
- 精度:360°/65535 = 0.00549°
- 类型:
具体实现
BLDCMotor.cpp
#include "BLDCMotor.hpp"
#include "Arduino.h"
/**
* 设置相电压
* @param u_d int16_t [-32768,32767] 表示 [-1,1] 精度:1/32768 = 0.0000305
* @param u_q int16_t [-32768,32767] 表示 [-1,1]
* @param e_angle uint16_t [0,65535] 表示 [0,2PI] 精度:360°/65535 = 0.00549°
*/
void BLDCMotor::setPhraseVoltage(int16_t u_d, int16_t u_q, uint16_t e_angle)
{
int16_t sin, cos;
_sincos(e_angle, &sin, &cos);
// 帕克逆变换
// 因为 0xffff * 0xffff ≈ 0xffff0000
// 即 uin16_t * uin16_t 结果须用 uit32_t 来保存
// 另外 因为结果扩大了 0xffff倍 ,所以要缩放回去。
int16_t u_alpha = ((cos * (int32_t)u_d) + (-sin * (int32_t)u_q)) / _INT16_ONE_;
int16_t u_beta = ((sin * (int32_t)u_d) + (cos * (int32_t)u_q)) / _INT16_ONE_;
// 克拉克逆变换(等幅值形式)
int16_t u_a = u_alpha;
int16_t u_b = (-u_alpha + _SQRT3_ * u_beta / _INT16_ONE_) / 2;
int16_t u_c = -(u_a + u_b);
Serial.print(u_a);
Serial.print(',');
Serial.print(u_b);
Serial.print(',');
Serial.print(u_c);
Serial.print('\n');
}
BLDCMotor.cpp
#ifndef __BLDCMotor_H__
#define __BLDCMotor_H__
#include <stdint.h>
#include "foc_utils.h"
class BLDCMotor
{
public:
/**
* 设置相电压
* @param u_d int16_t [-32768,32767] 表示 [-1,1] 精度:1/32768 = 0.0000305
* @param u_q int16_t [-32768,32767] 表示 [-1,1]
* @param e_angle uint16_t [0,65535] 表示 [0,2PI] 精度:360°/65535 = 0.00549°
*/
void setPhraseVoltage(int16_t u_d, int16_t u_q, uint16_t e_angle);
};
#endif
typedef.h
// 单位1 32767
#define _INT16_ONE_ 32767
// 单位PI 180°
#define _PI_ 32767
// 360°
#define _2PI_ 65535
// 90°
#define _PI_2_ 16383
// 180°
#define _PI_4_ 16383
// -90°=270°
#define _3_PI_2_ 16383
实现效果
02.park_and_clarke.ino
#include <Arduino.h>
#include "BLDCMotor.hpp"
#include "foc_utils.h"
#include "typedef.h"
BLDCMotor motor;
void setup()
{
Serial.begin(9600);
}
uint16_t a = 0;
void loop()
{
a += 1500;
if (a > _2PI_)
a -= _2PI_;
motor.setPhraseVoltage(_INT16_ONE_, 0, a);
}