极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 22839|回复: 16

技术问题

[复制链接]
发表于 2014-6-14 22:16:01 | 显示全部楼层 |阅读模式
我最近想做一个东西,但苦于不知道如何控制它。可能是C语言不行,亦或者是没有Arduino编程思想,弄了好几天都没什么结果。好了废话不多说,我讲一下我的问题吧。
大概想法就是:拿一个直滑式电位器(线性的)作为“定位器”,根据滑杆的位置换算出电机应该运动的时间,首先,我把从电位器引脚读取的值等分成三段0~341,341~682,682~1024,处在0~341段的就前进,前进的时间根据滑杆的位置;处在341~682段的停止;处在682~1023段的后退。可是在编程的时候出现了问题,让它动起来容易,但是它根本停不下来。

  1. int R_pin = 14;//定义模拟引脚1
  2. void setup()
  3. {
  4.   pinMode(8,OUTPUT);//定义电机需要的引脚
  5.   pinMode(9,OUTPUT);
  6.   pinMode(10,OUTPUT);
  7.   pinMode(5,OUTPUT);
  8.   pinMode(6,OUTPUT);
  9.   pinMode(7,OUTPUT);
  10.   pinMode(14,INPUT);
  11.   Serial.begin(9600);
  12. }
  13. void qianjin()//前进
  14. {
  15.      
  16.      digitalWrite(10,300);
  17.      digitalWrite(5,300);
  18.      digitalWrite(7,HIGH);//使直流电机(左)逆时针转
  19.      digitalWrite(6,LOW);
  20.      digitalWrite(8,LOW);//使直流电机(右)顺时针转
  21.      digitalWrite(9,HIGH);
  22. }

  23. void tingzhi()//停止
  24. {
  25.      digitalWrite(6,HIGH);//使直流电机(左)制动
  26.      digitalWrite(7,HIGH);
  27.      digitalWrite(8,HIGH);//使直流电机(右)制动
  28.      digitalWrite(9,HIGH);
  29. }
  30. void houtui()
  31. {
  32.      digitalWrite(10,300);//输入模拟值进行设定速度
  33.      digitalWrite(5,300);
  34.      digitalWrite(6,HIGH);//使直流电机(左)逆时针转
  35.      digitalWrite(7,LOW);
  36.      digitalWrite(8,HIGH);//使直流电机(右)顺时针转
  37.      digitalWrite(9,LOW);
  38. }
  39. void loop()
  40. {   int R,x,s,val=0,old_val=0;
  41.     unsigned long startTime=0;
  42.     float t;
  43.     val= analogRead(R_pin);
  44.     Serial.println(val);
  45.    if(old_val == val)
  46. {
  47.    startTime = millis(); //用来计时
  48.    if(val< 341){
  49.     t=0.0088*(341-val);
  50.     qianjin();
  51.     delay(t*1000+1000);
  52.     houtui();
  53.     delay(1000);
  54.     qianjin();
  55.     delay(1000);
  56.     houtui();
  57.     delay(t*1000+1000);
  58.     if(millis()-startTime<=5000)
  59.     tingzhi();
  60.     }
  61.     if(341 <= val <= 682)
  62.     tingzhi();
  63.   if(val>682){
  64.     t=0.0088*(val-682);
  65.     houtui();
  66.     delay(t*1000+1000);
  67.     qianjin();
  68.     delay(1000);
  69.     houtui();
  70.     delay(1000);
  71.     qianjin();
  72.     delay(1000);
  73.     tingzhi();
  74.     }
  75. }
  76. old_val = val;
  77. }
复制代码

我想着就是:滑杆到某个位置时,只要一次那样的动作(前进,后退,前进,后退,停止),停止后,再手动归位(就是手动把滑杆推到中间的位置,也就是模拟值在341~682的地方),如果下次再推动滑杆的时候还能继续那样的动作。
然而上述程序的结果是:一直前进,后退.............
求解啊!!!!希望大神级人物能够给个思路,让我继续走下去...



