>我正在做一个Arduino项目,控制一辆DIY RC卡车,该卡车读取RC接收器的输出引脚,并相应地PWM几个引脚。引脚连接到采用PWM的电机控制器上。
这就是问题所在。我的反向工作正常,但在向前的引脚上,我只得到随机活动。我使用的是Arduino Mega 2560。
这是代码。问题已发布在其下方:
#include <Servo.h>
//Create variables for three channels
int RXCH[3];
volatile int RXSG[3];
int RXOK[3];
int PWMSG[3];
byte vooruit;
byte achteruit;
Servo stuur;
int mv = 13;
int ma = 10;
void setup() {
Serial.begin(115200);
stuur.attach(8);
//Assign PPM input pins. The receiver output pins are conected as below to non-PWM Digital connectors:
RXCH[0] = 6; //Throttle
RXCH[1] = 7; //Steering
//RXCH[2] = 5; //Nothing yet
//RXCH[3] = 2; //Nothing yet
//RXCH[4] = 7; //Nothing yet
//RXCH[5] = 8; //Nothing yet
for (int i = 0; i < 3; i++){
pinMode(RXCH[i], INPUT);
}
//TCCR1B = TCCR1B & 0b11111000 | 0x01;
//TCCR2B = TCCR2B & 0b11111000 | 0x01;
}
void loop() {
// Read RX values
for (int i = 0; i < 3; i++){ //For each of the 6 channels:
RXSG[i] = pulseIn(RXCH[i], HIGH, 20000); //Read the receiver signal
if (RXSG[i] == 0) { //Error catching
RXSG[i] = RXOK[i];
} else {
RXOK[i] = RXSG[i];
}
//Substitute the high values to a value between -255 and 255
PWMSG[0] = map(RXSG[0], 1000, 2000, -255, 255);
//Servo values, calibrated according to my steering servo.
PWMSG[1] = map(RXSG[1], 1000, 2000, 24, 169);
//Make sure that the value stays within the desired boundaries.
constrain (PWMSG[i], -255, 255);
//For debugginf purposes
Serial.print(" || Ch: ");
Serial.print(i);
Serial.print(" / PWMSG: ");
Serial.print(PWMSG[i]);
}
delay (5);
// Car goes forwards
if (PWMSG[0] > 40)
{
MV();
}
// Car goes backwards
if (PWMSG[0] < -40)
{
MA();
}
// Car stops
else
{
stopmotor();
}
stuur.write(PWMSG[1]);
Serial.println();
}
void MV()
{
vooruit = PWMSG[0];
analogWrite (mv, vooruit);
digitalWrite (ma, LOW);
Serial.print(" vooruit: ");
Serial.print(vooruit);
}
void MA()
{
achteruit = abs(PWMSG[0]);
analogWrite (ma, achteruit);
digitalWrite (mv, LOW);
Serial.print(" achteruit: ");
Serial.print(achteruit);
}
void stopmotor()
{
digitalWrite (ma, LOW);
digitalWrite (mv, LOW);
}
我真的不知道代码是否被认为是漂亮的,或者我是否犯了一些基本错误。
这是我尝试以正确的方式做的第一个项目之一,发表评论等,欢迎所有评论良好的批评。
代码应该做什么:
- 将发射器上的摇杆向前移动
- ,汽车向前移动,速度应根据摇杆的位置而定。 将发射器上的摇杆向后移动
- ,汽车向后移动,速度应根据摇杆的位置而定。 向
- 左或向右移动发射器上的摇杆,车内的伺服器应根据Arduino计算的值做出反应。您可能想知道为什么我不将伺服器直接放在变送器上。嗯,那是因为我对这个项目有更多的未来想法,现在我可以更轻松地校准它。
问题:
- 当我向前移动发射器上的摇杆并且串行监视器打开时,我在串行监视器上获得了正确的值,但是引脚 13 上的 LED 只是随机闪烁,我必须说非常暗。
我已经尝试用 int 替换 byte 之类的东西,但没有效果。代码的其余部分工作正常。
使用一些新代码,我从每个"阶段"获得串行响应,除了控制引脚的最后阶段。
#include <Servo.h>
//Create variables for channels
Servo wheel;
int MFORWARD_PIN = 13;
#define MBACKWARD_PIN 10
#define WHEEL_PIN 8
#define THROTTLE_PIN 6
#define STEERING_PIN 7
void setup() {
Serial.begin(115200);
wheel.attach(WHEEL_PIN);
pinMode(THROTTLE_PIN, INPUT);
pinMode(STEERING_PIN, INPUT);
pinMode(MFORWARD_PIN, OUTPUT);
pinMode(MBACKWARD_PIN, OUTPUT);
//TCCR1B = TCCR1B & 0b11111000 | 0x01;
//TCCR2B = TCCR2B & 0b11111000 | 0x01;
}
void loop() {
int throttle = read_throttle();
int steering = read_steering();
delay (5);
throttle_handle(throttle);
steering_handle(steering);
}
// Read RX values
int read_throttle(){
int throttle = pulseIn(THROTTLE_PIN, HIGH, 20000);
throttle = map(throttle, 1000, 2000, -255, 255); //Substitute the high values to a value between -255 and 255.
constrain (throttle, -255, 255); //Make sure that the value stays within the desired boundaries.
//Serial.println(throttle);
}
int read_steering() {
int steering = pulseIn(STEERING_PIN, HIGH, 20000);
steering = map(steering, 1000, 2000, 24, 169); //Servo values, calibrated according to my steering servo.
constrain (steering, 24, 169); //Make sure that the value stays within the disired boundaries.
//Serial.println("steering");
}
void move_forward(int val) {
analogWrite (MFORWARD_PIN, val);
digitalWrite (MBACKWARD_PIN, LOW);
Serial.print(" vooruit: ");
Serial.print(val);
}
void move_backward(int val)
{
val = abs(val);
analogWrite (MBACKWARD_PIN, val);
digitalWrite (MFORWARD_PIN, LOW);
Serial.print(" achteruit: ");
Serial.print(val);
}
void move_stop()
{
digitalWrite (MFORWARD_PIN, LOW);
digitalWrite (MBACKWARD_PIN, LOW);
}
void throttle_handle(int throttle) {
//Serial.print("throttle");
if (throttle > 40) {
move_forward(throttle);
}
if (throttle < -40) {
move_backward(throttle);
}
else {
move_stop();
}
}
void steering_handle(int steering) {
wheel.write(steering);
// Serial.println("steering:");
// Serial.print(steering);
}
- 未使用的索引:
到处循环访问三个值,而数组中只使用两个项目。因此,您最好将所有大小更改为 2 而不是 3,或者您可以在源代码顶部定义一个NB_INPUT
常量,您可以轻松更改以获得更大的灵活性:
#define NB_INPUT 2
...
for (int i = 0; i<NB_INPUT; ++i) {
...
-
RXOK
setup()
:
对数组的评论是合理的,我在你的代码中看到的第一个错误是你从RXOK
数组中读取,而你没有在其中输入任何值。如果您确定RXSG
在Read RX values
循环的第一遍中只从pulseIn()
得到零,那还可以,但我怀疑是这样。例如:
for (int i=0; i<3; ++i)
RXOK[i] = 0;
所以你应该把值放在RXOK
值setup()
.
- for 循环中的常量索引:
然后,您将值从 1000->2000 map()
到 -255->255 用于 RXSG[0]
,并在 for 循环中RXSG[1]
,这将针对三次迭代完成。我不确定你想要什么,但如果你想为常量索引做这件事,你最好在循环之外做。但是,当您检查迭代循环的每个值的 -255->255 域上的约束时,我认为您可能希望对相对值执行此操作:
PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255);
但似乎域依赖于索引,因此您可能希望在源代码的顶部进行一些定义:
#define THROTTLE_IDX 0
#define STEERING_IDX 1
并将您的map()
放在 if 语句中:
if (i == THROTTLE_IDX)
PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255);
elif (i == STEERING_IDX)
PWMSG[i] = map(RXSG[i], 1000, 2000, 24, 169);
# add a else statement if you need to do a map for the other values of the array
constrain(PWMSG[i], -255, 255)
- 通用算法
我不确定您的用例是否真的需要一个数组。你最好保留一些变量,并更好地使用函数,使你的代码可读且更少错误:
#define THROTTLE_PIN 6
#define STEERING_PIN 7
#define WHEEL_PIN 8
#define MFORWARD_PIN 13
#define MBACKWARD_PIN 10
Servo wheel;
// sets up the arduino
void setup() {
Serial.begin(115200);
wheel.attach(WHEEL_PIN);
pinMode(THROTTLE_PIN, INPUT);
pinMode(STEERING_PIN, INPUT);
}
// input data handling
int read_throttle() {
int throttle = pulseIn(THROTTLE_PIN, HIGH, 20000);
return map(throttle, 1000, 2000, -255, 255);
}
int read_steering() {
int steering = pulseIn(STEERING_PIN, HIGH, 20000);
return map(throttle, 1000, 2000, 24, 169);
}
// output actions handling
void move_forward(int val) {
analogWrite(MFORWARD_PIN, val);
digitalWrite(MBACKWARD_PIN, LOW);
// Serial.print...
}
void move_backward(int val) {
analogWrite(MFORWARD_PIN, val);
digitalWrite(MBACKWARD_PIN, LOW);
// Serial.print...
}
void stop_motor() {
digitalWrite(MFORWARD_PIN, LOW);
digitalWrite(MBACKWARD_PIN, LOW);
}
void handle_throttle(int throttle) {
if (throttle > 40)
move_forward(throttle);
elif (throttle < -40)
move_backward(throttle);
else
stop_motor();
}
// general algorithm
void loop() {
int throttle = read_throttle();
delay(5);
handle_throttle(throttle);
}
代码重复更多,但有时复制代码比使代码几乎不可读且难以调试,同时不提供任何灵活性/模块化更好。以下是我在您的代码中发现的其他一些应该更正的内容:
命名约定:尝试为您的函数使用好名称(两个字母的变量或荷兰变量不是一个好主意,我不是英语母语,我总是避免在代码中使用我自己的基于语言的名称,即使对于我不共享的代码,你永远不知道谁会在 2 天、2 个月内阅读你的代码, 或 2 年(。
globals:尽量避免使用全局变量。在全局范围内只声明常量:
const int foo = 1;
或预处理器定义#define foo 1
,这样你就不会在arduino上花费太多的少量RAM空间。该规则的唯一例外(非常特定于 arduino 开发(是需要全局声明的对象(如代码中的Servo
(,以便您可以在setup()
函数中设置它们,并在loop()
函数中使用它们。
如果我推断你写的内容,你可能想添加一个handle_steering()
函数,例如:
void handle_steering(int steering) {
if (steering > NN)
turn_left(steering);
elif (steering < NN)
turn_right(steering);
else
keep_straight();
}
并将 loop(( 更改为 :
void loop() {
int throttle = read_throttle();
int steering = read_steering();
delay(5);
handle_throttle(throttle);
handle_steering(steering);
}
为了使它成为动态和灵活处理许多特征的更一般的情况,您可以保留一些数组:
-
PIN[]
: 包含引脚, -
DOM_MIN[]
:包含要素域的最小值(对于地图(, -
DOM_MAX[]
:包含要素的最大域(对于地图(, -
BOUND_MIN[]
:包含最小边界(对于handle_steering条件(, -
BOUND_MAX[]
:包含最大边界(对于handle_steering条件(, -
ACTION[]
:包含指向函数的指针。
然后你的算法将如下所示:
int read_input(int i) {
int value = pulseIn(PIN[i], HIGH, 20000);
return map(value, 1000, 2000, DOM_MIN[i], DOM_MAX[i]);
}
int handle_action(int i, int value) {
if (value > BOUND_MIN[i])
*(ACTION[i])(value);
elif (value < BOUND_MAX[i])
*(ACTION[i])(value);
else
*(ACTION[i])(-1);
}
void loop() {
for (int i=0; i<NB_INPUTS; ++i) {
int value = read_input(i);
delay(5);
handle_action(i, value);
}
}
但是由于您仍然对数组不满意(我也假设指针(,因此我暂时不建议以这种方式走得更远。首先做简单并使其工作,然后您可以尝试按照我在这里公开的想法对其进行分解。但是您正在制作嵌入式软件,其中RAM很少,处理能力低,而您的代码空间很便宜。因此,这是少数几种情况之一,您最好希望制作一个更冗余的代码,该代码将保留在程序空间中,而您希望在RAM中操作小符号。这就是为什么我不向您展示如何声明/定义数组以及如何处理函数指针,因为我认为解决方案(您要去的地方(不是执行所需操作的正确方法。
永远记住,越简单越好!
呵呵