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
查看完整版本: 【STC-FOC Lite】 FOC青春版,更少的成本,更简单的构造