Паук на ИК не реагирует на вторую команду

Вопросы программирования в системе Ардуино
ddt
Сообщения: 1
Зарегистрирован: 15 дек 2019, 18:32

Паук на ИК не реагирует на вторую команду

Сообщение ddt » 15 дек 2019, 18:50

Добрый день.

решил повторить проект ringo.

собрал прототип. код почти не изменил. робот реагирует только на первую команду и повторяет ее постоянно уже не реагируя на последующие.

собрал на nano, датчик висит на 2м пине (у автора аналоговый вход - у меня цифровой и датчик немного другой). команды принимает нормально если без двигателей смотреть на порту.

помогите понять что не так.

пробовал с прерываниями (поэтому на 2й линии оставил датчик - не как у автора), робот уже слушается команд но с переменным успехом.

хотелось бы понять что не так с оригинальным кодом.

Код: Выделить всё

#include <IRremote.h>

// EN: We use special library to receive and decode commands from IR remote.
// RU: Подключаем специальную библиотеку, предоставляющую функции
//     приёма и передачи ИК-команд. Сайт проекта:
//     https://github.com/shirriff/Arduino-IRremote


#include "ir_command_codes.h"

#include <Servo.h>

// EN: Analog pin where IR detector is pluged in.
// RU: Аналоговый вход контроллера, к которму подключен ИК-приёмник.
const int IR_PIN = 2;

// EN: Servo pins.
// RU: Цифровые выводы контролера, к которым подключены серводвигатели.
const int LEFT_SERVO_PIN = 3;
const int CENTRAL_SERVO_PIN = 4;
const int RIGHT_SERVO_PIN = 7;

// EN: Servo "zero" angle positions.
// RU: Центральное ("нулевое") положение серводвигателей в градусах.
const long LEFT_SERVO_ZERO_VALUE = 90;
const long RIGHT_SERVO_ZERO_VALUE = 90;
const long CENTRAL_SERVO_ZERO_VALUE = 90;

// EN: Amplitude of left and right servos.
// RU: Амплитула левого и правого серводвигателей.
const long SIDE_SERVOS_FULL_AMPLITUDE = 30;
// EN: Half amplitude of left and right servos. Is used when robot is turning
//     left or right while moving forward or backward.
// RU: Уменьшенная амплитула левого и правого серводвигателей. Используется
//     при поворотах совмещённых с движением вперёд или назад.
const long SIDE_SERVOS_HALF_AMPLITUDE = 15;
// EN: Amplitude of central servo.
// RU: Амплитула центрального серводвигателя.
const long CENTRAL_SERVO_AMPLITUDE = 20;

// EN: Periods for different speeds.
// RU: Периоды колебаний для различных скоростей.
const long STEP_PERIOD_VERY_SLOW = 2000;
const long STEP_PERIOD_SLOW = 1500;
const long STEP_PERIOD_FAST = 1000;
const long STEP_PERIOD_VERY_FAST = 500;

long lastMillis;
long globalPhase;
float angleShiftLeftServo;
float angleShiftRightServo;
float angleShiftCentralServo;
long stepPeriod;
long amplitudeLeftServo;
long amplitudeRightServo;
long irkod;
boolean isAttached;
boolean isStopped;

// EN: IRrecv class performs the decoding.
// RU: Создаём объект ИК-приёмник. Этот объект принимает и декодирует ИК-сигналы от пульта.
IRrecv irrecv(IR_PIN);

Servo LeftServo;
Servo RightServo;
Servo CentralServo;

void attachServos() {
  if (!isAttached) {
    LeftServo.attach(LEFT_SERVO_PIN);
    RightServo.attach(RIGHT_SERVO_PIN);
    CentralServo.attach(CENTRAL_SERVO_PIN);
    isAttached = true;
  }
}

// EN: In some positions servos can make noise and vibrate.
//     To avoid this noise and vibration detach servos when robot is stopped.
// RU: В некоторых положениях серводвигатели могут вибрировать и шуметь.
//     Чтобы это избежать во время остановок робота, сервы надо отключать.
void detachServos() {
  if (isAttached) {
    LeftServo.detach();
    RightServo.detach();
    CentralServo.detach();
    isAttached = false;
  }
}

