Arduino Uno时间问题

时间:2017-01-31 22:29:30

标签: bluetooth arduino-uno benchmarking

我一直在努力制造机器人"排水沟清洁剂"为学校项目。我决定使用Arduino Uno来控制电机。它只是一个前进/后退驱动器,因此只有一个电机控制机器人的运动。还有另一台电机控制着刀片" (因为没有一个更好的词)从前面出来把污垢扔到阴沟里。

我正在使用HC-05蓝牙模块接受来自智能手机和L9110 H桥的输入,以分别控制电机。有五个功能:前进运动,后退运动,刀片开启,停止和"自主"。自主涉及刀片开启,机器人向前移动20秒,向后移动10秒,重复直到调用停止功能。

问题在于,当我调用自治功能时,HC-06似乎停止接收数据,调试println("auto fwd")阻止串行监视器。 " auto rev"代码调试代码甚至没有达到。 stop函数无法运行,因为它看起来没有数据被接收,因此创建了一个无限循环。

我在这里尝试过使用BlinkWithoutDelay,老实说我不知道​​为什么这不起作用。

#include <SoftwareSerial.h> //Include the "SoftwareSerial" software in the program

#define M1A 5 //tells the software compiler to assign these varibales to these outputs on the Arduino board
#define M1B 9 //M1 motors are controlling the motion
#define M2A 4 //M2 motors control the blades
#define M2B 10

SoftwareSerial BT(3, 2); //Tells the program to assign pins 2 and 3 on the Arduino to send and receive data

void fw(); //Denoting Functions to be used
void bw();
void Stop();
void autonomous();
void bladesOn();

boolean autonom = false; //Variables
boolean blades = false;
unsigned long currentMillis = millis();
unsigned long previousMillis = 0;
const long fwdTime = 20000;
const long revTime = fwdTime/2;

void setup() {
  // put your setup code here, to run once:
  TCCR1B = (TCCR1B & 0b11111000) | 0x04;
  BT.begin(9600);
  Serial.begin(9600);
  pinMode(M1A, OUTPUT);
  pinMode(M1B, OUTPUT);
  pinMode(M2A, OUTPUT);
  pinMode(M2B, OUTPUT);
}

void loop() {
  if (BT.available()) {
    char input = BT.read(); //Read the incoming BlueTooth signal
    Serial.println(input); //Print the BT signal to the memory
    switch (input) { //IF input is 1, do this, IF input is 2, do that
      case '1':
        fw();
        break;
      case '2':
        bw();
        break;
      case '3':
        autonomous();
        blades = 1;
        autonom = true;
        break;
      case '4':
        bladesOn();
        blades = true;
        break;
      case '0':
        Stop();
        autonom = false;
        blades = false;
        break;
    }
  }
}

void bw() {
  digitalWrite(M1A, 0); //Give an output to the M1A pin
  analogWrite(M1B, 255); //Give an output to the M1B pin
  digitalWrite(M2A, 0);
  analogWrite(M2B, 255);
  Serial.println("Backwards");
}

void fw() {
  digitalWrite(M1A, 1);
  analogWrite(M1B, (255 - 255));
  digitalWrite(M2A, 1);
  analogWrite(M2B, (255 - 255));
  Serial.println("Forwards");
}

void Stop() {
  digitalWrite(M1A, 0);
  analogWrite(M1B, 0);
  digitalWrite(M2A, 0);
  analogWrite(M2B, 0);
  Serial.println("Stop");
}

void autonomous() {
  while (autonom == true) {
    if (currentMillis - previousMillis <= fwdTime) {
      //When time between last repeat of forwards/reverse and now is less than Time1, go forward
        digitalWrite(M1A, 1);
        analogWrite(M1B, (255 - 255));
        digitalWrite(M2A, 1);
        analogWrite(M2B, (255 - 255));
        Serial.println("auto fwd");
    }
    if (currentMillis - previousMillis <= revTime) {
      //When time between last repeat of forwards/reverse and now is less than Time2, go reverse
        digitalWrite(M1A, 0);
        analogWrite(M1B, 255);
        digitalWrite(M2A, 0);
        analogWrite(M2B, 255);
        Serial.println("auto rev");
    }
    if (currentMillis - previousMillis == revTime) { //Set previoustime to currenttime
      previousMillis = currentMillis;
  Serial.println("Autonom");
    }
  }
}

