Есть ли способ эффективно закодировать считывание четырех датчиков и отправить последовательный вывод, как только он обнаружит чтение?

На самом деле мне интересно, есть ли способ эффективно выполнить этот блок кода. В моих спецификациях есть две вещи, а именно:

  1. Четыре ИК-датчика, обнаруживающие засорение. В основном просто для того, чтобы активировать его ВЫСОКИЙ или НИЗКИЙ
  2. После срабатывания/срабатывания одного из датчиков он отправляет последовательный вывод.

Для этого я сделал этот код. В основном просто набивка digitalRead и их условия if в цикле. Есть ли способ сделать код короче, но ускорить отправку серийного номера?

#define IRSignal1 2
#define IRSignal2 3
#define IRSignal3 4
#define IRSignal4 5

int IRVal1;
int IRVal2;
int IRVal3;
int IRVal4;

void setup() {
  // поместите сюда код установки для однократного запуска:
  pinMode(IRSignal1, INPUT);
  pinMode(IRSignal2, INPUT);
  pinMode(IRSignal3, INPUT);
  pinMode(IRSignal4, INPUT);

  Serial.begin(9600);
}

void loop() {
  // поместите сюда ваш основной код для многократного запуска:
  IRVal1 = digitalRead(IRSignal1);
  IRVal2 = digitalRead(IRSignal2);
  IRVal3 = digitalRead(IRSignal3);
  IRVal4 = digitalRead(IRSignal4);

  if (IRVal1 == LOW) {
    Serial.print('1');
  }
  if (IRVal2 == LOW) {
    Serial.print('2');
  }
  if (IRVal3 == LOW) {
    Serial.print('3');
  }
  if (IRVal4 == LOW) {
    Serial.print('4');
  }
}

Если у вас есть советы или полезные ресурсы для эффективных методов кодирования, которые также помогают с распределением памяти, более коротким кодом и скоростью, я также хотел бы услышать их, если вы не возражаете.

Я использую Arduino Mega и Uno на случай, если эта информация окажется полезной.

, 👍-1

Обсуждение

Для чего вы оптимизируете? Код, который вы опубликовали, должен быть достаточно быстрым, чтобы отслеживать движущиеся объекты. Если они действительно быстрые, вы можете увеличить скорость передачи (поскольку при 9600 бод продолжительность передачи будет в нижнем миллисекундном диапазоне). Или у вас на самом деле больше кода и это только часть с ИК-датчиками? Это важно, так как этот другой код может изменить частоту выполнения функции loop() и многое другое., @chrisl

«Есть ли какой-либо способ?» почти всегда имеет ответ «да» ... в вашей программе вы можете отправить состояние четырех датчиков как биты одного байта ... использовать четыре запасных бита для сигнализации о состоянии датчика изменение, @jsotola

@chrisl Привет! Для этой системы я просто использую 4 ИК-датчика. Однако мне любопытно, что он делает с скетчем, если в коде будет больше, чем ИК-датчики (например, двигатели или приводы). Как это повлияет на частоту? Например, если сработал ИК-датчик (IRSignal1), то в ответ он, например, включает двигатель постоянного тока (Motor1). Во время вращения Motor1 сработал один из других ИК-датчиков (IRSignal2). Будет ли он одновременно запускать другой двигатель постоянного тока (двигатель 2) или придется ждать, пока не завершится работа двигателя 1?, @fireblazer10

@fireblazer10 Это полностью зависит от того, как вы программируете эти действия, а не от кода датчика, так как это уже довольно быстро. Вам нужно будет написать код действия неблокирующим способом, чтобы он не блокировал все остальное. Хотя это не относится к коду вашего датчика, а является общей парадигмой программирования., @chrisl


3 ответа


3

Всегда есть другие способы закодировать что-то (по крайней мере, если это нетривиально). Что для вас значит «эффективность» в данном случае? Если вас беспокоит скорость, увеличьте скорость передачи данных. Всякий раз, когда хотя бы один датчик имеет ВЫСОКИЙ уровень в течение более чем одной итерации цикла, время последовательного вывода будет контролироваться. Другой способ оптимизировать скорость — поместить код цикла в бесконечный цикл либо внутри функции loop(), либо в конце функции setup(), сохранив вызов и код возврата и входа функции цикла. Точно так же вы можете напрямую считывать входные регистры и сохранять четыре вызова digitalRead().

Но любой из ваших Arduino более чем достаточно быстр (т. е. намного быстрее, чем явления, которые он будет отслеживать), поэтому нет особого смысла в его оптимизации.

Обновление:

Что касается моего второго утверждения в моем коде об эффективных методах кодирования, оно касается распределения памяти, скорости и более короткого кода, потому что что, если в будущем там будет дюжина ИК-датчиков, он все еще будет поддерживать скорость?

Даже ваш Uno по-прежнему достаточно быстр, с достаточным объемом памяти, чтобы управлять дюжиной таких датчиков до уровня обработки, продемонстрированного в вашем коде, и даже больше!

Однако я бы уже заранее подумал об обработке нескольких датчиков без многократного повторения вашего кода, что повышает эффективность еще одного вида: оптимальное использование вашего времени.

Если вы сохранили массив данных датчиков и зациклились на нем, обрабатывая каждый датчик по очереди, один набор кода, который сработает правильно один раз, будет работать правильно "n" раз. Это будет легче прочитать кому-то другому (или вашему будущему я, который, как и я, забыл некоторые детали), и его будет легче исправить или расширить, если вам нужно будет сделать это правильно только за один раз. место вместо «n» мест.

