Featured image of post CM_FOC驱动器

CM_FOC驱动器

FOC驱动器

臭猫FOC驱动器设计日志

主控芯片:WCH-CH32V307VCT6
预驱芯片:EG2133
MOS:NEC6050
下载芯片:CH549G
电流检测:INA240A2 原理图设计
FOC驱动板正面
FOC驱动板反面

2024-9-15 期待已久的FOC驱动器终于开工设计!设计完成PCB以及原理图。第一次设计双路的FOC驱动器,也是第一次是设计功率地与普通的GND隔离。

另外就是电流检测芯片选择的是TI的INA240A2,有点难以购买qaq0.0每个芯片的价格在3元左右,属实有点成本爆炸。下次准备学习更换更为便宜的INA199或者其他国产方案。

2024-9-17 计划物料到货开始焊接

焊接完成的实物图
这板子有一些bug,就是CH549G下载电路的供电有些问题。在使用DC-12v供电测试的时候,CH549G下载电路的供电不稳定。 另外在开环测试的时候供电也不稳定。不知道是不是程序问题。 接下来抽时间对驱动器进行软件开发

方波驱动测试

在每个换相周期内,定子绕组中的电流被切换为高或低两个状态,形成矩形波。通常采用六步换向法,即每60度电角度换相一次,从而产生转矩。

开环FOC驱动测试

开环运行即根据系统时间为索引,根据时间固定生成三相的正弦波。需要涉及Clark变换以及Park变换。 simpleFOC的开环速度代码如下 参考了:https://github.com/haotianh9/DengFOC_on_STM32 电压控制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
static inline uint32_t LL_SYSTICK_IsActiveCounterFlag(void)
{
  return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == (SysTick_CTRL_COUNTFLAG_Msk));
}

uint32_t getCurrentMicros(void)
{
  /* Ensure COUNTFLAG is reset by reading SysTick control and status register */
  LL_SYSTICK_IsActiveCounterFlag();
  uint32_t m = HAL_GetTick();
  const uint32_t tms = SysTick->LOAD + 1;
  __IO uint32_t u = tms - SysTick->VAL;
  if (LL_SYSTICK_IsActiveCounterFlag()) {
    m = HAL_GetTick();
    u = tms - SysTick->VAL;
  }
  return (m * 1000 + (u * 1000) / tms);
} //【应该是获取运行时间的代码段。】 

float _electricalAngle(float shaft_angle, int pole_pairs) {
  return (shaft_angle * pole_pairs);
}

float _normalizeAngle(float angle){
  float a = fmod(angle, 2*M_PI);   //取余运算可以用于归一化,列出特殊值例子算便知
  return a >= 0 ? a : (a + 2*M_PI);
  //三目运算符。格式:condition ? expr1 : expr2
  //其中,condition 是要求值的条件表达式,如果条件成立,则返回 expr1 的值,否则返回 expr2 的值。
  //可以将三目运算符视为 if-else 语句的简化形式。
  //fmod 函数的余数的符号与除数相同。因此,当 angle 的值为负数时,余数的符号将与 _2M_PI 的符号相反。
  //也就是说,如果 angle 的值小于 0  _2M_PI 的值为正数,则 fmod(angle, _2M_PI) 的余数将为负数。
  //例如,当 angle 的值为 -M_PI/2_2M_PI 的值为 2M_PI 时,fmod(angle, _2M_PI) 将返回一个负数。
  //在这种情况下,可以通过将负数的余数加上 _2M_PI 来将角度归一化到 [0, 2M_PI] 的范围内,以确保角度的值始终为正数。
}

void setPwm(float Ua, float Ub, float Uc) {

//	// 限制上限
	Ua = _constrain(Ua, 0.0f, voltage_limit);
	Ub = _constrain(Ub, 0.0f, voltage_limit);
	Uc = _constrain(Uc, 0.0f, voltage_limit);
	// 计算占空比
	// 限制占空比从01
	dc_a = _constrain(Ua / voltage_power_supply, 0.0f , 1.0f );
	dc_b = _constrain(Ub / voltage_power_supply, 0.0f , 1.0f );
	dc_c = _constrain(Uc / voltage_power_supply, 0.0f , 1.0f );

	//写入PWM到PWM 0 1 2 通道
	TIM1->CCR1 = (uint32_t) roundf(dc_a*period);
	TIM1->CCR2 = (uint32_t) roundf(dc_b*period);
	TIM1->CCR3 = (uint32_t) roundf(dc_c*period);

}