void bladesOn() {
    blades = true;
    digitalWrite(M2A, 1);
    analogWrite(M2B, 0);
    Serial.println("Blades");
}

我知道这可能对某些人来说太长了,但任何帮助都会非常感激。如果您需要更多信息,请不要犹豫。

PS。我正在使用&#34; Arduino BT操纵杆&#34;作为控制机器人的Android应用程序,如果有帮助的话。

谢谢,

克雷格。

3 个答案:

答案 0 :(得分:1)

autonomous()函数的逻辑错误。如DigitalNinja所述,arduino将在函数的第二次调用时卡在while循环上,因为autonom变量仅在此循环之外更新。

即使不是这种情况,currentMillis变量也不会在代码中的任何位置更新,因此测试currentMillis - previousMillis <= fwdTime将始终为真。

(Ps:很抱歉这样回答,我没有足够的声誉发表评论。)

答案 1 :(得分:0)

<强>问题:

  1. autonom()包含一个循环while(autonom == true) { ... },它永远不会终止,因为autonom永远不会在循环中设置为false,因此控件永远不会返回给调用者{ {1}}并且您再也不会听蓝牙命令。

  2. 您不会在任何地方更新void loop() { ... },因此您的机器人会因为向前 / 向后而停滞不前>永远。

  3. currentMillis是不合适的,因为一般来说currentMillis - previousMillis == revTime可能会大于 currentMillis,而不会相等。您应该改为previousMillis + revTime

  4. 虽然不是很复杂,但你的代码很长,而且我没有太多时间花在答案上,所以我会尝试通过给你模拟来让你朝着正确的方向前进/ em> 伪代码中的正确设计。我相信你能够根据自己的需要使用它。

    请注意,在此示例中,currentMillis - previousMillis >= revTime设置了自主移动,'1'向后设置自主移动,并且不再使用'2'。这是因为我认为应该丰富您的通信协议,以便允许命令参数例如:移动持续时间。请注意,您可以通过设置'3'轻松复制'1''2'之前的行为。

    time = 0

    总结一下,一个小建议。在你的位置,我会更改像enum { STAY_STILL, MOVE_FORWARD, MOVE_BACKWARD, } #define FORWARD_TIME 20000 #define BACKWARD_TIME (FORWARD_TIME / 2) byte state = STAY_STILL; unsigned long startMillis; void loop() { currentMillis = millis(); if (BT.available()) { char input = BT.read(); switch (input) { case '1': state = MOVE_FORWARD; time = FORWARD_TIME; startMillis = currentMillis; break; case '2': state = MOVE_BACKWARD; time = BACKWARD_TIME; startMillis = currentMillis; break; // case '3' is pointless: instead of duplicating functionality // you should modify your communication protocol so to allow // setting both a direction and the amount of time you want // the robot to move in such direction. A value of 0 could // stand for 'forever', all other values could be interpreted // as seconds. case '4': start_blades(); break; case '5': stop_blades(); break; case '0': state = STAY_STILL; break; } } if (state == MOVE_FORWARD || state == MOVE_BACKWARD) { move_robot(); } else if (state == STAY_STILL) { stop_blades(); stop_robot(); } delay(10); } void start_blades() { digitalWrite(M2A, 1); analogWrite(M2B, 0); Serial.println("start blades"); } void stop_blades() { digitalWrite(M2A, 0); analogWrite(M2B, 0); Serial.println("stop blades"); } void stop_robot() { digitalWrite(M1A, 0); analogWrite(M1B, 0); Serial.println("stop wheels"); } void move_robot() { // time == 0 : move forever in one direction // else : move up until deadline if (time == 0 || currentMillis - startMillis <= time) { if (state == MOVE_FORWARD) { fw(); } else if (state == MOVE_BACKWARD) { bw(); } } else { // this will turn off both blades and // wheels at the next iteration of the loop() state = STAY_STILL; } } ... // your fw() and bw() functions ... 这样的函数,只在必要时执行操作,而不是无意识地设置值和打印内容。除了减少长函数的开销外,它还可以避免通过 serial 打印大量消息,从而使调试更容易。这可以通过使用更多信息丰富机器人的状态来实现,但它超出了问题和答案的范围。

答案 2 :(得分:0)

嗯,最后,我有一个变量,显然是自己打开和关闭。因此,当项目的截止日期进入时,我完全取出了自动功能。谢谢你所有的帮助,我可能没有得到它,但我学到了一点。