OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8790|回复: 21

关于带有直流电机的电位器的控制问题,控制电机来控制电位器的位置

[复制链接]

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
发表于 2017-12-4 16:00:14 | 显示全部楼层 |阅读模式
3金钱
我手上现有一个这样的推子,其实就是一个电位器带有直流电机,电位器是10K电阻。

推子

推子


1.现在我自己的做法是使用ADC读取电位器的电压,读取到的数值是10-4095的范围,把读取到的数据转换成1-100的数据。
接口1是接GND,接口3是接VCC 3.3V,接口2是给ADC读取数据,推动推子会改变电位器的电阻,总阻止为10K,T接口是轨迹跟踪,不知道怎么用。附上电位器的说明。

电位器

电位器

电位器电路

电位器电路


2.推子的电机我是使用DRV8833芯片来驱动,STM32 IO两针脚接入带IN1和IN2,给IN1高电平,IN2低电平,推子向上移动,给IN1低电平,IN2高电平,推子向下移动,这样就实现了电机的正反转;
采用PWM互补通道来驱动的,72MHz主频,定时器预分频为1分频,定时周期为900,那么450为占空比50%,电机不运行,900为占空比100%,推子全速向上移动,0为占空比0%,推子全速向下移动,这样也实现了电机的正反转,而且可以实现快慢速移动;

如果采用PWM亮通道来驱动,72MHz主频,定时器预分频为1分频,定时周期为500,那么250为占空比50%,,两IO都是250占空比50%,那么电机不运行,IO1设置为500占空比为100%,IO2设置为0占空比为0%,那么推子向上移动,IO1设置为0占空比为0%,IO2设置为100占空比为100%,那么推子向下移动,这样也实现了电机的正反转,而且可以实现快慢速移动;


md5.jpg md6.jpg md7.jpg

