Минимизация цифрового входного кода

Я создаю устройство, которое может умножать аналоговый входной сигнал относительно выбранного усиления с цифровых входов. Здесь я использовал два цифровых входа (из которых я могу иметь четыре выбора), но я планирую добавить еще два входа (тогда я могу иметь 16 выборов). Я сделал код с операторами if else, есть ли более короткий способ сделать это? или код становится огромным.

вот код:

#define sensor A0
#define resetPin 3
#define measurePin 2
#define k1 3
#define k2 4

float A = 0;
float J = 0;
int resetstatus = 0;
int measurestatus = 0;

void setup() {
  Serial.begin(9600);
  pinMode(sensor,INPUT);
  pinMode(resetPin,INPUT_PULLUP);
  pinMode(measurePin,INPUT_PULLUP);
  pinMode(k1,INPUT_PULLUP);
  pinMode(k2,INPUT_PULLUP);
  Serial.println("INITIALAIZING");
  delay(3000);
  Serial.println("Ready to begin");
  delay(200);
  }

void loop() 
{
  resetstatus = digitalRead(resetPin);
  measurestatus = digitalRead(measurePin);
  if(resetstatus == LOW) 
  {
    reset();
    delay(200);
  }
  if(measurestatus == LOW) 
  {
    if(digitalRead(k1 == LOW) && digitalRead(k2 == LOW))
    {
    J = 1.0;
    measure();
    delay(50); 
    }
    else if(digitalRead(k1 == LOW) && digitalRead(k2 == HIGH))
    {
    J = 2.0;
    measure();
    delay(50);
    }
    else if(digitalRead(k1 == HIGH) && digitalRead(k2 == LOW))
    {
    J = 3.0;
    measure();
    delay(50);
    }
    if(digitalRead(k1 == HIGH) && digitalRead(k2 == HIGH))
    {
    J = 4.0;
    measure();
    delay(50);
    }
  }
}
void measure()
{
  A = analogRead(sensor);
  float sumA = A * J;
  Serial.println(sumA);
}
void reset()
{
  Serial.println("reset");
}

У меня возникла проблема с выводом этого кода (Я использую потенциометр для подачи на Arduino аналогового значения)

вывод

Я не знаю, почему вывод показывает 993 и 3972 в каждом цикле. Может кто-нибудь объяснить?

, 👍0


4 ответа


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

2

Я создал код с операторами if else. Есть ли более короткий способ сделать это?

j = 1 + (digitalRead(k1) | (digitalRead(k2) << 1) | (digitalRead(k3) << 2) | (digitalRead(k3) << 3));

или

j = 1 + digitalRead(k1) + 2*digitalRead(k2) + 4*digitalRead(k3) + 8*digitalRead(k4)

Не знаю, почему вывод показывает 993 и 3972 в каждом цикле. Может кто-нибудь объяснить?

напечатанные значения неверны из-за ошибки, указанной в ответе Ника

,

3

Это неправильно:

if(digitalRead(k1 == LOW)

Вы имеете в виду:

if(digitalRead(k1) == LOW

То же самое касается и многих других мест в вашем коде.

,

2

Я создал код с операторами if else. Есть ли более короткий способ сделать это? в противном случае код становится огромным.

Да, есть способ упрощения. Как уже заметил @Juraj, в этом частном случае его можно даже выразить как двоичное представление:

if(digitalRead(k1) == LOW && digitalRead(k2) == LOW)
{
J = 1.0;
measure();
delay(50); 
}
else if(digitalRead(k1) == LOW && digitalRead(k2) == HIGH)
{
J = 2.0;
measure();
delay(50);
}
else if(digitalRead(k1) == HIGH && digitalRead(k2) == LOW)
{
J = 3.0;
measure();
delay(50);
}
if(digitalRead(k1) == HIGH && digitalRead(k2) == HIGH)
{
J = 4.0;
measure();
delay(50);
}

То, что вы здесь делаете, представляет собой следующую схему:

  • прочитать состояние кнопок
  • в зависимости от того, какие комбинации кнопок нажаты, присвойте J
  • разное значение

Мы можем обобщить эту концепцию «получить значение J для определенной комбинации кнопок», выполнив следующие действия:

  • объединить все «состояния кнопок» в одно уникальное число
  • найти соответствующее значение J

Если мы назовем состояния кнопок ввода «k1» и «k2», то увидим следующую логику:

| k1 | k2 | J   |
| 0  | 0  | 1.0 |
| 0  | 1  | 2.0 |
| 1  | 0  | 3.0 |
| 1  | 1  | 4.0 |

Мы просто объединяем входные данные кнопок в одну битовую строку «k1|k2» и видим

| (k1,k2) | J   |
| 00      | 1.0 |
| 01      | 2.0 |
| 10      | 3.0 |
| 11      | 4.0 |

Если мы перепишем двоичные индексы в десятичные числа:

| (k1,k2) | J   |
| 0       | 1.0 |
| 1       | 2.0 |
| 2       | 3.0 |
| 3       | 4.0 |

Итак, мы видим, что можем использовать это число (k1,k2) как индекс от 0 до 3, чтобы получить значение J как таковое:

//Объединить все нажатия кнопок в одно число
//использование битовых сдвигов
int index = (digitalRead(k2) << 1) | digitalRead(k1);

//Все используемые значения J в правильном порядке
const float J_values[] = {
        1.0f, 2.0f, 3.0f, 4.0f
};

//получить правильное значение J
J = J_values[index];

//измерение и задержка
measure();
delay(50);

Это заменяет все ваши 4 оператора if-else и делает то же самое.

Теперь, если вы добавите больше входов, вы можете просто расширить способ построения индексного номера и вашего массива J_values. Запишите "таблицу функций" для нужных вам значений J, как указано выше, создайте строки битов, упорядочите индексы в порядке возрастания и запишите значения массива соответственно.

Ссылки:

  • https://www.cprogramming.com/tutorial/bitwise_operators.html
  • https://www.arduino.cc/reference/en/language/structure/bitwise-operators/bitshiftleft/
,

1

Подключите все 4 контакта к одному порту, затем выполните чтение порта. Допустим, вы использовали D2,3,4,5. Затем переключатели = (PIND && 0b00111100) >> 2;

затем переключатели = от 0 до 15, и вы можете сделать ветвление на этом.

,