void setup() {
  // EN: Start the IR receiver.
  // RU: Начинаем прослушивание ИК-сигналов.
  irrecv.enableIRIn();
  Serial.begin(9600);   
  attachServos();
  isStopped = true;
  lastMillis = millis();

  angleShiftLeftServo = 0;
  angleShiftRightServo = 0;
  angleShiftCentralServo = 0;
 
  stepPeriod = STEP_PERIOD_FAST;
}

// EN: Gets angle for servo.
//     Param amplitude - amplitude of oscillating process,
//     param phaseMillis - current duration of oscillating,
//     param shiftAndle - phase of oscillating process.
// RU: Получение угла для серводвигателя.
//     Параметр amplitude - амплитуда колебаний,
//     Параметр phaseMillis - текущая продолжительность колебаний,
//     Параметр shiftAndle - фаза колебаний.
int getAngle(long amplitude, long phaseMillis, float shiftAngle) {
  float alpha = 2 * PI * phaseMillis / stepPeriod + shiftAngle;
  float angle = amplitude * sin(alpha);
  return (int)angle;
}

template<typename T,size_t N>
boolean hasCode(T (&commandCodes)[N], long code) {
  for (int i = 0; i < N; i++) {
    if (commandCodes[i] == code) {
      return true;
    }
  }
  return false;
}

