我一直在努力制造机器人"排水沟清洁剂"为学校项目。我决定使用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应用程序,如果有帮助的话。
谢谢,
克雷格。
答案 0 :(得分:1)
autonomous()
函数的逻辑错误。如DigitalNinja所述,arduino将在函数的第二次调用时卡在while循环上,因为autonom变量仅在此循环之外更新。
即使不是这种情况,currentMillis
变量也不会在代码中的任何位置更新,因此测试currentMillis - previousMillis <= fwdTime
将始终为真。
(Ps:很抱歉这样回答,我没有足够的声誉发表评论。)
答案 1 :(得分:0)
<强>问题:强>
autonom()
包含一个循环while(autonom == true) { ... }
,它永远不会终止,因为autonom
永远不会在循环中设置为false
,因此控件永远不会返回给调用者{ {1}}并且您再也不会听蓝牙命令。
您不会在任何地方更新void loop() { ... }
,因此您的机器人会因为向前 / 向后而停滞不前>永远。
写currentMillis
是不合适的,因为一般来说currentMillis - previousMillis == revTime
可能会大于 currentMillis
,而不会相等。您应该改为previousMillis + revTime
。
虽然不是很复杂,但你的代码很长,而且我没有太多时间花在答案上,所以我会尝试通过给你模拟来让你朝着正确的方向前进/ 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)
嗯,最后,我有一个变量,显然是自己打开和关闭。因此,当项目的截止日期进入时,我完全取出了自动功能。谢谢你所有的帮助,我可能没有得到它,但我学到了一点。