49741933o 发表于 2014-6-14 22:16:01

技术问题

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

int R_pin = 14;//定义模拟引脚1
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,300);
   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,300);//输入模拟值进行设定速度
   digitalWrite(5,300);
   digitalWrite(6,HIGH);//使直流电机(左)逆时针转
   digitalWrite(7,LOW);
   digitalWrite(8,HIGH);//使直流电机(右)顺时针转
   digitalWrite(9,LOW);
}
void loop()
{   int R,x,s,val=0,old_val=0;
    unsigned long startTime=0;
    float t;
    val= analogRead(R_pin);
    Serial.println(val);
   if(old_val == val)
{
   startTime = millis(); //用来计时
   if(val< 341){
    t=0.0088*(341-val);
    qianjin();
    delay(t*1000+1000);
    houtui();
    delay(1000);
    qianjin();
    delay(1000);
    houtui();
    delay(t*1000+1000);
    if(millis()-startTime<=5000)
    tingzhi();
    }
    if(341 <= val <= 682)
    tingzhi();
if(val>682){
    t=0.0088*(val-682);
    houtui();
    delay(t*1000+1000);
    qianjin();
    delay(1000);
    houtui();
    delay(1000);
    qianjin();
    delay(1000);
    tingzhi();
    }
}
old_val = val;
}
我想着就是:滑杆到某个位置时,只要一次那样的动作(前进,后退,前进,后退,停止),停止后,再手动归位(就是手动把滑杆推到中间的位置,也就是模拟值在341~682的地方),如果下次再推动滑杆的时候还能继续那样的动作。
然而上述程序的结果是:一直前进,后退.............
求解啊!!!!希望大神级人物能够给个思路,让我继续走下去...



hsr18299 发表于 2014-6-16 03:19:54

int R_pin = 14;//定义模拟引脚1??

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

弘毅 发表于 2014-6-16 06:56:29

你用了太多的delay,我想问题可能出在这里。

49741933o 发表于 2014-6-18 15:01:18

hsr18299 发表于 2014-6-16 03:19 static/image/common/back.gif
int R_pin = 14;//定义模拟引脚1??

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

模拟引脚A0~A5对应14~19

49741933o 发表于 2014-6-18 15:03:56

弘毅 发表于 2014-6-16 06:56 static/image/common/back.gif
你用了太多的delay,我想问题可能出在这里。

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

沧海笑1122 发表于 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的乐趣本身就在这里。希望能够帮到你。

49741933o 发表于 2014-7-3 22:33:09

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

首先谢谢你精彩的答复和给的链接
驱动模块用的是L289N
这是我稍微修改了一下的代码(虽然还是没有达到预期的效果,但是看起来整洁一些!)int R_pin = 14; //定义电位器的引脚
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:
   {
       qianjin();delay(t*1000+1000);
       houtui();delay(1000);
       qianjin();delay(1000);
       houtui();delay(t*1000+1000);
   }break;
   case 1:
       tingzhi();break;
   case 2:
   {
       houtui();delay(t*1000+1000);
       qianjin();delay(1000);
       houtui();delay(1000);
       qianjin();delay(1000);
      } break;
   }
}你说的对,我是用小车来反应现象的。最上面的程序可以实现前进和后退,就是停不下来。 抛开最上面的程序,不说那个了,说这个-------->反正我想实现的就是:如果我推到了一个位置,小车只会有一次相应的动作。比如推到320,小车会前进,后退,前进,后退,此时小车已到达初始位置,然后,它应该停止了,等待接受下一个信号,继续下一个动作,但是因为我没有去推滑杆(其实也不需要、不应该推),所以读取的信号还是和原来的一样,(问题就在这,所以小车一直前进,后退,不能停止。)我不知道怎样去控制它

沧海笑1122 发表于 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又挂了。

uvvvvw 发表于 2014-7-4 18:41:28

加个状态变数罢.
当左转或右转时, 状态=1,已后再在左或右时不动作.
拨回中间时,状=0. 就正常了

49741933o 发表于 2014-7-4 19:21:20

uvvvvw 发表于 2014-7-4 18:41 static/image/common/back.gif
加个状态变数罢.
当左转或右转时, 状态=1,已后再在左或右时不动作.
拨回中间时,状=0. 就正常了

要是你,你会往哪加?麻烦给修改一下,谢谢!!