void loop() {
 
  long millisNow = millis();
  long millisPassed = millisNow - lastMillis;
  if (isStopped) {
    // EN: We should wait for half a second. After that we think that servos are in zero
    //     position and we can detach them.
    // RU: Ждём полсекунды, чтобы серводвигатели вышли в нулевое положение и отключаем их.
    if (millisPassed >= 500) {
      lastMillis = 0;
      detachServos();
    }

    globalPhase = 0;
  } else {
    lastMillis = millisNow;
   
    globalPhase += millisPassed;
    globalPhase = globalPhase % stepPeriod;
  }
 
  // EN: Declaration of the structure that is used for received and decoded IR commands.
  // RU: Описываем структуру results, в которую будут помещаться
  //     принятые и декодированные ИК-команды:
  decode_results results;
 
  // EN: We can handle IR command if it is received and decoded successfully.
  // RU: Если команда успешно принята и декодирована, то мы можем её обрабатывать.
 
  if (irrecv.decode(&results)) {
    irkod=results.value;
   
    if (irkod > 0 && irkod < 0xFFFFFFFF)
    {
    if (hasCode(IR_COMMAND_FORWARD_CODES, irkod) ||
        hasCode(IR_COMMAND_FORWARD_LEFT_CODES, irkod) ||
        hasCode(IR_COMMAND_FORWARD_RIGHT_CODES, irkod)) {
   
      attachServos();
      isStopped = false;
      angleShiftLeftServo = 0;
      angleShiftRightServo = 0;
      angleShiftCentralServo = PI/2;
       
      amplitudeLeftServo = SIDE_SERVOS_FULL_AMPLITUDE;
      amplitudeRightServo = SIDE_SERVOS_FULL_AMPLITUDE;
      if (hasCode(IR_COMMAND_FORWARD_LEFT_CODES, irkod)) {
        amplitudeLeftServo = SIDE_SERVOS_HALF_AMPLITUDE;
      } else if (hasCode(IR_COMMAND_FORWARD_RIGHT_CODES, irkod)) {
        amplitudeRightServo = SIDE_SERVOS_HALF_AMPLITUDE;
      }
    } else if(hasCode(IR_COMMAND_BACKWARD_CODES, irkod) ||
              hasCode(IR_COMMAND_BACKWARD_LEFT_CODES, irkod) ||
              hasCode(IR_COMMAND_BACKWARD_RIGHT_CODES, irkod)) {

      attachServos();
      isStopped = false;
      angleShiftLeftServo = 0;
      angleShiftRightServo = 0;
      angleShiftCentralServo = -PI/2;

      amplitudeLeftServo = SIDE_SERVOS_FULL_AMPLITUDE;
      amplitudeRightServo = SIDE_SERVOS_FULL_AMPLITUDE;
      if (hasCode(IR_COMMAND_BACKWARD_LEFT_CODES, irkod)) {
        amplitudeRightServo = SIDE_SERVOS_HALF_AMPLITUDE;
      } else if (hasCode(IR_COMMAND_BACKWARD_RIGHT_CODES, irkod)) {
        amplitudeLeftServo = SIDE_SERVOS_HALF_AMPLITUDE;
      }
    } else if (hasCode(IR_COMMAND_TURN_LEFT_CODES, irkod)) {
      attachServos();
      isStopped = false;
      angleShiftLeftServo = 0;
      angleShiftRightServo = PI;
      angleShiftCentralServo = -PI/2;
      amplitudeLeftServo = SIDE_SERVOS_FULL_AMPLITUDE;
      amplitudeRightServo = SIDE_SERVOS_FULL_AMPLITUDE;
    } else if (hasCode(IR_COMMAND_TURN_RIGHT_CODES, irkod)) {
      attachServos();
      isStopped = false;
      angleShiftLeftServo = 0;
      angleShiftRightServo = PI;
      angleShiftCentralServo = PI/2;
      amplitudeLeftServo = SIDE_SERVOS_FULL_AMPLITUDE;
      amplitudeRightServo = SIDE_SERVOS_FULL_AMPLITUDE;
    } else if (hasCode(IR_COMMAND_STOP_CODES, irkod)) {
      attachServos();
      isStopped = true;
      angleShiftLeftServo = 0;
      angleShiftRightServo = 0;
      angleShiftCentralServo = 0;
      amplitudeLeftServo = SIDE_SERVOS_FULL_AMPLITUDE;
      amplitudeRightServo = SIDE_SERVOS_FULL_AMPLITUDE;
    } else if (hasCode(IR_COMMAND_VERY_SLOW_CODES, irkod)) {
      // EN: globalPhase correction to save servo positions when changing period.
      // RU: Корректировка globalPhase чтобы сохранить положение серв при смене периода колебаний ног.
      globalPhase = globalPhase * STEP_PERIOD_VERY_SLOW / stepPeriod;
      stepPeriod = STEP_PERIOD_VERY_SLOW;
    } else if (hasCode(IR_COMMAND_SLOW_CODES, irkod)) {
      globalPhase = globalPhase * STEP_PERIOD_SLOW / stepPeriod;
      stepPeriod = STEP_PERIOD_SLOW;
    } else if (hasCode(IR_COMMAND_FAST_CODES, irkod)) {
      globalPhase = globalPhase * STEP_PERIOD_FAST / stepPeriod;
      stepPeriod = STEP_PERIOD_FAST;
    } else if (hasCode(IR_COMMAND_VERY_FAST_CODES, irkod)) {
      globalPhase = globalPhase * STEP_PERIOD_VERY_FAST / stepPeriod;
      stepPeriod = STEP_PERIOD_VERY_FAST;
    }
    // EN: Once a code has been decoded, the resume() method must be called to resume receiving codes.
    // RU: После декодирования кода для продолжения приёма должен вызаваться метод resume().
   Serial.println(irkod);
   
    }
    irrecv.resume();
   
  }
   
  if (isAttached) {
    LeftServo.write(LEFT_SERVO_ZERO_VALUE + getAngle(amplitudeLeftServo, globalPhase, angleShiftLeftServo));
    RightServo.write(RIGHT_SERVO_ZERO_VALUE + getAngle(amplitudeRightServo, globalPhase, angleShiftRightServo));
    CentralServo.write(CENTRAL_SERVO_ZERO_VALUE + getAngle(CENTRAL_SERVO_AMPLITUDE, globalPhase, angleShiftCentralServo));
    if (irkod > 0 && irkod < 0xFFFFFFFF) { Serial.println(irkod);}
   
  }
 
}


на ардуино.ру сказали что библиотеки серво и IRremote конфликтуют по таймерам- проанализировал их - НЕТ. не конфликтуют и используют 1 и 2й таймеры сообверственно. вариант с конфликтом отпадает.
еще разница в том что я использую датчик ик подключенный к цифровому порту- у автора - аналоговый.
не пойму в чем ошибка? помогите.
я так понимаю что у всех кто повторяет этот проект - все работает, потомучто аналогичной проблемы не нашел в интернет.

да, еще пробовал по прерыванию ни порту ик датчика регистрировать команду- получается чуть лучше но все равно не всегда выполняет команду.
прием команд проверял. все принимает. отключал сервы и выводил в монитор.


Вернуться в «Программирование Ардуино»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя