Как разоблачить битовые маски с Arduino? (не кнопки ...) - PullRequest
1 голос
/ 25 марта 2020

У меня есть этот фрагмент кода, который я хотел бы отменить: я хочу убедиться, что даже через ± 1,5 секунды показания будут такими же (если это так, сделайте что-нибудь, иначе сделайте что-нибудь еще ...) .

Функция Winning_check () получает битовую маску в качестве входных данных и запускается внутри l oop ().

void winning_check(uint16_t mask) {
if ((mask & 0b11111000000000) == 0b11111000000000) {  // btm row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(BTM_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(BTM_ROW_SENSOR_PIN)) digitalWrite(BTM_ROW_MOTOR_PIN, HIGH);
}
if ((mask & 0b00000111110000) == 0b00000111110000) {  // mid row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(MID_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(MID_ROW_SENSOR_PIN)) digitalWrite(MID_ROW_MOTOR_PIN, HIGH);
}
if ((mask & 0b00000000001111) == 0b00000000001111) {  // top row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(TOP_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(TOP_ROW_SENSOR_PIN)) digitalWrite(TOP_ROW_MOTOR_PIN, HIGH);
}

}

Я пробовал это, но это не не похоже на работу:

void winning_check(uint16_t mask) {
if ((mask & 0b11111000000000) == 0b11111000000000) {  // btm row winning sequence
    last_debounce_time = millis();
    if ((millis() - last_debounce_time) >= DEBOUNCE_DELAY_MS) {
        if ((mask & 0b11111000000000) == 0b11111000000000) {
            digitalWrite(WINNING_SENSOR_PIN, HIGH);
            digitalWrite(BTM_ROW_MOTOR_PIN, LOW);  // =turn on
        }
    }
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(BTM_ROW_SENSOR_PIN)) digitalWrite(BTM_ROW_MOTOR_PIN, HIGH);
}
if ((mask & 0b00000111110000) == 0b00000111110000) {  // mid row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(MID_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(MID_ROW_SENSOR_PIN)) digitalWrite(MID_ROW_MOTOR_PIN, HIGH);
}
if ((mask & 0b00000000001111) == 0b00000000001111) {  // top row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(TOP_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(TOP_ROW_SENSOR_PIN)) digitalWrite(TOP_ROW_MOTOR_PIN, HIGH);
}

}

спасибо заранее.

РЕДАКТИРОВАТЬ

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

О программе Сброс WinningState на LOW, у меня есть функция сброса, которая вызывается, когда игра заканчивается - то есть, когда я сбрасываю WinningState.

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

Еще одна вещь, которая может вызвать это, - то, что всегда вызывается оператор else. Я проверил это в последовательном мониторе, используя Serial.println ().

void winning_check(uint16_t mask) {
if (((mask & 0b11111000000000) == 0b11111000000000 || (mask & 0b00000111110000) == 0b00000111110000 || (mask & 0b00000000001111) == 0b00000000001111) && (winning_state == false)) {
    Serial.println("Win detected");
    winning_state = true;
    last_debounce_time = millis();
}
if ((millis() - last_debounce_time) >= DEBOUNCE_DELAY_MS && (mask & 0b11111000000000) == 0b11111000000000) {  // btm row winning sequence
    Serial.println("btm row win confirmed");
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(BTM_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    Serial.println(".");
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(BTM_ROW_SENSOR_PIN)) digitalWrite(BTM_ROW_MOTOR_PIN, HIGH);
}
if ((millis() - last_debounce_time) >= DEBOUNCE_DELAY_MS && (mask & 0b00000111110000) == 0b00000111110000) {  // mid row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(MID_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(MID_ROW_SENSOR_PIN)) digitalWrite(MID_ROW_MOTOR_PIN, HIGH);
}
if ((millis() - last_debounce_time) >= DEBOUNCE_DELAY_MS && (mask & 0b00000000001111) == 0b00000000001111) {  // top row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(TOP_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(TOP_ROW_SENSOR_PIN)) digitalWrite(TOP_ROW_MOTOR_PIN, HIGH);
}

}

Вот функция, которая вызывает последовательность:

uint16_t get_clowns_state() {
uint16_t clowns_mask = 0;
for (uint16_t i = 0; i < 14; i++) {
    clowns_mask |= (uint16_t)(digitalRead(clowns_pins[i]) << i);
}

return clowns_mask;

}

и внутри l oop (), которую я вызываю: victory_check (get_clowns_state ());

Ответы [ 2 ]

0 голосов
/ 11 апреля 2020

Теперь мне нужно кое-что обновить, так как я гораздо лучше программист, но логика c очень надежная и действительно работает исключительно хорошо. Попробуйте мою eRCaGuy_EventReader библиотеку debounce отсюда: https://github.com/ElectricRCAircraftGuy/eRCaGuy_EventReader.

Вот пример использования. Обратите внимание, что у вас есть несколько вариантов: вы можете действовать на: 1) отклоненное действие / событие (в данный момент состояние изменяется с false на true или с true на false), OR 2) в соответствии с отклоненное состояние . Изучите приведенный ниже пример кода, и я думаю, вы сможете понять разницу.

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

#include <eRCaGuy_EventReader.h>

// 1500ms, or 1.5 sec debounce delay (last state must remain unchanged for this duration or else the
// debounce is not yet considered "complete")
constexpr unsigned int DEBOUNCE_DELAY_MS = 1500; 
constexpr bool EVENT_STATE_WHEN_EVENT_OCCURS = true;

// In this example I create one debouncer. It looks like you will need
// to create several to accomplish what you want. Create one debouncer
// object for each event you'd like to debounce, and follow the pattern
// and usage shown below according to your needs.
eRCaGuy_EventReader debouncer(DEBOUNCE_DELAY_MS, EVENT_STATE_WHEN_EVENT_OCCURS);

