5-битный способ связи?

bit

Хорошо, я работаю над проектом, в котором я хочу, чтобы несколько переключателей создавали "код" для определения дальнейших действий. По сути, это 5-битный процесс связи, который создаст выходные данные с 32-битным диапазоном результатов от 00000 до 11111.

Я тестирую метод с тремя переключателями, поэтому, если первый и третий переключатели работают/включены, он будет показывать 101. Второй и третий, 011 и т.д. Я недостаточно сведущ, чтобы знать, есть ли здесь лучший метод, но есть ли лучший способ сделать это?

    // Определите используемые контакты
int pin_switch = 10;
int pin_switch2 = 11;
int pin_switch3 = 12;

// создать int для 3-значного кода
int code = 000;
 

void setup() 
{
    Serial.begin(9600); 
    pinMode(pin_switch, INPUT); 
    pinMode(pin_switch2, INPUT); 
    pinMode(pin_switch3, INPUT); 
}
 
void loop()
{

if pin_switch == HIGH;
    {code += 100;}

if pin_switch2 == HIGH;
    {code += 10;}

if pin_switch3 == HIGH;
    {code += 1;}

Serial.print(code);

// operate based on code output
if code == 101;
    {do 101 stuff}

if code == 001
    {do 001 stuff}

// сбросить код для следующего цикла, чтобы числа не продолжали расти
code = 000;
}

, 👍-1

Обсуждение

Примечание: не записывайте начальные нули в десятичном числе на C или C++ (или на множестве других языков) - числа будут рассматриваться как восьмеричные, а не десятичные, что очень редко бывает тем, что вам нужно., @Mat


2 ответа


2

Было бы удобнее и меньше печатать, если бы вы поместили все свои контакты переключателя в массив. Таким образом, вы можете обойти его, чтобы настроить порты и прочитать их, а не копировать/вставлять "один и тот же" код снова и снова.

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

Идея такого рода цикла заключается в следующем:

  1. начните с пустого (нулевого) кода
  2. умножьте код на 10 (или один раз сдвиньте влево для двоичного кода)
  3. считайте переключатель, добавьте 1 к коду, если он ВЫСОКИЙ
  4. вернитесь к шагу 2, если есть еще переключатели.

Значение уже прочитанных переключателей "сдвигается" на один слот влево перед чтением следующего переключателя, в результате чего получается нужный вам код.

Порядок, в котором вы перечисляете порты в массиве, важен: первый порт в массиве изменит крайнюю левую (самую значимую) цифру/бит в коде.

const uint8_t switch_pin[] = { 10, 11, 12 };
const uint8_t num_switches = sizeof(switch_pin)/sizeof(switch_pin[0]);

void setup() {
  // Установить все контакты переключателя в режим ввода
  for (uint8_t i = 0; i < num_switches; ++i) {
    pinMode(switch_pin[i], INPUT);
  }
  Serial.begin(9600);
}

void loop() {
  int code = 0;
  // Считать каждый переключатель и вычислить код
  for (uint8_t i = 0; i < num_switches; ++i) {
    // Если код должен быть в десятичной системе счисления
    code = code * 10;
    code += digitalRead(switch_pin[i]);
    /* Для двоичной версии код должен быть длиной всего 8 бит:
    code <<= 1;
    code |= digitalRead(switch_pin[i]);
    */
  }
  
  // Делайте что-нибудь с кодом
  Serial.println(code);
  delay(200);
}
,

О, спасибо, Мэт, я думаю, что Сдвиг и Добавление-это терминология, которой мне не хватало! Я думаю, что я действительно хочу перейти на двоичный код, я думаю, что расширю это до пяти переключателей, чтобы аспект переключения упрощал это в моем представлении. Глядя на ваш код здесь: код <<= 1; Как бы я изменил и добавил для других частей кода? Приор выведет 010, верно? Мне бы просто нужно было сделать <<<=1; И <<= 1, чтобы получить 110? Спасибо вам за помощь., @Mulcch

Если " код равен 1010, код <<= 1 (это то же самое, что " код = код << 1) приведет к "10100" (сдвиньте влево, вставьте ноль справа). Код |= 1; будет "заполнять" последнюю позицию до " 10101. код |= 0;` ничего не даст., @Mat


2

К сожалению, ваш код повсюду. Вы должны использовать синтаксис C/C++, чего вы не делаете. Кроме того, вы на самом деле не читаете никаких данных.

  • если утверждения выглядят так:

      if(condition){
          my_code();
      }
    
  • if(pin_switch == ВЫСОКИЙ) (исправленный синтаксис) всегда будет ложным, так как pin_switch имеет значение 10. Это просто номер контакта. Чтобы действительно прочитать номер контакта, вам нужно использовать digitalRead() следующим образом:

      if(digitalRead(pin_switch) == HIGH)
    

    или даже проще

      if(digitalRead(pin_switch))
    
  • Похоже, что вы хотите манипулировать битами с помощью кода += 100;, но компилятор принимает числа как десятичные. Таким образом, вы добавляете 100 в код. Пожалуйста, изучите побитовые операторы. Также: вы действительно можете записывать числа в двоичном или шестнадцатеричном формате, используя 0b101 или 0xF3 соответственно (значения здесь являются лишь примерами). Это также означает, что код int = 000; совпадает с кодом int = 0;.


Чтобы построить 3-значный код из входных данных, вы можете собрать их вместе с помощью побитовых операторов:

code = (digitalRead(pin_switch3) << 2) | (digitalRead(pin_switch2) << 1) | digitalRead(pin_switch);

В зависимости от вашего используемого Arduino и используемых контактов, вы можете сделать это еще проще. Контакты сортируются по портам. Каждый порт имеет специальный регистр функций, в котором хранится текущее состояние контактов. Вы можете замаскировать любые нежелательные контакты и изменить число, чтобы оно было правильно обосновано. Например: На выводах Uno и Nano от 2 до 7 принадлежат PORTD. Таким образом, если вы используете контакты от 2 до 4 для своих 3 переключателей, вы можете получить код, такой как:

code = (PIND & 0b00011100) >> 2;

Это немного сложнее понять, но это поможет вам позже, когда вы будете больше заниматься Arduino.


Для принятия решения о том, какое действие следует выполнить на основе кода, обычно проще использовать оператор случая переключения:

switch(code){
    case 0b101:
        do_something();
        break;
    case 0b011:
        do_something_else();
        break;
}
,

Спасибо! Да, мой код был поспешно собран из примера, чтобы протестировать метод. Действительно ценю направление здесь, я буду больше копаться в побитовых операторах!, @Mulcch

@Mulcch ой, исправлена небольшая ошибка. Я использовал "PORTD` вместо "PIND". Первый используется для установки выходного состояния вывода, второй отражает текущее входное состояние., @chrisl

Спасибо, что поймали! Я не уверен, что пойду по этому пути, но действительно полезно знать об этом., @Mulcch