Управление двумя ультразвуковыми датчиками без блокировки другого

У меня есть ультразвуковой датчик расстояния. Когда этот датчик измеряет расстояние менее 25 см, второй датчик должен измерять расстояние менее 5 см. Если нет, то должен быть промежуток времени в одну минуту, после которого динамик должен издавать шум, пока второй датчик не измеряет расстояние менее 5 см.

У меня проблемы с этим. Первый датчик имеет много кода, он также должен работать, поэтому использование цикла while для ожидания одной минуты для другого датчика и создания шума после этого невозможно.

Как решить эту дилемму? Я читал прерывания в Arduino, но, к сожалению, не знаю, как заставить это работать.

, 👍0

Обсуждение

посмотрите на пример «мигать без промедления»; вам нужно сделать то же самое во время «ожидания» на датчиках., @dandavis


2 ответа


Лучший ответ:

5

Я настоятельно рекомендую вам использовать прерывания и убедиться, что датчики находятся в цилиндрическом конусе, чтобы максимально предотвратить помехи друг другу.

Вот фрагмент кода, который может дать вам представление о том, как устанавливаются и используются прерывания. Я считаю, что вы можете адаптировать его к себе. Он взят с форума Arduino (ссылка), авторство "cattledog".

volatile unsigned long LastPulseTimeA;
volatile unsigned long LastPulseTimeB;
int durationA;
int durationB;
//беззнаковое длинное startTime;
#define trigPinA 7
#define echoPinA 2
#define trigPinB 8
#define echoPinB 3
void setup() {
  Serial.begin (9600);
  pinMode(trigPinA, OUTPUT);
  pinMode(echoPinA, INPUT);
   pinMode(trigPinB, OUTPUT);
  pinMode(echoPinB, INPUT);  
attachInterrupt(digitalPinToInterrupt(echoPinA), EchoPinA_ISR, CHANGE);  // Прерывание контакта 2 при любом изменении
attachInterrupt(digitalPinToInterrupt(echoPinB),EchoPinB_ISR, CHANGE);  // Прерывание Pin3 при любом изменении
}
void loop(){
  digitalWrite(trigPinA, LOW);
  digitalWrite(trigPinB, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPinA, HIGH);
  digitalWrite(trigPinB, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPinA, LOW);
  digitalWrite(trigPinB, LOW);
  Serial.print("Sensor A  ");
  Serial.print(LastPulseTimeA);
  Serial.print('\t');
  Serial.print((LastPulseTimeA/2) / 29.1,1);
  Serial.println("cm");
  Serial.print("Sensor B  ");
  Serial.print(LastPulseTimeB);
  Serial.print('\t');
  Serial.print((LastPulseTimeB/2) / 29.1,1);
  Serial.println("cm");

  delay(1000);
}
void EchoPinA_ISR() {
    static unsigned long startTimeA;

    if (digitalRead(echoPinA)) // Ушел ВЫСОКИЙ
        startTimeA = micros();
    else  // Ушел НИЗКИЙ уровень
        LastPulseTimeA = micros() - startTimeA;
}
void EchoPinB_ISR() {
    static unsigned long startTimeB;

    if (digitalRead(echoPinB)) // стал ВЫСОКИМ
        startTimeB = micros();
    else  // Ушел НИЗКИЙ уровень
        LastPulseTimeB = micros() - startTimeB;
}
,

Спасибо, я попробую. Вопрос, однако, будет ли достаточно времени для запуска остальной части программы, поскольку я предполагаю, что контакты будут постоянно менять значение, прерывая программу 24/7?, @andrew

Насколько я вижу из спецификаций, эхо будет занимать некоторое время до 25 мс в зависимости от расстояния, может быть даже больше, если нет препятствия, и тогда может занять до 38 мс. Так что загруженности не будет. Но, конечно, это также то, что вы хотите сделать с эхо-данными. Затем вы можете подумать о переключении Arduino Mega или даже Cortex-M0 или выше., @Sener


1

довольно просто:

  if (time_is_up_for_sensor1()) read_sensor1(); // читаем датчик1, если время истекло
  if (time_is_up_for_sensor2()) read_sensor2(); //читаем датчик2, если время истекло

в time_is_up_for_sensor1/2() обновить для следующего раунда чтения:

int time_is_up_for_sensor1(void) {
  static uint32_t millis_next = 0; //следующий миллисекунд
  if (millis() >= millis_next) {  //время для датчика1 истекло
    millis_next += INTERVAL_SENSOR1; // переход к следующему времени измерения
    return 1;  //нужно считать датчик1
  } else return 0;
}

аналогично для датчика2

,

millis_next += INTERVAL_SENSOR1; ... if (millis() >= millis_next)... метод неправильно вычисляет, когда millis() переполняется. Чтобы избежать этого, вместо этого напишите millis_prev = millis(); (или, возможно, millis_prev += INTERVAL_SENSOR1;), а затем проверьте с помощью if (millis()-millis_prev > INTERVAL_SENSOR1)..., @James Waldby - jwpat7

что именно делает static uint32_t millis_next = 0;? (я новичок в C++/Arduino), @andrew