void setup()
{

}

void loop()
{
  // Check your masks here
  // ***FILL IN YOUR REAL LOGIC HERE TO CHECK IF THE MASKS ARE THE SAME!***
  bool masks_are_same = true; 

  // Register a new reading
  debouncer.readEvent(masks_are_same);

  // Now get debounced values

  int8_t debounced_action = debouncer.getDebouncedAction();
  switch (debounced_action)
  {
    // No change in the true, debounced event state since last time interpreting the event, or 
    // debounceDelay time not yet elapsed
    case eRCaGuy_EventReader::NO_ACTION:
      // do what you want here
      break;
    // A new event just occurred (debounce delay has elapsed)
    // ie: debounced version of `masks_are_same` has gone from false to true!
    case eRCaGuy_EventReader::ACTION_OCCURRED:
      // do what you want here
      break;
    // A new event just "un-occurred" by going back to its resting state (debounce delay has 
    // elapsed); ie: debounced version of `masks_are_same` has just gone from true back to false!
    case eRCaGuy_EventReader::ACTION_UNOCCURRED:
      // do what you want here
      break;
  }

  // This is the debounced version of `masks_are_same`
  bool masks_are_same_debounced = debouncer.getDebouncedState();
  if (masks_are_same_debounced)
  {
    // do whatever you want if the masks are the same
  }
  else
  {
    // do whatever you want if the masks are different
  }
}
0 голосов
/ 25 марта 2020

Так как вам нужен конечный автомат, он работает следующим образом:

 // Global var place before setup()
bool winningState = false;

void winning_check(uint16_t mask) {
    // We check if a winning state is hit

if ( ( (mask & 0b11111000000000) == 0b11111000000000 // added bracket
|| (mask & 0b00000111110000) == 0b00000111110000 
|| (mask & 0b00000000001111) == 0b00000000001111 ) // added bracket
&& winningState == false) {  // we hit for the first time herebtm row winning sequence
    winningState = true;
    last_debounce_time = millis();
}
    // we hit for the next 1.5 sec time herebtm row winning sequence

    if ((millis() - last_debounce_time) <= DEBOUNCE_DELAY_MS && (mask & 0b11111000000000) == 0b11111000000000) { // inversed logic opposite to yours
            digitalWrite(WINNING_SENSOR_PIN, HIGH);
            digitalWrite(BTM_ROW_MOTOR_PIN, LOW);  // =turn on
        }
    } else {
        winningState = false; // Reset the var
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(BTM_ROW_SENSOR_PIN)) digitalWrite(BTM_ROW_MOTOR_PIN, HIGH);

}
if ((millis() - last_debounce_time) <= DEBOUNCE_DELAY_MS &&(mask & 0b00000111110000) == 0b00000111110000) {  // mid row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(MID_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    winningState = false; // Reset the var
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(MID_ROW_SENSOR_PIN)) digitalWrite(MID_ROW_MOTOR_PIN, HIGH);
}
if ((millis() - last_debounce_time) <= DEBOUNCE_DELAY_MS && (mask & 0b00000000001111) == 0b00000000001111) {  // top row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(TOP_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    winningState = false; // Reset the var
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(TOP_ROW_SENSOR_PIN)) digitalWrite(TOP_ROW_MOTOR_PIN, HIGH);
}

Перед тем, как войти в вашу логи c, мы должны сделать одноразовую настройку таймера и установить переменную, которая не установлена снова, пока dtate не изменился снова. Сделал быструю запись в редакторе, поэтому, если есть какие-либо проблемы с скобками, я могу редактировать, если это необходимо.

Редактировать

Изменены скобки и инвертированные логики отказов c (исключены логи ОП c)

Второе редактирование

Основной вопрос c:
Если то, что произойдет, если произойдет через 1,5 секунды только один раз, тогда используйте эту логику c:

(millis() - last_debounce_time) >= DEBOUNCE_DELAY_MS   // Your logic

, тогда применяется следующий код

 if ((millis() - last_debounce_time) >= DEBOUNCE_DELAY_MS &&(mask & 0b00000111110000) == 0b00000111110000) {  // mid row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(MID_ROW_MOTOR_PIN, LOW);  // =turn on
     winningState = false; // Reset the var
} else {
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(MID_ROW_SENSOR_PIN)) digitalWrite(MID_ROW_MOTOR_PIN, HIGH);
}

или это должно произойти в течение 1,5 секунд, после чего измените состояние:

  (millis() - last_debounce_time) <= DEBOUNCE_DELAY_MS   // "My" logic

, чем применяется этот код:

if ((millis() - last_debounce_time) <= DEBOUNCE_DELAY_MS &&(mask & 0b00000111110000) == 0b00000111110000) {  // mid row winning sequence
    digitalWrite(WINNING_SENSOR_PIN, HIGH);
    digitalWrite(MID_ROW_MOTOR_PIN, LOW);  // =turn on
} else {
    winningState = false; // Reset the var
    // digitalWrite(WINNING_SENSOR_PIN, LOW);
    if (!digitalRead(MID_ROW_SENSOR_PIN)) digitalWrite(MID_ROW_MOTOR_PIN, HIGH);
}

Будет полезно, если вы примените диаграмму состояний следующим образом.

  • Определите состояние (определенную маску)
  • сделайте что-нибудь1 в течение 1500 мс И состояние не изменится
  • остановить что-то1, если состояние меняется и время <1500 мс -> сбросить и вернуть
  • остановить что-то1, если время истекло И состояние не изменилось -> сделать что-то2
...