aqa
发表于 2023-12-5 12:10:53
学习
aqa
发表于 2023-12-5 12:26:56
下载了
王昱顺
发表于 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赋给定时器初值,改变定时器计时时间的方式实现速度采样。
以下是有关的代码实现long Set_Time_Dat = 0;
void Timer0_Isr(void) interrupt 1
{
u16 Time_Dat;
TR0 = 0; // 关掉定时器0
while (_speed_dat_flag)
; // 等待flag为0
_angle_dangle = (_angle_this_dat - _angle_last_dat);
if (_angle_dangle != 0)
_speed_dtime = 0;
_speed_dtime = (_speed_this_time - _speed_last_time);
if (_angle_dangle < -(Encode_bit_Max / 2))
_angle_dangle += Encode_bit_Max; // 过零处理
if (_angle_dangle > (Encode_bit_Max / 2))
_angle_dangle -= Encode_bit_Max;
_angle_last_dat = _angle_this_dat;
_speed_last_time = _speed_this_time;
Set_Time_Dat += (4096 - abs(_angle_dangle)); // 根据角度差自适应
if (Set_Time_Dat > 50000)
Set_Time_Dat = 50000; // 限制最大值
if (Set_Time_Dat < 250)
Set_Time_Dat = 250; // 限制最小值
Time_Dat = (u16)(65536UL - Set_Time_Dat);
TH0 = (u8)(Time_Dat >> 8);
TL0 = (u8)Time_Dat;
TR0 = 1; // 设置完成再开启
}
王昱顺
发表于 2023-12-6 16:42:00
本帖最后由 王昱顺 于 2023-12-6 16:45 编辑
最近成果,完成了基于磁编码器较为稳定的速度读取
时间上使用的是PWM作为全局时间滴答定时器,因为用定时器好像读TH和TL的时候总是有几个数据会抽风
角度数据是SPI-DMA读取的
void PWM_Transform_Timer_Init(void)
{
//PWMB工作在普通模式
PWMB_PSCRH = (u8)(52 >> 8);//1Mhz输出,1us定时精度
PWMB_PSCRL = (u8)(52);
PWMB_ARRH = (u8)(50000 >> 8);//50ms中断一次,降低性能开销
PWMB_ARRL = (u8)(50000);
PWMB_CR1 = 0x05;//启动定时器,仅计数器溢出可中断
PWMB_IER = 0x01;//仅允许更新中断
PPWMBH = 1;
PPWMB = 1;//最高优先级
}
void PWMB_Isr(void) interrupt 27
{
PWMB_SR1 = 0x00;//清除标志位
Tick_ms+=50;//每次溢出都是50ms
}
u16 Read_Timer_Cnt(void)
{
u8 cnth, cntl;
cnth = PWMB_CNTRH;
cntl = PWMB_CNTRL;
return (u16)cnth << 8 | (u8)cntl;
}
王昱顺
发表于 2023-12-8 11:25:05
增加了启动自检声音
实现的方式是通过调整PWM的分频系数使得电机的基频改变,然后对其中一相注入一定的电压(正常情况是50%占空比,不发声),这样就可以让电机发出声音了。
通过对基频的改变可以发出不同音调的声音,三声嘀嘀嘀可以分别注入三相,这样如果线没接好/电机线圈断开的情况,就不是完整的三声,可能是两声响或者不出声音了。
以下是效果视频:
实现代码:
void Set_PWM_PSC(u16 dat) // 设置PWM基频用于发出声音
{
WritePWMA((char)&PWMA_PSCRH, (u8)(dat >> 8)); // 预分频,异步方式
WritePWMA((char)&PWMA_PSCRL, (u8)(dat));
}
void Reset_PWM_PSC(void)
{
WritePWMA((char)&PWMA_PSCRH, (u8)(Moto_PWM_PSC >> 8)); // 预分频
WritePWMA((char)&PWMA_PSCRL, (u8)(Moto_PWM_PSC));
}
// 缺相检测,电机线断联/坏掉就会少于三声
void Di_Di_Di(void)
{
// 设置基频分频系数
Set_PWM_PSC(28);
setPwm((0.05 / 12.0 * Moto_PWM_PERIOD), 0, 0); // A相,0.05V响应电压(声音小)
Delay200ms();
Set_PWM_PSC(24);
setPwm(0, (0.05 / 12.0 * Moto_PWM_PERIOD), 0); // B相
Delay200ms();
Set_PWM_PSC(22);
setPwm(0, 0, (0.05 / 12.0 * Moto_PWM_PERIOD)); // C相
Delay200ms();
Reset_PWM_PSC(); // 恢复基频
setPwm(0, 0, 0);
}
lzzasd
发表于 2023-12-8 17:35:15
厉害 {:4_174:}{:4_174:}{:4_174:}{:4_174:}
王昱顺
发表于 2023-12-9 20:36:14
本帖最后由 王昱顺 于 2023-12-9 20:43 编辑
新增加了电机参数自动辨识功能
目前可以自动辨识的参数包括:
电机极对数、磁铁安装方向、磁编码器零点校准值
并且使用EEPROM进行存储,一次校准后,后面一直可以使用。
下载时需要去掉”擦除用户EEPROM“选线
目前有两种触发校准的方式:
1.判断EEPROM中没有存储数据,按下KEY按键时自动进行一次校准,校准完成之后进行等待。
2.长按KEY按键会触发一次EEPROM扇区擦除,此时再按一次KEY就可以重新校准了。
除此之外短按KEY都是测试启动,可以启动/停止电机用来快速测试。
下面是测试视频:
380091044
发表于 2023-12-11 15:43:36
一起玩起来
WHX
发表于 2023-12-11 16:14:30
学习
pangshijz
发表于 2023-12-12 08:30:56
向高手学习{:4_250:}
页:
1
2
[3]
4
5
6
7
8
9
10
11