49741933o 发表于 2014-7-4 23:47:31

49741933o 发表于 2014-7-4 19:21 static/image/common/back.gif
要是你,你会往哪加?麻烦给修改一下,谢谢!!

这是我修改后的代码,但还是出现问题了——停不下来。。我是这样想的:比如往左推(val=320),此时x=0,虽然state变为0了, if(state == 1 && val< 341)这个语句不执行,但同时x=0一直没改变,所以还是一直前进,后退,如此循环。。试了很多次,但就是停不下来,不知道咋办了!int R_pin = 14;
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,300);
   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,300);//输入模拟值进行设定速度
   digitalWrite(5,300);
   digitalWrite(6,HIGH);//使直流电机(左)逆时针转
   digitalWrite(7,LOW);
   digitalWrite(8,HIGH);//使直流电机(右)顺时针转
   digitalWrite(9,LOW);
}
void loop()
{   intstate =1, x,val;
   float t;
    val= analogRead(R_pin);
    Serial.println(val);
   if(state == 1 && val< 341)
    {state = 0; x=0; t=0.0088*(341-val);}
   if(state == 0 && 341 <= val <=682)
   {state=1;x=1;}
   if(state == 1 && val > 682)
    {state = 0; x=2;t=0.0088*(val-682);}
switch(x)
   {
   case 0:
   {
       qianjin();delay(t*1000+1000);
       houtui();delay(1000);
       qianjin();delay(1000);
       houtui();delay(t*1000+1000);
   }break;
   case 1:
       tingzhi();break;
   case 2:
   {
       houtui();delay(t*1000+1000);
       qianjin();delay(1000);
       houtui();delay(1000);
       qianjin();delay(1000);
      } break;
   }
}

uvvvvw 发表于 2014-7-4 23:50:59

49741933o 发表于 2014-7-4 23:47 static/image/common/back.gif
这是我修改后的代码,但还是出现问题了——停不下来。。我是这样想的:比如往左推(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;
   }
}


试试:handshake

沧海笑1122 发表于 2014-7-4 23:59:49

49741933o 发表于 2014-7-4 19:21 static/image/common/back.gif
要是你,你会往哪加?麻烦给修改一下,谢谢!!

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

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

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

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


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

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

void qianjin()//前进,
{
   
   digitalWrite(6,HIGH);//YELLOW
   digitalWrite(7,LOW);
   digitalWrite(8,LOW);

}

void tingzhi()//停止
{
   digitalWrite(8,HIGH);//RED
   digitalWrite(7,LOW);
   digitalWrite(6,LOW);

}
void houtui()//后退
{

   digitalWrite(7,HIGH);//GREEN
   digitalWrite(6,LOW);
   digitalWrite(8,LOW);

}
void loop()
{   int x,val;
   float t;
    //先把电位器输入注释掉,直接给val赋值。可以把需要赋值的语句保留,其余注释。
   // val= analogRead(R_pin);
    //val=320;// 0<val<341
   //val=500;   //341<val<682
   val=800; // val>682

   if(digitalRead(3)==HIGH)//按钮按下
{
    delay(10); //然后延时一段时间,消抖
    //判断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:
   {
      Serial.println("0");//在串口观察一下进入了何种动作,下同
       qianjin();delay(t*1000+1000);
       houtui();delay(1000);
       qianjin();delay(1000);
       houtui();delay(t*1000+1000);
       tingzhi();//增加停止动作,在你的第一个程序中有,第二个程序没有。如不需要可以去除,下同。
   }break;
   case 1:
      Serial.println("1");
       tingzhi();break;
   case 2:
   {
      Serial.println("2");
       houtui();delay(t*1000+1000);
       qianjin();delay(1000);
       houtui();delay(1000);
       qianjin();delay(1000);
       tingzhi();;//add stop
      } break;
   }
}
}

沧海笑1122 发表于 2014-7-5 00:08:40

49741933o 发表于 2014-7-5 09:40:54

沧海笑1122 发表于 2014-7-5 00:08 static/image/common/back.gif


哇,十分感谢你为了我这个问题而亲自搭建的电路!!:):handshake
今天估计没时间看了,明天要考试了,我得悠着点。。。以后肯定还有很多问题不知道,还得请教你,咱加个好友吧。。
页: [1] 2
查看完整版本: 技术问题