回复

使用道具 举报

发表于 2014-6-16 03:19:54 | 显示全部楼层
int R_pin = 14;//定义模拟引脚1  ??

模擬輸入analog in應該是A0~A5吧!!
回复 支持 反对

使用道具 举报

发表于 2014-6-16 06:56:29 | 显示全部楼层
你用了太多的delay,我想问题可能出在这里。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-18 15:01:18 | 显示全部楼层
hsr18299 发表于 2014-6-16 03:19
int R_pin = 14;//定义模拟引脚1  ??

模擬輸入analog in應該是A0~A5吧!!

模拟引脚A0~A5对应14~19
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-18 15:03:56 | 显示全部楼层
弘毅 发表于 2014-6-16 06:56
你用了太多的delay,我想问题可能出在这里。

你知道还有什么可以用来定位的吗?我是书上看到有个“位置感测模块”,但是在淘宝上找不到,我就纳闷了。。。
回复 支持 反对

使用道具 举报

发表于 2014-7-3 15:44:52 | 显示全部楼层
本帖最后由 沧海笑1122 于 2014-7-3 15:50 编辑

1、我们简单探讨一下你的程序:
手头没有板子,我大致看了一下,给你的val设定了三种情形:
(1)val=1
t=0.0088*340=2.992
前进后,延时3992
后退,延迟1000
前进,1000
后退,3992
这时的时间流逝:9984。不满足<=5000
结果:停不下来


(2)val=100
t=0.0088*241=2.1208
前进,3120
后退,1000
前进,1000
后退,3120
这时的时间流逝:8242。不满足<=5000
结果:停不下来


(3)val=340
t=0.0088*1=0.0088
前进:1009
后退,1000
前进,1000
后退,1009
这时的时间流逝:4018。满足<=5000
结果:可以停下来

那么,你的“停止”临界点在哪里呢?我们可以推导一下:
你的一个动作后,延时一共是:2*t*1000+4000
如果小于5000才能停下来,t<=0.5
t=0.0088*(341-val)
val>284,也就是说,你稳定地输入一个大于284,且小于341的值,是可以得到你的控制结果的。

那么,为什么你得不到呢?
原因在于你不可能一步推到这个值。你的电阻值一定是从零开始一点一点加上去的,你在读取val却没有消抖(没有等待其到位的延时),所以在电阻从val=0到284之间,按照你的控制逻辑停不下来的。而且一直陷于不停地delay累加当中,那会是一个很大的累加值。可以想象你的控制结果一定是不停地前进、后退。
所以我觉得是你的逻辑出了问题,你用了一个费力不讨好的方法。

为了验证你的逻辑,你可以抛开电阻,直接用串口下发val,或者在变量里先一步到位给他一个320,看看你的控制逻辑能否实现。

2、楼主是要控制小车的进退转向吗?
你可以考虑上摇杆,本身那就是两个轴的可变电阻,可以满足你的控制要求。

2、下位机这边是小车吧,小车有非常成熟的控制方法,可以看看本论坛的BOXZ库。http://wiki.geek-workshop.com/doku.php?id=arduino:libraries:boxz
3、你的电机驱动用的什么模块,我看到你设定速度“300”,最大是255吧?


另外,除了代码,最好把你的接线图,所用器件附上,大家可以帮助你。
如果你需要帮助,请详细回应,我晚上回去帮你把程序走一边,因为现在没有板子,也可能说得不对。我们可以一起探讨,arduino的乐趣本身就在这里。希望能够帮到你。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-3 22:33:09 | 显示全部楼层

本帖最后由 49741933o 于 2014-7-3 22:47 编辑

