Arduino输出引脚输出随机活动

时间:2013-06-20 08:22:30

标签: c arduino remote-control

我正在开发一个控制DIY RC卡车的Arduino项目,该卡车读取RC接收器的输出引脚,因此应该PWMs两个引脚。引脚挂在一个带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);
}

1 个答案:

答案 0 :(得分:0)

  • 未使用的索引:

你到处都循环三个值,而你只在数组中使用两个项目。因此,您最好将所有尺寸更改为2而不是3,或者您可以在源代码顶部定义NB_INPUT常量,以便更轻松地更改:

#define NB_INPUT 2
...

for (int i = 0; i<NB_INPUT; ++i) {
...
    {li> RXOK setup()

你对数组的评论是合理的,我在你的代码中看到的第一个错误就是你从RXOK数组中读取,而你没有在其中添加任何值。如果您确定RXSGpulseIn()循环的第一次传递中Read RX values只得到for (int i=0; i<3; ++i) RXOK[i] = 0; 的零,那就可以了,但我对此表示怀疑。 e.g:

RXOK

因此,您应将setup()中的值放在map()

  • for循环中的常量索引:

然后,RXSG[0] for {@ 1}}中的RXSG[1]PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255); 的值为#define THROTTLE_IDX 0 #define STEERING_IDX 1 ,这将在三次迭代中完成。我不确定你想要什么,但如果你想为常量索引做这件事,你最好在循环的。但是,当您在迭代循环的每个值上检查-255-> 255域的约束时,我认为您可能希望对相对值执行此操作:

map()

但似乎域依赖于索引,因此您可能希望在源代码的顶部创建几个定义:

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); } 放入if语句中:

const int foo = 1;
  • 一般算法

我不确定你的用例确实需要一个数组。您最好保留一些变量并更好地使用函数,以使代码可读并减少bugprone:

#define foo 1

有更多的代码重复,但有时重复代码比使代码几乎不可读,并且难以调试而不提供任何灵活性/模块性更好。以下是我在代码中发现的其他一些应该纠正的事情:

  • 命名约定:尝试为你的函数使用好名字(两个字母变量,或荷兰变量不是一个好主意,我不是英国本土的,我总是避免使用我自己的基于语言的代码,即使代码我不共享,你也不知道谁会在2天,2个月或2年内阅读你的代码。

  • 全局:尽量避免使用全局变量。在全局范围内仅声明常量:Servo或预处理器定义setup(),这样您就不会在arduino上花费太多的RAM空间。该规则的唯一例外是arduino开发非常具体,它是您需要全局声明的对象(如代码中的loop()),因此您可以在handle_steering()函数中设置它们,以及在void handle_steering(int steering) { if (steering > NN) turn_left(steering); elif (steering < NN) turn_right(steering); else keep_straight(); } 函数中使用它们。

如果我根据你所写的内容进行推断,你可能想要添加void loop() { int throttle = read_throttle(); int steering = read_steering(); delay(5); handle_throttle(throttle); handle_steering(steering); } 函数,例如:

PIN[]

并将loop()更改为:

DOM_MIN[]

为了使动态和灵活处理许多功能成为一般情况,你可以保留一些数组:

  • DOM_MAX[]:包含引脚,
  • BOUND_MIN[]:包含最少的要素域(针对地图),
  • BOUND_MAX[]:包含最多功能的域(对于地图),
  • ACTION[]:包含最小边界(对于handle_steering条件),
  • 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); } } :包含最大边界(对于handle_steering条件),
  • {{1}}:包含指向函数的指针。

然后你的算法将看起来像

{{1}}

但是你仍然不熟悉数组(并且我也假设指针),我不建议暂时采用这种方式。首先要做到这一点,并让它工作,然后你可以尝试按照我在这里暴露的想法将其分解。但是你正在制作一个嵌入式软件,其中RAM很少且处理能力很低,而你的代码空间很便宜。因此,这是少数几个你最好想要制作更多冗余代码以保留在程序空间中的情况之一,而你想在RAM中操作尽可能少的符号。这就是为什么我没有告诉你如何声明/定义数组,以及如何处理函数指针,因为我不认为解决方案(你正在前进的地方)是正确的方法来做你想要的。

永远记住,越简单越好!

HTH