Хотите изменить внешний вид выходных данных терминала, когда ваш проект вырос до 12 или 14 датчиков? Это легко, когда вам нужно сделать все правильно в одном месте!

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

В зависимости от того, как вы расширите свою обработку, у вас, вероятно, может закончиться скорость или память, но судя по представленному коду, этот день кажется далеким. И вы упомянули, что рядом стоит Мега... :-)

,

насколько я понимаю, вопрос OP хочет решить, так как сначала печатать на Serial, только если состояние датчика изменится, @Juraj

Спецификация устройства не указана. Код, написанный правильно, обнаруживает и сообщает о «запущенном» состоянии (очевидно, НИЗКИЙ сигнал). Если требуется отчет о состоянии *изменения*, это не было ни заявлено, ни закодировано. Я ответил на вопрос, который был задан - относительно эффективности. Если ОП не получил помощи, которую он хочет, редактирование его вопроса, чтобы он был более конкретным, вызовет более конкретную помощь., @JRobert

О, извините, я только что понял, что не объяснил, что означает эффективность в контексте моего поста. Я отредактирую его правильно, но на самом деле я имею в виду скорость и сокращение кода. Что касается моего второго утверждения в моем коде об эффективных методах кодирования, оно касается распределения памяти, скорости и более короткого кода, потому что что, если в будущем там будет дюжина ИК-датчиков, он все еще будет поддерживать скорость? Но я не уверен, что это требует другой темы для этого?, @fireblazer10


0

Проще всего это сделать с помощью цифрового прерывания, однако ограничение здесь заключается в том, что стандартный Uno имеет только 2 контакта с возможностью прерывания (2,3), поэтому он не будет работать с 4 датчиками. Однако другие платы, такие как ESP8266, поддерживают прерывания почти на всех выводах (требуется только объявление ICACHE_RAM_ATTR в вызываемой функции)

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  // присоединяем прерывания к запуску функции при изменении состояния вывода
  attachInterrupt(digitalPinToInterrupt(2), pinAtriggered, CHANGE);
  attachInterrupt(digitalPinToInterrupt(3), pinBtriggered, CHANGE); 
}

void loop(){
}
//при использовании ESP8266 это будет выглядеть так:
//ICACHE_RAM_ATTR недействительным pinAtriggered() {
void pinAtriggered(){
  Serial.println("triggered");
}
void pinBtriggered(){
  Serial.println("triggered");
}
,

Хотя на Uno можно было бы использовать PinChangeInterrupt, который доступен для большего количества контактов., @chrisl

Как правило, это плохая идея использовать Serial.println() из подпрограммы обслуживания прерывания., @Edgar Bonet


1

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

Если ИК-датчик переходит в НИЗКИЙ уровень и остается НИЗКИМ, программа отправит соответствующее сообщение повторно, так быстро, как это возможно. Так как код работает намного быстрее, чем последовательный порт, это скоро заполнит последовательный порт выходной буфер порта. Когда это произойдет, Serial.print() не будет больше не может поместить свое сообщение в этот буфер. Столкнувшись с этой ситуацией, он переключится с обычной неблокирующей работы на другой режим блокировки. В этом режиме он заблокирует программу ожидая, пока последовательный порт освободит место в буфере, и только тогда он поместит туда свое сообщение и вернется. Конечный результат что программа будет тормозить и соответствовать скорости серийника порт: всего 960 выполнений функции loop() в секунду.

Интересным побочным эффектом этой ситуации является то, что когда датчик перестанет обнаруживать какую-либо блокировку, тем не менее Arduino продолжит отправка сообщений о том, что обнаружена блокировка. Будет продолжайте делать это около 66 мс: время, необходимое для очистки 63-байтный буфер последовательного вывода.

Если вас беспокоит эта проблема, есть простой способ решить ее: быть для увеличения скорости передачи данных. Это не изменит качественного поведение, но это заставит эти вещи происходить быстрее. я предлагаю тебе подумайте о том, чтобы вместо этого изменить протокол связи, который вы определили для Arduino: вместо повторной отправки информации о текущее состояние датчиков, он может отправлять информацию о состоянии изменения. То есть: одно сообщение отправляется, когда детектор переходит в ВЫСОКИЙ уровень, и другое сообщение отправляется, когда он становится НИЗКИМ. В качестве альтернативы, это может отправить полную информацию о состоянии (какие датчики НИЗКИЙ или ВЫСОКИЙ) периодически или каждый раз, когда это состояние изменяется, или комбинация обе. Я не знаю, что вы делаете с этой информацией на другая сторона последовательной связи, поэтому я не могу сказать, какой вариант может быть больше подходит для вас.

Вы написали в комментарии, что можете подумать о том, чтобы в будущем управлять двигатель вместо отправки последовательных сообщений. Если вы пойдете по этому пути, вы определенно нужно работать над изменениями состояния. для запуска постоянно, двигатель не требует многократного нажатия кнопки «ON» кнопку тысячу раз в секунду, и он не выключится все по себя только потому, что вы перестали его включать. Вместо этого вы включаете его один раз и оставить его в покое, и он останется. Когда ты захочешь, чтобы это прекратилось, вы должны активно выключать его. Действия по включению/выключению требуется только для изменения состояния мотора, а не для сохранения текущее состояние.

,