Прерывание запуска двигателей

Я использую роботизированный автомобиль с 4wd для измерения прямых расстояний. Я прикрепил два датчика на двух передних колесах, чтобы измерить расстояние, и я использую два задних колеса, чтобы отрегулировать автомобиль и держать его прямо, используя компас в качестве ориентира. Проблема в том, что когда моя программа выполняет раздел, который приводит в движение задние колеса, это каким-то образом вызывает прерывание и увеличивает количество тиков. Что является причиной этой проблемы?

volatile unsigned long enc_l = 0;
volatile unsigned long enc_r = 0;

void driveStraight(float drive_distance, int motor_power)
{
  Serial.print("\n");
  Serial.println("num_tick_l \t num_tick_r \t diff_l \t diff_r \t enc_1_prev \t enc_r_prev \t Power_l \t Power_r \t Power_a \t Power_b ");

  unsigned long num_ticks_l;
  unsigned long num_ticks_r;

  // Установить начальную мощность двигателя
  int power_l = motor_power;
  int power_r = motor_power;

  // Используется для определения, в какую сторону повернуть, чтобы настроить
  unsigned long diff_l;
  unsigned long diff_r;

  // Сброс количества отсчетов энкодера
  enc_l = 0;
  enc_r = 0;

  // Запомнить предыдущие подсчеты кодировщика
  unsigned long enc_l_prev = enc_l;
  unsigned long enc_r_prev = enc_r;

  // Рассчитать общее количество тиков
  float num_rev = (drive_distance * 10) / wheel_c;   // Преобразовать в мм
  unsigned long target_count =  29; //num_rev * counts_per_rev;


  /*
    // Отладка
    Serial.print("Driving for ");
    Serial.print(drive_distance);
    Serial.print(" cm(");
    Serial.print(target_count);
    Serial.print(" ticks) at ");
    Serial.print(motor_power);
    Serial.println(" Motor Power");
  */

  // Двигайтесь до тех пор, пока один из энкодеров не достигнет желаемого значения
  while ((enc_l < target_count) && (enc_r < target_count))
  {

    bluetooth();                                // если получено новое значение bluetooth, выходите из цикла
    if (blueToothVal == 5) {
      break;                                    // Если получена команда Bluetooth 'Stop', то выходите из цикла
    }

    // Примерное количество тактов энкодера
    num_ticks_l = enc_l;
    num_ticks_r = enc_r;

    // Выборка текущего количества тиков
    Serial.print(num_ticks_l);
    Serial.print("  \t\t");
    Serial.print(num_ticks_r);

    // Привод
    drive(power_l, power_r);

    // Количество тиков, подсчитанных с момента последнего раза
    const int StraightDriveOffset = 1;                    // Увеличьте это значение или даже сделайте его отрицательным числом, чтобы настроить

    diff_l = num_ticks_l - enc_l_prev;                    // + Прямой привод offset;
    diff_r = num_ticks_r - enc_r_prev;


    Serial.print("  \t\t");
    Serial.print(diff_l);
    Serial.print(" \t \t");
    Serial.print(diff_r);


    // Сохраните текущий счетчик тиков для следующего раза
    enc_l_prev = num_ticks_l;
    enc_r_prev = num_ticks_r;


    Serial.print("   \t \t");
    Serial.print(enc_l_prev);
    Serial.print(" \t \t");
    Serial.print(enc_r_prev);


    // Если левый быстрее, замедлите его и ускорьте правый
    if ( diff_l > diff_r) {
      power_l -= motor_offset;
      power_r += motor_offset;
    }

    // Если вправо быстрее, замедлите его и ускорьте вправо
    if ( diff_l < diff_r) {
      power_l += motor_offset;
      power_r -= motor_offset;
    }

    // Отладка
    Serial.print(" \t\t");
    Serial.print(power_l);
    Serial.print(" \t\t");
    Serial.println(power_r);


    // Кратковременная пауза, чтобы дать двигателям отреагировать
    delay(20);
  }

  StopCar();
  //Звуковой сигнал();
}