3.
这个是我写的读取AD滤波的代码,使用的是HAL库,STM32CubeMX生成的代码,读取8个电位器的电压,每个通道取10个数据减去最大值和最小值取平均值,本次的值占6成,上一次的值占4成作为第一次滤波;第二次滤波是获取每个通道10个数据先由大到小排序,然后去除前后4个数,取3-8位6个数取平均值;最后每个通道的AD值是,本次二次滤波占5成+一次滤波占3成+上次二次滤波占2成作为最终AD的值。
3.1.这样滤波的话,不知是否有问题?我读取的数据是10多到4094,如果不经过滤波的话是10多到4095.
3.2.我在二次滤波最后赋值到通道的时候,AD_CH=(sum2*5+After_filter*3+AD_CH*2)/10;在main函数里调用AD_CH的时候,值也是10多到4094,AD_CH*100/4094就转成1-100的数值。而我在二次滤波那里改成AD_CH=((sum2*5+After_filter*3+AD_CH*2)/10)*100/4094;,那么再在main函数里调用AD_CH的值就会变成1-80,数据少了20,这个是什么原因?
[mw_shl_code=c,true]        /**************ADC一次滤波*****************/
void ADC_Filter(void)
{
         int max=0,min=60000;  
   int sum = 0,sum2=0;
   uint16_t count;
         int t;
        uint8_t i,j,k;
       
for(i=0;i<channel;i++)//8个通道
{
  for(count=0;count<data/8+1;count++)//80个数据,每个通道占10个数据
  {
                sum += AD_Value[count];//10个数据的总和
//                printf("i=%d count=%d sum=%d AD_Value=%d\n",i,count,sum,AD_Value[count]);
                if(AD_Value[count]>max)        max=AD_Value[count];//获取最大值
                if(AD_Value[count]<min)        min=AD_Value[count];//获取最小值
  }
        sum=sum-max-min;//10个数据的总和减去最大值和最小值
  After_filter=(sum/((data+1)/8-2)*6+After_filter*4)/10; //一次过滤后的值,本次过滤值占6成,上一次过滤值占4成
//        printf("max=%d,min=%d,sum=%d,After_filter[%d]=%d\n",max,min,sum,i,After_filter);

        /**************ADC二次滤波*****************/
        for(k=0;k<data/8+1;k++)
        {
                AD_Value1[k]=AD_Value[k];//获取每个通道的数据作为二次过滤的数据
//                printf("k=%d,AD_Value1=%d,i=%d\n",k,AD_Value1[k],i);
        }
   for(k=0;k<data/8+1;k++){      
    for(j=0;j<(data/8+1)-k;j++)
     if(AD_Value1[j]>AD_Value1[j+1])
      {
                                t=AD_Value1[j];
                                AD_Value1[j]=AD_Value1[j+1];  
                                AD_Value1[j+1]=t;
                        }//每个通道按大到小排序
   }
         /*累加ADC的值*/
        for(k=(data/8+1)/5;k<channel;k++)
        {
                //3到8累加
                sum2 += AD_Value1[k];
//                printf("k=%d,sum2=%d,AD_Value1=%d\n",k,sum2,AD_Value1[k]);
        }
       
        /*3到8的平均值*/
        sum2 /= (channel-1-1);
        AD_CH=(sum2*5+After_filter*3+AD_CH*2)/10;
       
  sum=0;
        sum2=0;
        max=0;
        min=6000;
}
}[/mw_shl_code]
4.我想要实现的功能是:
1.我推动推子,AD读取的数据为1-100,把这个数据发给DSP来控制音量,1为最小声,100为最大声,如果我写的获取电位器电压的滤波没有问题的话,这个已经解决了;
2.在外部我会使用软件来控制推子的位置,例如我需要推子去到50这个位置,AD读取到的数据是30,那么推子就需要向上移动到50的位置,电机就需要把推子推到50的位置。
现在的问题是不知道怎么控制电机把推子推到需要设定的位置。
第一我是使用IO输出高低电平控制推子的 方向,全速运行.这样的情况是去到那个位置的时候不停地跳动,不能准确地确认那个位置。
[mw_shl_code=c,true]void PID_PWM(uint32_t SetPoint)
{
               
      uint32_t NextPoint;
      int iError,iError2;//偏差值
      
        while(1)
        {
                        ADC_Filter();//ADC过滤
                  /* 得到AD获取值,数值为1-100 */
      NextPoint=AD_CH[0]*100/4094;
      /*计算偏差值,确定推子移动的方向*/     
      iError=SetPoint-NextPoint;
                        iError2=NextPoint-SetPoint;
      printf("设定目标位置 -> %d\n",SetPoint);
                        printf("当前目标位置 -> %d\n",NextPoint);
                        printf("差值1 -> %d,差值12 -> %d\n",iError,iError2);               
                        if(iError > 0)
                        {
                                HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,0);
                                HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,1);
                                if(iError2<10 && iError2>=0)
                                {
                                        HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,0);
                                        HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,0);
                                        break;
                                }
                        }
                         else if(iError < 0)
                        {
                                HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,1);
                                HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,0);
                                if(iError2<10 && iError2>=0)
                                {
                                        HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,0);
                                        HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,0);
                                        break;
                                }
                        }
                        else
                        {
                                break;
                        }
        }
}[/mw_shl_code]

第二,我是使用PWM来控制电机的速度也是一样的做法,设定的值和AD读取到的值对比,相减小于10的时候降低电机速度,相等的时候停止,但是也是一样不停地在那个位置跳动。

我想知道用什么方法可以实现这样的功能?或者有那位大神可以帮助小弟的,小弟万分感激,最好可以有做过类似的案例参考一下,小弟也附上我的项目,麻烦懂的朋友帮忙修改一下。 ADC_DMA_Test1.zip (18.38 MB, 下载次数: 322)

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-4 16:00:15 | 显示全部楼层
难道已经沉下去了吗?
回复

使用道具 举报

2

主题

130

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1878
金钱
1878
注册时间
2011-9-16
在线时间
421 小时
发表于 2017-12-4 17:58:19 | 显示全部楼层
这是卖香烟的机子上用的?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2017-12-5 01:40:18 | 显示全部楼层
帮顶
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-5 07:58:48 | 显示全部楼层
mackyming 发表于 2017-12-4 17:58
这是卖香烟的机子上用的?

这是用在调音台上,控制音量
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-5 08:05:15 | 显示全部楼层
不会真的已经沉到底了吧?难道没有人做过这些吗?给些建议也好啊
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2017-12-5 08:36:12 | 显示全部楼层
没做过,AD采回的数值有些许跳动是正常的,跳动过大那就有干扰了吧。 闭环控制的话应该用PID吧,调PID参数
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-5 08:47:00 | 显示全部楼层
wxjhby 发表于 2017-12-5 08:36
没做过,AD采回的数值有些许跳动是正常的,跳动过大那就有干扰了吧。 闭环控制的话应该用PID吧,调PID参数

主要是不知道PID用来做什么,是用来控制电机速度,还是控制AD读取到的数据和传输进来的数据做差值使用,我试过PID只是控制电机的速度,但是不知道用PID怎么做到可以控制电机去到那个位置的停止
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2017-12-5 08:59:59 | 显示全部楼层
本帖最后由 wxjhby 于 2017-12-5 09:01 编辑

假设音量设定值是 1-100,1-100 对应的AD值 10 - 4095 量程越大控制的越精确所以要用AD值做控制,PID做的差应该是当前位置值 与 目标位置值的差,然后改变的是电机的PWM频率,也就是电机速度,差值越大,给电机的PWM值越大,差值越小,给电机的PWM值越小。误差不能保证真的为0,在某个误差范围内,就认为已经到位。 如果你要对电机的速度也要进行闭环,那么还要加光电编码器,再弄一套PID,没必要的吧.  以上只是个人想法,仅供参考,不确保一定可行。PID简单是因为不用建模,但是参数整定还是很麻烦的
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-5 10:37:04 | 显示全部楼层
wxjhby 发表于 2017-12-5 08:59
假设音量设定值是 1-100,1-100 对应的AD值 10 - 4095 量程越大控制的越精确所以要用AD值做控制,PID做的差 ...

我需要的功能是把AD的值转换成1-100,然后用PID来比比目标值和设定值的差值,但是我是需要电机全速来推到推子,应该算差值来推动推子的话,推子速度太慢,感觉不行,因为别人的是无论去那里位置,电机的速度都是全速推动的,所以我才不知道是不是应该使用pwm来控制电机的速度,如果是全速的话,直接给高低电平控制比较简单,只要怎么判断AD获取的位置和设定的位置相等就停止电机,但是这样又会有抖动
回复

使用道具 举报

2

主题

130

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1878
金钱
1878
注册时间
2011-9-16
在线时间
421 小时
发表于 2017-12-5 11:16:32 | 显示全部楼层
本帖最后由 mackyming 于 2017-12-5 11:21 编辑

是你的电机控制策略有问题,怎么能使用互补PWM来控制H桥驱动直流电机呢,这样即使占空比为50%电机也不是处于完全静止状态,而是处于抖动状态,取决于你的PWM频率。
直流电机控制你可以采用上臂PWM,使H桥下臂处于低电平,这样可以通过占空比调速,需要停止的的时候置上下臂都为低电平即可(或都为高)),这时电机才完全处于静止状态。你仔细看下DRV8833的真值表吧。
阿里旺旺图片20171205112724.jpg
阿里旺旺图片20171205112743.jpg
回复

使用道具 举报

15

主题

406

帖子

0

精华

高级会员

Rank: 4

积分
795
金钱
795
注册时间
2015-3-26
在线时间
151 小时
发表于 2017-12-5 11:28:11 | 显示全部楼层
还不如换数字电位器呢
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-6 09:41:55 | 显示全部楼层
mackyming 发表于 2017-12-5 11:16
是你的电机控制策略有问题,怎么能使用互补PWM来控制H桥驱动直流电机呢,这样即使占空比为50%电机也不是处 ...

我试了一下,两个IO都使用pwm模式,一个通道使用pwm输出,一个给低电平,全速运行电机判断位置就停,但是会跑过设定的位置一点点,这个应该怎么解决?附上代码[mw_shl_code=c,true]void PID_PWM(uint32_t SetPoint)
{
      uint32_t NextPoint;
      int iError,iError2;//偏差值
      
        while(1)
        {
                        ADC_Filter();//ADC过滤
                  /* 得到AD获取值,数值为1-100 */
      NextPoint=AD_CH[0]*1000/4094;
      /*计算偏差值,确定推子移动的方向*/     
      iError=SetPoint-NextPoint;
                        iError2=NextPoint-SetPoint;
      printf("设定目标位置 -> %d\n",SetPoint);
                        printf("当前目标位置 -> %d\n",NextPoint);
                        printf("差值1 -> %d,差值12 -> %d\n",iError,iError2);               
                        if(iError > 0)        //推子向上移动
                        {
                                HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
                                __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,1000);
                                HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,0);
                                if(iError2<10 && iError2>=0)
                                {
                                        HAL_TIM_PWM_Stop(&htim3,TIM_CHANNEL_4);
                                        HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,0);
                                        HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,0);
                                        break;
                                }
                        }
                         else if(iError < 0)//推子向下移动
                        {
                                HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
                                __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,1000);
                                HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,0);
                                if(iError2<10 && iError2>=0)
                                {
                                        HAL_TIM_PWM_Stop(&htim3,TIM_CHANNEL_3);
                                        HAL_GPIO_WritePin(MD1_GPIO_Port,MD1_Pin,0);
                                        HAL_GPIO_WritePin(MD2_GPIO_Port,MD2_Pin,0);
                                        break;
                                }
                        }[/mw_shl_code]
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-6 09:42:23 | 显示全部楼层
xyl210xyl 发表于 2017-12-5 11:28
还不如换数字电位器呢

数字电位器有和我使用的推子电位器一样的吗?
回复

使用道具 举报

15

主题

406

帖子

0

精华

高级会员

Rank: 4

积分
795
金钱
795
注册时间
2015-3-26
在线时间
151 小时
发表于 2017-12-6 10:12:25 | 显示全部楼层
sea008 发表于 2017-12-6 09:42
数字电位器有和我使用的推子电位器一样的吗?

只能说有这么种东西,但是符不符合你们的应用就不知道了 ,可以了解一下;本身就是电子的调电位,需要用电机的去转化成机械,然后再去控制电位 。。。是不是有点繁琐
回复

使用道具 举报

4

主题

52

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
282
金钱
282
注册时间
2014-2-20
在线时间
27 小时
发表于 2017-12-6 10:49:32 | 显示全部楼层
为什么不用步进电机呢?
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-6 13:31:10 | 显示全部楼层
沉默的疯狂 发表于 2017-12-6 10:49
为什么不用步进电机呢?

做我们这个都是用这些,买回来配套的都是直流电机。没有办法,除非自己换电机,这个又没有必要
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-6 13:32:21 | 显示全部楼层
xyl210xyl 发表于 2017-12-6 10:12
只能说有这么种东西,但是符不符合你们的应用就不知道了 ,可以了解一下;本身就是电子的调电位,需要用 ...

这个虽然是电位器控制音量,但是也会用到上位器来控制推子的位置,所以要需要靠电机来推动电位器的推子
回复

使用道具 举报

15

主题

406

帖子

0

精华

高级会员

Rank: 4

积分
795
金钱
795
注册时间
2015-3-26
在线时间
151 小时
发表于 2017-12-6 17:08:34 | 显示全部楼层
sea008 发表于 2017-12-6 13:32
这个虽然是电位器控制音量,但是也会用到上位器来控制推子的位置,所以要需要靠电机来推动电位器的推子

直流电机怎么定位
回复

使用道具 举报

2

主题

130

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1878
金钱
1878
注册时间
2011-9-16
在线时间
421 小时
发表于 2017-12-7 13:37:42 | 显示全部楼层
这个电位器其实就是当绝对位置编码器来使的
对于定位误差,只要不大于允许的数值是能够接受的
提高定位精度的方法:
1你可以采用固定偏差来修正,比如说定位到100,你在98 的时候就控制停掉,转动惯量或动作延时会使停止的时候在100左右
2采用减速曲线,比如说定位到100,你在90的时候就降低电机运行速度,使用低速运行到目标值,
3反复调整,超过了就反转,达不到就正转,直到满足条件
如果你能把上面几个办法组合使用,应当能得到你需要的效果
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2017-12-4
在线时间
56 小时
 楼主| 发表于 2017-12-8 08:09:09 | 显示全部楼层
mackyming 发表于 2017-12-7 13:37
这个电位器其实就是当绝对位置编码器来使的
对于定位误差,只要不大于允许的数值是能够接受的
提高定位精 ...

有没有类似这个代码给我参考一下?不知道是不是我自己的代码问题,总是实现不了这样,总是会超出位置才停止
回复

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-5-23
在线时间
2 小时
发表于 2018-5-23 13:23:58 | 显示全部楼层
学习,学习!!!
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-7 16:18

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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