首先谢谢你精彩的答复和给的链接
驱动模块用的是L289N
这是我稍微修改了一下的代码(虽然还是没有达到预期的效果,但是看起来整洁一些!)
  1. int R_pin = 14; //定义电位器的引脚
  2. void setup()
  3. {
  4.   pinMode(8,OUTPUT);//定义输入、输出接口
  5.   pinMode(9,OUTPUT);
  6.   pinMode(10,OUTPUT);
  7.   pinMode(5,OUTPUT);
  8.   pinMode(6,OUTPUT);
  9.   pinMode(7,OUTPUT);
  10.   pinMode(14,INPUT);
  11.   Serial.begin(9600);
  12. }
  13. void qianjin()//前进,
  14. {
  15.      
  16.      digitalWrite(10,300);
  17.      digitalWrite(5,255);
  18.      digitalWrite(7,HIGH);//使直流电机(左)逆时针转
  19.      digitalWrite(6,LOW);
  20.      digitalWrite(8,LOW);//使直流电机(右)顺时针转
  21.      digitalWrite(9,HIGH);
  22. }

  23. void tingzhi()//停止
  24. {
  25.      digitalWrite(6,HIGH);//使直流电机(左)制动
  26.      digitalWrite(7,HIGH);
  27.      digitalWrite(8,HIGH);//使直流电机(右)制动
  28.      digitalWrite(9,HIGH);
  29. }
  30. void houtui()
  31. {
  32.      digitalWrite(10,255);
  33.      digitalWrite(5,255);
  34.      digitalWrite(6,HIGH);//使直流电机(左)逆时针转
  35.      digitalWrite(7,LOW);
  36.      digitalWrite(8,HIGH);//使直流电机(右)顺时针转
  37.      digitalWrite(9,LOW);
  38. }
  39. void loop()
  40. {   int x,val;
  41.    float t;
  42.     val= analogRead(R_pin);
  43.     Serial.println(val);
  44.    if(val< 341)
  45.     { x=0; t=0.0088*(341-val);}
  46.    else if(341 <= val <=682)
  47.      x=1;
  48.    if(val > 682)
  49.     { x=2;  t=0.0088*(val-682);}
  50. switch(x)
  51.    {
  52.      case 0:
  53.      {
  54.        qianjin();delay(t*1000+1000);
  55.        houtui();delay(1000);
  56.        qianjin();delay(1000);
  57.        houtui();delay(t*1000+1000);
  58.      }break;
  59.      case 1:
  60.        tingzhi();break;
  61.      case 2:
  62.      {
  63.        houtui();delay(t*1000+1000);
  64.        qianjin();delay(1000);
  65.        houtui();delay(1000);
  66.        qianjin();delay(1000);
  67.       } break;
  68.    }
  69. }
复制代码
你说的对,我是用小车来反应现象的。最上面的程序可以实现前进和后退,就是停不下来。 抛开最上面的程序,不说那个了,说这个-------->反正我想实现的就是:如果我推到了一个位置,小车只会有一次相应的动作。比如推到320,小车会前进,后退,前进,后退,此时小车已到达初始位置,然后,它应该停止了,等待接受下一个信号,继续下一个动作,但是因为我没有去推滑杆(其实也不需要、不应该推),所以读取的信号还是和原来的一样,(问题就在这,所以小车一直前进,后退,不能停止。)我不知道怎样去控制它
回复 支持 反对

使用道具 举报

发表于 2014-7-4 13:00:57 | 显示全部楼层
本帖最后由 沧海笑1122 于 2014-7-4 13:09 编辑

     请楼主仔细看我的回复, val= analogRead(R_pin);,你用的是这个,连延时都没有,也没有消抖,电阻的读数(实际上读的是电压)是一直在跳的,关键是你不可能一下推到320。一定是从0开始加起来的,在加的过程中,根据你设定的逻辑,小车是不会停止的。等到了320。你中间大量累积的delay,不停地在前进、后退,而没有像你想象那样停止。让你误以为是控制出了问题,其实你的逻辑理论上并没有问题,而你在推动电阻过程中,积累的延时过长(我给你分析了,在val=1时,就有9秒多的延迟,要是推到10,又是7.6秒)。这样下去两个结果,一是你等不及就断电,二是328的小体格被搞死了。

    我给你出的主意你试了吗?先不要用val= analogRead(R_pin);直接给val=320看看控制结果(是不是可以实现前进、后退。。。停止)。