void drive(int power_a, int power_b)
{
  getCompass();                                                     // Обновить направление компаса
  bluetooth();                                                      // Проверьте, были ли отправлены какие-либо команды Bluetooth

  if (blueToothVal == 5) {
    break; // Если получена команда Stop Bluetooth ('5'), то выходите из цикла
  }

  // Ограничить мощность в диапазоне от -255 до 255
  power_a = constrain(power_a, -255, 255);
  power_b = constrain(power_b, -255, 255);

  if ( abs(desired_heading - compass_heading) <= compass_dev )      // Если желаемый курс и курс компаса находятся в пределах отклонения компаса, на X градусов друг от друга, затем двигайтесь вперед
    // в противном случае найдите кратчайший радиус поворота и поверните налево или направо
  {
    // Направление двигателя влево
    if ( power_a < 0)
    {
      motor2.setSpeed(abs(power_a));       // Двигатель - переднее левое колесо
      motor2.run(BACKWARD);

    }
    else
    {
      motor2.setSpeed(abs(power_a));       // Двигатель - переднее левое колесо
      motor2.run(FORWARD);

    }

    // Правильное направление двигателя
    if ( power_b < 0)
    {
      motor4.setSpeed(abs(power_b));       // Двигатель - переднее левое колесо
      motor4.run(BACKWARD);

    }
    else
    {
      motor4.setSpeed(abs(power_b));       // Двигатель - переднее левое колесо
      motor4.run(FORWARD);

    }

  }

  else
  {
    int x = (desired_heading - 359);                          // x = желаемый курс GPS - 360
    int y = (compass_heading - (x));                          // y = курс компаса - x
    int z = (y - 360);                                        // z = y - 360

    if ((z <= 180) && (z >= 0))                               // если z меньше 180 и не является отрицательным значением, то поверните налево
    { // в противном случае поверните направо
      motor1.setSpeed(190);
      motor3.setSpeed(190);
      motor1.run(BACKWARD);
      motor3.run(FORWARD);
    }
    else
    {
      motor1.setSpeed(190);
      motor3.setSpeed(190);
      motor1.run(FORWARD);
      motor3.run(BACKWARD);

    }
  }
}

void countLeft()
{
  enc_l ++;
}

void countRight()
{
  enc_r ++;
}

и это то, что находится в функции настройки

const int enc_l_pin = 18;
const int enc_r_pin = 19;

