2013-06-20 2 views
0

Я работаю над проектом Arduino, управляющим грузовиком DIY RC, который считывает выходные выводы RC-приемника и должен PWMs на пару контактов соответственно. Штыри подключаются к контроллеру двигателя, который принимает PWM.Выходы выходных контактов Arduino случайная активность

Именно здесь возникает проблема. Мой реверс работает отлично, но на штыре, который делает вперед, я получаю случайную активность. Я использую 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 просто случайно Микс, очень тусклый, должен сказать.

Я уже пытался заменить такие вещи, как byte с int, но это не повлияло. Остальная часть кода работает нормально.

Используя некоторый новый код, я получаю последовательный ответ от каждой «стадии», за исключением заключительных этапов, которые управляют выводами.

#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); 
} 
+0

Side комментарий: Это мой первый проект с использованием массива, так что может быть вне границ, или не правильно, я выяснить, как именно работает массив. –

+0

Первой мыслью является то, что у вас есть две записи RXCH, но они перехватывают три из них, так что то, что вызывает pinMode() со случайными данными, - это чья-то догадка (она ведет себя только с pin <70). –

ответ

0
  • Неиспользованный индекс:

Везде цикл в течение трех значений, в то время как вы используете только два элемента в массиве.Так что лучше изменить все свои размеры до 2, а не 3, или вы можете определить константу NB_INPUT в верхней части исходного кода, который вы можете легко изменить для большей гибкости:

#define NB_INPUT 2 
... 

for (int i = 0; i<NB_INPUT; ++i) { 
... 
  • RXOK в setup():

вашего комментарий о массивах оправдан, то первая ошибкой я вижу в вашем коде является то, что вы читаете из RXOK массива, в то время как вы не ставили какое-либо значения в нем. Если вы уверены, что RXSG получает только нули от pulseIn() на первом проходе цикла Read RX values, все может быть в порядке, но я сомневаюсь, что это так. например .:

for (int i=0; i<3; ++i) 
    RXOK[i] = 0; 

Таким образом, вы должны поместить значения в RXOK значений в setup().

  • постоянные индексы в цикле:

Тогда вы map() значения от 1000-> 2000 -255-> 255 для RXSG[0] и RXSG[1] внутри для цикла, что будет сделано для три итерации. Я не уверен, что вы там хотите, но если вы хотите сделать это для постоянных индексов, вам лучше сделать это за пределами цикла. Но, как вы проверяете ограничение на -255-> области 255 для каждого значения итерации цикла, я думаю, что вы можете сделать это на относительных величинах:

PWMSG[i] = map(RXSG[i], 1000, 2000, -255, 255); 

но кажется домен зависит по индексу, так что вы можете сделать пару определяет, в верхней части исходного кода:

#define THROTTLE_IDX 0 
#define STEERING_IDX 1 

и поставить 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) 
  • общий алгоритм

Я не уверен, что вам действительно нужен массив для вашего прецедента. Вы бы лучше держать несколько переменных вокруг и лучшее использование функций для вашего кода, чтобы быть читаемыми и менее bugprone:

#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); 
} 

Есть больше коды дублирования, но иногда лучше дублировать код, чем сделать код почти нечитаемый и трудно отлаживается, не предлагая никакой гибкости/модульности. А вот несколько других вещей, которые я нашел в вашем коде, которые должны быть исправлены:

  • Naming Convention: пытаются использовать хорошие имена для функций (две буквы переменных или голландскими переменных не является хорошей идеей , Я не английский, и я всегда избегаю использовать свои собственные языковые имена в коде даже для кода, который я не разделяю, вы никогда не знаете, кто будет читать ваш код через 2 дня, 2 месяца или 2 года).

  • globals: Старайтесь избегать использования глобальных переменных как можно больше.Объявите только константу в глобальной области: const int foo = 1; или препроцессор определяет #define foo 1, так что вы не тратите слишком много свободного места на вашем ардуине. Единственное исключение из этого правила, которое очень специфично для разработки 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(); 
} 

и изменить цикл() для:

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[]: содержащие указатели на развлечения ctions.

, а затем ваш алгоритм будет выглядеть как:

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); 
    } 
} 

но вы еще не знакомы с массивами (и я полагаю, указатели, а), я бы не рекомендовал идти дальше, что путь в настоящее время. Сначала сделайте это просто и заставьте его работать, а затем вы можете попытаться разложить его по идее, которую я раскрываю здесь. Но вы создаете встроенное программное обеспечение, где оперативная память редко встречается, а вычислительная мощность низкая, а ваше кодовое пространство дешево. Таким образом, это один из немногих случаев, когда вам лучше сделать более избыточный код, который останется в программном пространстве, тогда как вы хотите манипулировать как небольшими символами в ОЗУ. Вот почему я не показываю вам, как массивы объявляются/определены, и как обрабатывать указатели на функции, потому что я не думаю, что это решение (куда вы направлялись) - это правильный способ делать то, что вы хотите.

Всегда помните, проще, лучше!

НТН

+0

Прежде всего, большое спасибо, я многому научился от вашего ответа. Я полностью изменил свой код, но на последнем этапе, то есть значение ШИМ для двигателя, я не получаю никакой ценности. Я пробовал кое-что, сначала я добавил Serial.print каждую «сцену», чтобы узнать, какие этапы работают, а какие нет. Я обнаружил, что обработка дроссельной заслонки (/ рулевое управление) работала, как и считывание входных контактов. Но когда я разместил Сериал.напечатайте в move_back/forward/ect, я не получил ответа. Я размещаю свой новый код в главном вопросе, не могу опубликовать его здесь. –

Смежные вопросы