另外,电机驱动模块应该是L298N吧(你回帖中误为289.如果是L298N,你的速度控制参数再看看手册),板子有光耦隔离吗。我建议你先用LED代替电机,把代码调好再上电机,不然不定因素太多,没等调好,电机或者298又挂了。

回复 支持 反对

使用道具 举报

发表于 2014-7-4 18:41:28 来自手机 | 显示全部楼层
加个状态变数罢.
当左转或右转时, 状态=1,已后再在左或右时不动作.
拨回中间时,状=0. 就正常了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-4 19:21:20 | 显示全部楼层
uvvvvw 发表于 2014-7-4 18:41
加个状态变数罢.
当左转或右转时, 状态=1,已后再在左或右时不动作.
拨回中间时,状=0. 就正常了

要是你,你会往哪加?  麻烦给修改一下,谢谢!!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-4 23:47:31 | 显示全部楼层
49741933o 发表于 2014-7-4 19:21
要是你,你会往哪加?  麻烦给修改一下,谢谢!!

这是我修改后的代码,但还是出现问题了——停不下来。我是这样想的:比如往左推(val=320),此时x=0,虽然state变为0了, if(state == 1 && val< 341)这个语句不执行,但同时x=0一直没改变,所以还是一直前进,后退,如此循环。。试了很多次,但就是停不下来,不知道咋办了!
  1. int R_pin = 14;
  2. void setup()
  3. {
  4.   pinMode(8,OUTPUT);//定义输入、输出接口
  5.   pinMode(9,OUTPUT);
  6.   pinMode(10,OUTPUT);
  7.   pinMode(5,OUTPUT);
  8.   pinMode(6,OUTPUT);
  9.   pinMode(7,OUTPUT);
  10.   pinMode(14,INPUT);
  11.   Serial.begin(9600);
  12. }
  13. void qianjin()//前进
  14. {
  15.      
  16.      digitalWrite(10,300);
  17.      digitalWrite(5,300);
  18.      digitalWrite(7,HIGH);//使直流电机(左)逆时针转
  19.      digitalWrite(6,LOW);
  20.      digitalWrite(8,LOW);//使直流电机(右)顺时针转
  21.      digitalWrite(9,HIGH);
  22. }

  23. void tingzhi()//停止
  24. {
  25.      digitalWrite(6,HIGH);//使直流电机(左)制动
  26.      digitalWrite(7,HIGH);
  27.      digitalWrite(8,HIGH);//使直流电机(右)制动
  28.      digitalWrite(9,HIGH);
  29. }
  30. void houtui()
  31. {
  32.      digitalWrite(10,300);//输入模拟值进行设定速度
  33.      digitalWrite(5,300);
  34.      digitalWrite(6,HIGH);//使直流电机(左)逆时针转
  35.      digitalWrite(7,LOW);
  36.      digitalWrite(8,HIGH);//使直流电机(右)顺时针转
  37.      digitalWrite(9,LOW);
  38. }
  39. void loop()
  40. {   int  state =1, x,val;
  41.    float t;
  42.     val= analogRead(R_pin);
  43.     Serial.println(val);
  44.    if(state == 1 && val< 341)
  45.     {state = 0; x=0; t=0.0088*(341-val);}
  46.    if(state == 0 && 341 <= val <=682)
  47.      {state=1;x=1;}
  48.    if(state == 1 && val > 682)
  49.     {state = 0; x=2;  t=0.0088*(val-682);}
  50. switch(x)
  51.    {
  52.      case 0:
  53.      {
  54.        qianjin();delay(t*1000+1000);
  55.        houtui();delay(1000);
  56.        qianjin();delay(1000);
  57.        houtui();delay(t*1000+1000);
  58.      }break;
  59.      case 1:
  60.        tingzhi();break;
  61.      case 2:
  62.      {
  63.        houtui();delay(t*1000+1000);
  64.        qianjin();delay(1000);
  65.        houtui();delay(1000);
  66.        qianjin();delay(1000);
  67.       } break;
  68.    }
  69. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2014-7-4 23:50:59 | 显示全部楼层
49741933o 发表于 2014-7-4 23:47
这是我修改后的代码,但还是出现问题了——停不下来。。我是这样想的:比如往左推(val=320),此时x=0, ...

int R_pin = 14; //定义电位器的引脚
int S=0; ////////////////////////////////////////////////////////////////////////////
void setup()
{
  pinMode(8,OUTPUT);//定义输入、输出接口
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(14,INPUT);
  Serial.begin(9600);
}
void qianjin()//前进,
{
     
     digitalWrite(10,300);
     digitalWrite(5,255);
     digitalWrite(7,HIGH);//使直流电机(左)逆时针转
     digitalWrite(6,LOW);
     digitalWrite(8,LOW);//使直流电机(右)顺时针转
     digitalWrite(9,HIGH);
}

void tingzhi()//停止
{
     digitalWrite(6,HIGH);//使直流电机(左)制动
     digitalWrite(7,HIGH);
     digitalWrite(8,HIGH);//使直流电机(右)制动
     digitalWrite(9,HIGH);
}
void houtui()
{
     digitalWrite(10,255);
     digitalWrite(5,255);
     digitalWrite(6,HIGH);//使直流电机(左)逆时针转
     digitalWrite(7,LOW);
     digitalWrite(8,HIGH);//使直流电机(右)顺时针转
     digitalWrite(9,LOW);
}
void loop()
{   int x,val;
   float t;
    val= analogRead(R_pin);
    Serial.println(val);
   if(val< 341)
    { x=0; t=0.0088*(341-val);}
   else if(341 <= val <=682)
     x=1;
   if(val > 682)
    { x=2;  t=0.0088*(val-682);}
switch(x)
   {
     case 0:
     {
      if (S==0) ///////////////////////////////////////////////
        {      ///////////////////////////////////////////////
         qianjin();delay(t*1000+1000);
         houtui();delay(1000);
         qianjin();delay(1000);
         houtui();delay(t*1000+1000);
         S=1;  //////////////////////////////////////////////
        }      //////////////////////////////////////////////
     }break;
     case 1:
       tingzhi();break;
       S=0;    //////////////////////////////////////////////
     case 2:
     {
      if (S==0) ///////////////////////////////////////////////
        {      ///////////////////////////////////////////////      
         houtui();delay(t*1000+1000);
         qianjin();delay(1000);
         houtui();delay(1000);
         qianjin();delay(1000);
         S=1;  //////////////////////////////////////////////
        }      //////////////////////////////////////////////         
      } break;
   }
}


试试
回复 支持 反对

使用道具 举报

发表于 2014-7-4 23:59:49 | 显示全部楼层
49741933o 发表于 2014-7-4 19:21
要是你,你会往哪加?  麻烦给修改一下,谢谢!!

回家搭了一个电路,把你的第二个程序跑了一遍(第一个程序的5000ms延时实在不可行),现在说说情况:
我用三个LED代表你的三个动作定义:前进、后退、停止。
没有用电位器模拟输入,在程序中直接分别定义:320,500,800,代表电位器的三个区间。
运行结果和你的预设是一致的。
val=320时,进、退、进、退、停。   这个停是我后来加的,我看你希望有此动作,但是在第二个程序中漏了。
val=500时,停止
val=800时,退,进,退,进,停。 这个“停”同上。

问题是:以val=320为例。因为tingzhi()后没有延时,所以红色led只闪了一下,又回到进、退、进、退的动作循环。
           这个短暂的tingzhi()就是一个脉冲,让你的电机实际上停不下来。这就是你在实际控制中感觉不到“停“的原因。

解决办法:最简单的是我帮你加了一个按钮。这个按钮包络了整个动作判断。在你传递参数后,按下按钮。你需要
的控制动作就出现了,而且最后一个tingzhi()会一直保存下去(你的小车会一直停着),直到下一次按下按钮。

这个时候,你就可以恢复你的电位器作为模拟输入了,在电位器推到某个位置时,按下按钮,控制动作。
把电位器赋值和小车控制分解成两个动作,简单,明晰。


整个程序我已经在IDE1.05下测试过。你把LED改成小车的调速和方向控制即可。我还是建议你考虑BOXZ库,能省很多事。
希望能够帮助你。
  1. //int R_pin = 14; //定义电位器的引脚
  2. void setup()
  3. {
  4.   pinMode(6,OUTPUT);//PIN6黄色,代表前进//串接220Ω电阻限流,下同
  5.   pinMode(7,OUTPUT);//PIN7绿色,代表后退
  6.   pinMode(8,OUTPUT);//PIN8红色,代表停止

  7.   pinMode(3,INPUT);//按钮输入, 开关接在Arduino D3和+5V之间; 10kΩ电阻接在Arduino D3和GND之间;
  8.   Serial.begin(9600);
  9. }

  10. void qianjin()//前进,
  11. {
  12.      
  13.      digitalWrite(6,HIGH);//YELLOW
  14.      digitalWrite(7,LOW);
  15.      digitalWrite(8,LOW);

  16. }

  17. void tingzhi()//停止
  18. {
  19.      digitalWrite(8,HIGH);//RED
  20.      digitalWrite(7,LOW);
  21.      digitalWrite(6,LOW);

  22. }
  23. void houtui()//后退
  24. {

  25.      digitalWrite(7,HIGH);//GREEN
  26.      digitalWrite(6,LOW);
  27.      digitalWrite(8,LOW);

  28. }
  29. void loop()
  30. {   int x,val;
  31.    float t;
  32.     //先把电位器输入注释掉,直接给val赋值。可以把需要赋值的语句保留,其余注释。
  33.    // val= analogRead(R_pin);
  34.     //val=320;// 0<val<341
  35.    //val=500;   //341<val<682
  36.    val=800; // val>682
  37.   
  38.    if(digitalRead(3)==HIGH)  //按钮按下
  39.   {
  40.     delay(10); //然后延时一段时间,消抖
  41.     //判断val,分别进入不同子程序,执行相应动作
  42.    
  43.    if(val< 341){
  44.      x=0; t=0.0088*(341-val);}
  45.    else if(341 <= val <=682)
  46.      x=1;
  47.    if(val > 682)
  48.     { x=2;  t=0.0088*(val-682);}
  49. switch(x)
  50.    {
  51.      case 0:
  52.      {
  53.         Serial.println("0");//在串口观察一下进入了何种动作,下同
  54.        qianjin();delay(t*1000+1000);
  55.        houtui();delay(1000);
  56.        qianjin();delay(1000);
  57.        houtui();delay(t*1000+1000);
  58.        tingzhi();//增加停止动作,在你的第一个程序中有,第二个程序没有。如不需要可以去除,下同。
  59.      }break;
  60.      case 1:
  61.       Serial.println("1");
  62.        tingzhi();break;
  63.      case 2:
  64.      {
  65.         Serial.println("2");
  66.        houtui();delay(t*1000+1000);
  67.        qianjin();delay(1000);
  68.        houtui();delay(1000);
  69.        qianjin();delay(1000);
  70.        tingzhi();;//add stop
  71.       } break;
  72.    }
  73. }
  74. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2014-7-5 00:08:40 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-5 09:40:54 | 显示全部楼层
沧海笑1122 发表于 2014-7-5 00:08

哇,十分感谢你为了我这个问题而亲自搭建的电路!!
今天估计没时间看了,明天要考试了,我得悠着点。。。以后肯定还有很多问题不知道,还得请教你,咱加个好友吧。。
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-19 18:00 , Processed in 0.051727 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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