void setup()
    {
      Serial.begin(115200);                                            // Serial 0 предназначен для связи с компьютером
      Serial3.begin(9600);                                             // Serial 1 предназначен для связи по Bluetooth - НЕ ИЗМЕНЯТЬ - JY-MCU HC-06 v1.40

      Wire.begin();                                                    // Подключение к шине I2C, используемой для компаса HMC5883L
      compass.begin();                                                 // инициализировать compass (HMC5883L)
      compass.setRange(HMC5883L_RANGE_1_3GA);                          // Установить диапазон измерений
      compass.setMeasurementMode(HMC5883L_CONTINOUS);                  // Установить режим измерения
      compass.setDataRate(HMC5883L_DATARATE_30HZ);                     // Установить скорость передачи данных
      compass.setSamples(HMC5883L_SAMPLES_8);                          // Установить количество усредненных выборок
      compass.setOffset(118, 473);                                      // Установить калибровочное смещение

      // Зуммер
      pinMode(Buzzer_pin, OUTPUT);

      // Настройка контактов
      pinMode(enc_l_pin, INPUT);
      pinMode(enc_r_pin, INPUT);


      // Настройка прерываний
      attachInterrupt(digitalPinToInterrupt(enc_l_pin), countLeft, CHANGE);
      attachInterrupt(digitalPinToInterrupt(enc_r_pin), countRight, CHANGE);

, 👍2

Обсуждение

Я не вижу никакого кода прерывания. Пожалуйста, предоставьте полный (!) рабочий минимальный пример кода, который показывает вашу проблему., @chrisl

Да, извините, я только что добавил их в, @NoName123

У вас есть подтягивающий или подтягивающий резистор? Если нет, то выход будет плавающим., @chrisl

Когда я пытаюсь подключить подтягивающий резистор к + vcc и выходному контакту датчика эффекта Холла, как показано на рисунке, напряжение остается постоянным, @NoName123

Какой именно тип датчика Холла вы используете?, @chrisl

UGN3503UA Датчик эффекта Холла https://www.jaycar.com.au/medias/sys_master/images/9168322953246/ZD1902-dataSheetMain.pdf, @NoName123


1 ответ


1

Я думаю, у вас есть 2 проблемы:

  1. Используемый датчик Холла является аналоговым устройством, а не цифровым. Это означает, что он не будет выдавать ни Vcc, ни 0V, а вместо этого аналоговое (непрерывное) напряжение в зависимости от магнитного поля. При нулевом магнитном поле он будет выдавать примерно половину напряжения питания (в данном случае 2,5 В, поскольку Vcc для вас равен 5 В). Для аналоговых сигналов подтягивания или опускания не имеют смысла. Цифровые контакты имеют гистерезис, что означает, что они будут обнаруживать НИЗКОЕ напряжение между 0 В и 1,67 В и ВЫСОКОЕ между 3,33 В и 5 В (см. Этот ответ). Это также называется триггером Шмитта. Я предполагаю, что вы просто хотите измерить, что магнит находится рядом с датчиком (так что имеет значение только одна полярность). Это означает, что напряжение будет оставаться, скажем, выше 2,5 В (в зависимости от полярности) и будет колебаться только от 2,5 В до 5 В и обратно. В этом состоянии состояние вывода будет оставаться высоким, так как оно установлено на высоком уровне, но никогда не достигает напряжения, достаточного для установки его на низкое значение. Прерывание не будет вызвано. В зависимости от того, что вы хотите, и следующей проблемы, вы можете вместо этого использовать компаратор (который является специальным периферийным устройством микроконтроллера) для запуска увеличения при достижении заданного порогового напряжения (это также означает, что оно будет срабатывать из-за небольших изменений порогового значения), или вы можете купить или построить внешний триггер Шмитта, с помощью которого вы можете изменять пороговые напряжения для НИЗКИХ и ВЫСОКИХ значений.

  2. Двигатели излучают довольно много электромагнитного шума, который может искажать аналоговые сигналы поблизости. Скорее всего, шум от двигателей достаточно высок, чтобы ложно вызвать изменение состояния на выводе. Возможно, вам следует посмотреть на аналоговый сигнал с помощью осциллографа, который может показать вам, сколько шума у вас действительно есть в этой ситуации. Существует много способов уменьшить шум в аналоговом сигнале. Один из них заключается в добавлении фильтра нижних частот для подавления в основном высокочастотного шума. Это работает только в том случае, если частота вашего сигнала значительно ниже (так что вы можете обрезать фильтр нижних частот, чтобы пропустить ваш сигнал).


На картинке я не вижу, как магниты и датчики движутся в машине. Обязательно измеряйте различные напряжения в разных состояниях (магнит рядом с датчиком, магнит вдали). Если датчик слишком чувствителен или ваш магнит слишком силен, вы можете получить еще меньший диапазон напряжения, чем 2,5 В, который у вас уже есть.

,

Спасибо за ценную информацию. Я буду работать над разработкой триггера Шмитта и дам вам знать, как я это сделаю., @NoName123

Я построил неинвертирующий триггер Шмитта. Принципиальную схему можно увидеть в посте. Проблема, с которой я сталкиваюсь, заключается в том, что как только я подключаю выходной вывод датчика эффекта Холла к входу триггера Шмитта, на входе остается 3,3 В, а на выходе отображается около 4,22 В., @NoName123