Использование оператора case с приемником ИК-излучателя
Я пытаюсь использовать два "инфракрасных модуля обхода препятствий" для работы со следующим скетчем. Из всех моих исследований я считаю, что формулировка случая - мой лучший вариант, потому что (я понимаю) набросок не будет продолжаться, пока случай не будет удовлетворен, однако я получаю странный результат. При использовании двух датчиков, как показано на схеме ниже, светодиоды мигают попеременно, но рядом с ИК-датчиками их нет.
Если я использую только один модуль, светодиод будет гореть до тех пор, пока датчик не увидит что-то, затем светодиод выключится на запрограммированную задержку, а затем снова загорится.
В итоге я ищу три модуля, которые будут загораться случайным образом, когда один загорается, он ждет, пока что-то не сломает луч, затем загорается другой и ждет... У кого-нибудь есть идеи, как заставить это работать?
int ledselect;
int led1 = 2;
int led2 = 3;
int ir1 = 4;
int ir2 = 5;
int s1 = A0;
int s2 = A1;
void setup() {
Serial.begin(9600);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(ir1, OUTPUT);
pinMode(ir2, OUTPUT);
pinMode(s1, INPUT);
pinMode(s2, INPUT);
}
void loop() {
ledselect = random(2);
switch (ledselect) {
case 0:
digitalWrite(led1, HIGH);
digitalWrite(ir1, HIGH);
delay(50);
while (analogRead(s1) >= 100)
{
delay(50);
digitalWrite(led1, LOW);
digitalWrite(ir1, LOW);
}
break;
case 1:
digitalWrite(led2, HIGH);
digitalWrite(ir2, HIGH);
delay(50);
while (analogRead(s2) >= 100)
{
delay(50);
digitalWrite(led2, LOW);
digitalWrite(ir2, LOW);
}
break;
}
}
@Bender, 👍-1
Обсуждение1 ответ
Происходит следующее:
- Выбирается случайное число
- Горит свет
- Он срабатывает, когда рядом ничего нет (при условии, что низкое значение аналогового датчика означает, что поблизости ничего нет?)
- Горит тот же или другой индикатор (в зависимости от случайного светодиода).
- Продолжить с 3.
Некоторые причины, по которым это может не сработать:
- Проверьте значение (должно ли оно быть больше или меньше 100?)
- Возможно, датчик не очень точен и иногда дает 0 или максимальные значения, которые неверны. Чтобы изменить это, несколько раз прочитайте датчик и возьмите среднее значение или удалите несколько самых низких и самых высоких значений (чтобы удалить пики) и получите среднее значение.
ОБНОВЛЕНИЕ
Тело операторов case
почти одинаково, сделайте его функцией, вызываемой из обоих операторов case
:
Ваш код будет выглядеть так:
void loop() {
ledselect = random(2);
switch (ledselect) {
case 0:
process(led1, ir1, s1);
break;
case 1:
process(led2, ir2, s2);
break;
}
}
void process(int led, int sw, int ir)
{
digitalWrite(led, HIGH);
digitalWrite(ir, HIGH);
delay(50);
while (analogRead(sw) >= 100)
{
delay(50);
digitalWrite(led, LOW);
digitalWrite(ir, LOW);
}
}
Если вы используете тернарный оператор ( x ? y : z, что означает, если x чем y else z), то ваша функция loop
будет выглядеть так:
void loop() {
ledselect = random(2);
process(ledselect == 0 ? led1 : led2,
ledselect == 0 ? ir1 : ir2,
ledselect == 0 ? s1 : s2);
}
Еще более элегантный способ — использовать массив для частей (не знаю, какое имя может быть лучше), вместо всех переменных с именами 0 и 1, поместить их в массивы, и вы получите следующий код ниже. Если вы сделаете больше деталей, вы просто измените начало кода.
int ledselect;
const int NrOfParts = 2;
int leds [NrOfParts] = { 2 , 3 };
int irs [NrOfParts] = { 4, 5 };
int switches [NrOfParts] = { A0, A1 };
void setup() {
Serial.begin(9600);
for (int part = 0; part < NrOfParts; part++)
{
pinMode(leds [part], OUTPUT);
pinMode(irs [part], OUTPUT);
pinMode(switches[part], INPUT);
}
}
void loop()
{
ledselect = random(2);
process(leds[ledselect], irs[ledselect], switches[ledselect]);
}
void process(int led, int sw, int ir)
{
digitalWrite(led, HIGH);
digitalWrite(ir, HIGH);
delay(50);
while (analogRead(sw) >= 100)
{
delay(50);
digitalWrite(led, LOW);
digitalWrite(ir, LOW);
}
}
Обновление 2
Еще лучший способ — создать структуру (так вы будете хранить всю информацию об одной "части" вместе).
Это решение использует & (разыменование), что означает, что это похоже на переменную, указывающую на часть.
int ledselect;
const int NrOfParts = 2;
struct Part
{
int led;
int ir;
int sw;
};
Part _parts[NrOfParts] =
{
{ 2, 4, A0 },
{ 3, 5, A1 }
};
void setup() {
Serial.begin(9600);
for (int partNumber = 0; partNumber < NrOfParts; partNumber++)
{
Part& part = _parts[partNumber];
pinMode(part.led, OUTPUT);
pinMode(part.ir , OUTPUT);
pinMode(part.sw , INPUT);
}
}
void loop()
{
process(_parts[random(2)]);
}
void process(Part& part)
{
digitalWrite(part.led, HIGH);
digitalWrite(part.ir, HIGH);
delay(50);
while (analogRead(part.sw) >= 100)
{
delay(50);
digitalWrite(part.led, LOW);
digitalWrite(part.ir, LOW);
}
}
Спасибо, Мишель, за ваш ответ. Я воспользовался вашим предложением, чтобы очистить скетч, и очень ценю, что вы нашли время, чтобы проанализировать мой вопрос и ответ., @Bender
Я добавил еще несколько альтернатив, не используйте их, если вы не чувствуете себя комфортно., @Michel Keijzers
- Использование аналогового входа для чтения кнопки
- Как работать с аналоговыми контактами в цикле?
- Двоичный в десятичный с использованием побитовых операторов
- Неверные показания аналогового термистора
- Декодирование порта VGA с помощью Arduino
- Что касается обхода PGA в ADS1262
- Помогите совместить цифровой и аналоговый код в программировании ардуино
- Как масштабировать сигнал от 0 до 5 В до -5 В до +5 В?
скетч не будет продолжаться до тех пор, пока случай не будет удовлетворен
... это не совсем правильно... оператор case - это просто структурарешения
, которая разветвляется на разные части кода в зависимости от значения параметра.. .. это похоже на серию операторов if, @jsotola