void setPhaseVoltage(float Uq,float Ud, float angle_el) {
  angle_el = _normalizeAngle(angle_el + zero_electric_angle);
  // 帕克逆变换
  Ualpha =  -Uq*sin(angle_el);
  Ubeta =   Uq*cos(angle_el);

  // 克拉克逆变换
  Ua = Ualpha + voltage_power_supply/2;
  Ub = (sqrt(3)*Ubeta-Ualpha)/2 + voltage_power_supply/2;
  Uc = (-Ualpha-sqrt(3)*Ubeta)/2 + voltage_power_supply/2;
  setPwm(Ua,Ub,Uc);
}

//开环速度函数
float velocityOpenloop(float target_velocity){
//	uint32_t now_us = getCurrentMicros();
//	uint32_t now_us = HAL_GetTick();
//  Provides a tick value in microseconds.

  //计算当前每个Loop的运行时间间隔
//  float Ts = (now_us - open_loop_timestamp) * 1e-3f;
	float Ts=5E-3f;

  // 通过乘以时间间隔和目标速度来计算需要转动的机械角度,存储在 shaft_angle 变量中。
  //在此之前,还需要对轴角度进行归一化,以确保其值在 0  2π 之间。
  shaft_angle = _normalizeAngle(shaft_angle + target_velocity*Ts);
  //以目标速度为 10 rad/s 为例,如果时间间隔是 1 秒,则在每个循环中需要增加 10 * 1 = 10 弧度的角度变化量,才能使电机转动到目标速度。
  //如果时间间隔是 0.1 秒,那么在每个循环中需要增加的角度变化量就是 10 * 0.1 = 1 弧度,才能实现相同的目标速度。
  //因此,电机轴的转动角度取决于目标速度和时间间隔的乘积。

  // Uq is not related to voltage limit
  float Uq = 5.5;

  setPhaseVoltage(Uq,  0, _electricalAngle(shaft_angle, pole_pairs));

//  open_loop_timestamp = now_us;  //用于计算下一个时间间隔

  return Uq;
}

开环波形图测试
波形图根据上述代码来生成的话有些错误。这导致电机不能正确转动。而发出固定的啸叫。
开环波形图测试
时间改为us后,波形图更加混乱。
将时间的获取改为定时器中断+全局变量后。首先设置1us生成波形图如下:
开环波形图测试
调整为200us时波形图如下:
开环波形图测试
按理说这样运行开环已经可以完美运行,但是接入电脑5v-usb供电的时候电机依然跳动+啸叫。
接入正常12v电源供电时,板子直接没了反应。。可能是设计的电源出现了问题。将电压降低到5v后板子可以正常上电启动,但是无法正常运行,整体是一种上电运行后,电机转动力巨大,然后系统死机重启陷入了死循环。
电源设计还是不太过关。。。而且设计的有些混乱。。计划下一板改进,但是这种工程耗费时间太大了,下次进行工程实现之前应该提前做好功课。

AS5600磁编码器电机底板

2024-9-18 PCB刚刚到货,准备抽时间进行焊接。再一次把CM_FOC的串口通信部分焊接完成,方便查看波形等。 SH1.25的接口画错了,属实是大意了。飞线暂时解决了问题。 焊接完成的实物图

AS5600磁编码器数据读取

AS5600是12位的霍尔磁编码器,它的地址是0x36,只需要读取0x0C、0x0D这两个寄存器就可以读出角度的原始数据,再将其乘以360,再除以4096,就可以获得角度值。

鸽了一段时间,等忙完就马上开始测试。在此之前还需要把电源修好、、、、悲

Licensed MIT OR GPL3.0 WHATEVERS ON GITHUB_PAGE SHOW YOU