找回密码
 立即注册
楼主: 王昱顺

【STC-FOC Lite】 FOC青春版,更少的成本,更简单的构造

  [复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:428
  • 最近打卡:2025-05-01 14:31:13

1

主题

48

回帖

1325

积分

金牌会员

积分
1325
发表于 2023-12-5 12:10:53 来自手机 | 显示全部楼层
学习
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:428
  • 最近打卡:2025-05-01 14:31:13

1

主题

48

回帖

1325

积分

金牌会员

积分
1325
发表于 2023-12-5 12:26:56 来自手机 | 显示全部楼层
下载了
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2218

回帖

5450

积分

版主

积分
5450
发表于 2023-12-6 16:37:32 | 显示全部楼层
有关磁编码器测速


首先是从速度的计算公式下手,v=ds/dt
那么,提高编码器分辨率和提高时间的分辨率都十分重要。
并且因为转动的时候并非完全平稳的一条速度曲线,为了避免采样速度过快使得ds为太小的数值进而导致数值的不稳定,应该通过以下几种规则限定如何读取速度

开始我想的是应该分为两种模式,ds控制的模式和dt控制的模式
首先是读到ds为0或者接近0的情况,应该延长读取的周期,防止计算的v突变成0
其次是读到ds接近0.5圈的情况,则应该加快采样速度,防止出现超过半圈的计算错误。

但是实际工作中发现还是优先保证ds的数值比较合适,因为保证dt的话,采样率较高可能会造成较大的数据波动,体现起来就是数据毛刺。
举个例子就是ds=5,dt=50us,此时计算v=0.1*3662(编码器系数)=366.2rpm
那么ds稍微变化一些,ds=4,dt=50us,v=292.96rpm,可以看到跨度非常大,变化高达73,这显然是令人不能接受的。

那么根据这个优先保证ds的思想,可以设置一个简单的由P控制的参数
将角度变化量和0.25圈进行对比,通过累加完成控制dt。
然后通过对dt进行限制最大值(最低采样频率)和最小值(最高采样频率)。通过将dt赋给定时器初值,改变定时器计时时间的方式实现速度采样。

以下是有关的代码实现
  1. long Set_Time_Dat = 0;
  2. void Timer0_Isr(void) interrupt 1
  3. {
  4.         u16 Time_Dat;
  5.         TR0 = 0; // 关掉定时器0
  6.         while (_speed_dat_flag)
  7.                 ; // 等待flag为0
  8.         _angle_dangle = (_angle_this_dat - _angle_last_dat);
  9.         if (_angle_dangle != 0)
  10.                 _speed_dtime = 0;
  11.         _speed_dtime = (_speed_this_time - _speed_last_time);
  12.         if (_angle_dangle < -(Encode_bit_Max / 2))
  13.                 _angle_dangle += Encode_bit_Max; // 过零处理
  14.         if (_angle_dangle > (Encode_bit_Max / 2))
  15.                 _angle_dangle -= Encode_bit_Max;
  16.         _angle_last_dat = _angle_this_dat;
  17.         _speed_last_time = _speed_this_time;
  18.         Set_Time_Dat += (4096 - abs(_angle_dangle)); // 根据角度差自适应
  19.         if (Set_Time_Dat > 50000)
  20.                 Set_Time_Dat = 50000; // 限制最大值
  21.         if (Set_Time_Dat < 250)
  22.                 Set_Time_Dat = 250; // 限制最小值
  23.         Time_Dat = (u16)(65536UL - Set_Time_Dat);
  24.         TH0 = (u8)(Time_Dat >> 8);
  25.         TL0 = (u8)Time_Dat;
  26.         TR0 = 1; // 设置完成再开启
  27. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2218

回帖

5450

积分

版主

积分
5450
发表于 2023-12-6 16:42:00 | 显示全部楼层
本帖最后由 王昱顺 于 2023-12-6 16:45 编辑

最近成果,完成了基于磁编码器较为稳定的速度读取


时间上使用的是PWM作为全局时间滴答定时器,因为用定时器好像读TH和TL的时候总是有几个数据会抽风
角度数据是SPI-DMA读取的

截图202312061640105322.jpg

  1. void PWM_Transform_Timer_Init(void)
  2. {
  3.     //PWMB工作在普通模式
  4.     PWMB_PSCRH = (u8)(52 >> 8);//1Mhz输出,1us定时精度
  5.     PWMB_PSCRL = (u8)(52);
  6.     PWMB_ARRH = (u8)(50000 >> 8);//50ms中断一次,降低性能开销
  7.     PWMB_ARRL = (u8)(50000);
  8.     PWMB_CR1 = 0x05;//启动定时器,仅计数器溢出可中断
  9.     PWMB_IER = 0x01;//仅允许更新中断
  10.     PPWMBH = 1;
  11.     PPWMB = 1;//最高优先级
  12. }
  13. void PWMB_Isr(void) interrupt 27
  14. {
  15.     PWMB_SR1 = 0x00;//清除标志位
  16.     Tick_ms+=50;//每次溢出都是50ms
  17. }
  18. u16 Read_Timer_Cnt(void)
  19. {
  20.     u8 cnth, cntl;
  21.     cnth = PWMB_CNTRH;
  22.     cntl = PWMB_CNTRL;
  23.     return (u16)cnth << 8 | (u8)cntl;
  24. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2218

回帖

5450

积分

版主

积分
5450
发表于 2023-12-8 11:25:05 | 显示全部楼层
增加了启动自检声音


实现的方式是通过调整PWM的分频系数使得电机的基频改变,然后对其中一相注入一定的电压(正常情况是50%占空比,不发声),这样就可以让电机发出声音了。
通过对基频的改变可以发出不同音调的声音,三声嘀嘀嘀可以分别注入三相,这样如果线没接好/电机线圈断开的情况,就不是完整的三声,可能是两声响或者不出声音了。
以下是效果视频:



实现代码:
  1. void Set_PWM_PSC(u16 dat) // 设置PWM基频用于发出声音
  2. {
  3.     WritePWMA((char)&PWMA_PSCRH, (u8)(dat >> 8)); // 预分频,异步方式
  4.     WritePWMA((char)&PWMA_PSCRL, (u8)(dat));
  5. }
  6. void Reset_PWM_PSC(void)
  7. {
  8.     WritePWMA((char)&PWMA_PSCRH, (u8)(Moto_PWM_PSC >> 8)); // 预分频
  9.     WritePWMA((char)&PWMA_PSCRL, (u8)(Moto_PWM_PSC));
  10. }
  11. // 缺相检测,电机线断联/坏掉就会少于三声
  12. void Di_Di_Di(void)
  13. {
  14.         // 设置基频分频系数
  15.         Set_PWM_PSC(28);
  16.         setPwm((0.05 / 12.0 * Moto_PWM_PERIOD), 0, 0); // A相,0.05V响应电压(声音小)
  17.         Delay200ms();
  18.         Set_PWM_PSC(24);
  19.         setPwm(0, (0.05 / 12.0 * Moto_PWM_PERIOD), 0); // B相
  20.         Delay200ms();
  21.         Set_PWM_PSC(22);
  22.         setPwm(0, 0, (0.05 / 12.0 * Moto_PWM_PERIOD)); // C相
  23.         Delay200ms();
  24.         Reset_PWM_PSC(); // 恢复基频
  25.         setPwm(0, 0, 0);
  26. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:372
  • 最近打卡:2025-05-01 10:53:48

12

主题

125

回帖

1685

积分

金牌会员

积分
1685
发表于 2023-12-8 17:35:15 | 显示全部楼层
厉害
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2218

回帖

5450

积分

版主

积分
5450
发表于 2023-12-9 20:36:14 | 显示全部楼层
本帖最后由 王昱顺 于 2023-12-9 20:43 编辑

新增加了电机参数自动辨识功能


目前可以自动辨识的参数包括:
电机极对数、磁铁安装方向、磁编码器零点校准值

并且使用EEPROM进行存储,一次校准后,后面一直可以使用。
下载时需要去掉”擦除用户EEPROM“选线
截图202312092043423846.jpg


目前有两种触发校准的方式:
1.判断EEPROM中没有存储数据,按下KEY按键时自动进行一次校准,校准完成之后进行等待。
2.长按KEY按键会触发一次EEPROM扇区擦除,此时再按一次KEY就可以重新校准了。
除此之外短按KEY都是测试启动,可以启动/停止电机用来快速测试。


下面是测试视频:



点评

好,一直在前进  发表于 2023-12-9 23:14
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:497
  • 最近打卡:2025-04-30 20:48:13
已绑定手机

151

主题

589

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-12-11 15:43:36 | 显示全部楼层
一起玩起来
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:484
  • 最近打卡:2025-05-01 08:52:01
已绑定手机

23

主题

589

回帖

2813

积分

金牌会员

积分
2813
发表于 2023-12-11 16:14:30 | 显示全部楼层
学习
不停地学习
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:382
  • 最近打卡:2025-04-30 16:48:47

10

主题

214

回帖

1519

积分

金牌会员

积分
1519
发表于 2023-12-12 08:30:56 | 显示全部楼层

向高手学习
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 19:38 , Processed in 0.241092 second(s), 116 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表