Функции, задерживающие распознавание датчика жестов

programming time oled delay seeeduino-xiao

Я работаю над простым маленьким роботом, который избавит меня от скуки, и все, что у него есть, — это OLED-дисплей 64 x 32 для глаз и датчик распознавания жестов PAJ7620 с Seeeduino Xiao в качестве основной платы.

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

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

Что я могу сделать, чтобы это исправить? Может кто-нибудь помочь или дать совет, как мне улучшить свой код?

    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <Wire.h>
    #include <DFRobot_PAJ7620U2.h>

    int like_score = 3;//Оцените, насколько вы нравитесь боту: это повлияет на то, какие пустоты будут использоваться.
    int max_like_score = 17;
    char buffer[9];

    unsigned long previousMillis = 0;
    const long interval = 1000;

    DFRobot_PAJ7620U2 paj;

    U8G2_SSD1306_64X32_1F_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
    
    // шрифты https://github.com/olikraus/u8g2/wiki/fntlistall#4-pixel-height
    void setup(void) {
      u8g2.begin();
      Serial.begin(115200);
      delay(300);
      u8g2.clearBuffer();
      Serial.println("Gesture recognition system base on PAJ7620U2");
      while (paj.begin() != 0) {
        Serial.println("initial PAJ7620U2 failure! Please check if all the connections are fine, or if the wire sequence is correct?");
        delay(500);
      }
      Serial.println("PAJ7620U2 init completed, start to test the gesture recognition function");
      paj.setGestureHighRate(true);
    }

    void normalL() {       //нормальное прямое выражение
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, normal);
      u8g2.sendBuffer();
    }
    void blinkL() {        //мигает
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, blink);
      u8g2.sendBuffer();
    }
    void left() {          //смотрит влево
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, blinkleft);
      u8g2.sendBuffer();
    }
    void right() {         //выглядит правильно
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, blinkright);
      u8g2.sendBuffer();
    }
    void angryL() {        //злой
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, angry);
      u8g2.sendBuffer();
    }
    void loveL() {         //влюблен
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, love);
      u8g2.sendBuffer();
    }
    void sleepL() {        //спящий
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, sleep);
      u8g2.sendBuffer();
    }
    void susL() {          //подозрительно
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, sus);
      u8g2.sendBuffer();
    }
    void stunL() {         //выглядит ошеломленным
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, stun);
      u8g2.sendBuffer();
    }
    void upL() {           // Смотрим вверх
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, up);
      u8g2.sendBuffer();
    }
    void gleeL() {
      u8g2.clearBuffer();  // очищаем внутреннюю память
      u8g2.drawBitmap(0, 0, 8, 32, glee);
      u8g2.sendBuffer();
    }
    void randomEx() {
      int rand = random(1, 8);
      if (rand == 1) {
        normalL();
      } else if (rand == 2) {
        left();
      } else if (rand == 3) {
        right();
      } else if (rand == 4) {
        angryL();
      } else if (rand == 5) {
        loveL();
      } else if (rand == 6) {
        susL();
      } else if (rand == 7) {
        upL();
      } else if (rand == 8) {
        gleeL();
      }
    }

    void likeRoutine() {
      normalL();
      delay(random(1000, 6500));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(2500, 4000));
      blinkL();
      delay(90);
    }
    void kindofLikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void dislikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void hateRoutine() {
      angryL();
      delay(random(1000, 5000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }

    void loop(void) {
      DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture();
      if (gesture != paj.eGestureNone) {
        String description = paj.gestureDescription(gesture);  //Преобразуем номер жеста в строковое описание
        if (gesture == 256) {                                  //волна
          gleeL();
          delay(random(1000, 4500));
        } else if (gesture == 2 && like_score < max_like_score) {  // домашнее животное
          blinkL();
          delay(90);
          loveL();
          like_score++;
          Serial.println(like_score);
          delay(random(1000, 3000));
          if (like_score == max_like_score) {
            blinkL();
            delay(90);
            loveL();
            delay(random(1000, 3000));
          }
        } else if (gesture == 16 && like_score <= max_like_score) {  //thump
          stunL();
          like_score--;
          Serial.println(like_score);
          delay(random(1000, 4000));
          angryL();
          delay(random(1000, 3000));
        } else if (gesture == 128) {
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_t0_11_tf);  // выбираем подходящий шрифт
          dtostrf(like_score, 6, 0, buffer);
          String scoreStr = String(buffer);
          u8g2.drawStr(0, 20, scoreStr.c_str());
          u8g2.sendBuffer();
          delay(random(2000, 3500));
        }
      } else {
        if (like_score >= 11) {
          likeRoutine();
        } else if (like_score > 7 && like_score < 11) {
          kindofLikeRoutine();
        } else if (like_score > 0 && like_score < 7) {
          dislikeRoutine();
        } else if (like_score < 0) {
          hateRoutine();
        }
      }
    }

, 👍2

Обсуждение

Да спасибо., @Renier Jr.

Спасибо, я сделаю это., @Renier Jr.

@jsotola Это было очень похоже на ответ на вопрос, а не на просьбу уточнить информацию. Не могли бы вы превратить это в ответ? Подсказка: вырезать и вставить должно работать. Спасибо!, @Nick Gammon

*Мой код очень неэффективен из-за всех функций...* — совсем нет. Использование функций для обеспечения читаемости кода очень распространено, а замедление минимально., @Nick Gammon

@jsotola Я просто прошу, чтобы ваш разумный комментарий об использовании delay() был включен в ответ, а не в комментарий. Однако, если вы хотите, предоставьте больше кода, но я просил не об этом., @Nick Gammon


1 ответ


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

3

Функция delay() замедляет выполнение кода, поскольку это функция блокирующая.

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

Самым простым решением для вашего кода может быть библиотека FSM (конечный автомат). Он будет следить за вашим временем.

Вы также можете заменить функции delay() своей собственной функцией задержки, например


void myDelay(int totalDelay) {

   for (i = 0; i < totalDelay/100; i++) {

                           // делаем здесь некоторые хозяйственные работы, например, считываем данные с датчиков

      delay(100);          // это блокируется только на 1/10 секунды
   }                       // корректируем значение задержки, если уборка занимает много времени
}

Задержка разбивается на множество мелких задержек, между которыми есть время заняться другими делами.

Другой способ — проверить в начале loop(), сколько времени прошло. См. пример кодаblinkWithoutDelay в Arduino IDE.

Вот пример в симуляторе, который может вам помочь.

https://wokwi.com/projects/362275278547275777

,

Спасибо! Это определенно очень помогает!, @Renier Jr.