2

I am working on a simple little robot to cure my boredom and all it has is a 64 x 32 OLED for the eyes, and a PAJ7620 Gesture recognition sensor with a Seeeduino Xiao as the main board.

Basically, when people swipe above the head where the sensor is, the robot will show the heart eyes. There are different reactions for different actions and all this is controlled through functions. When the sensor does not detect anything, the robot is supposed to cycle through a certain void which is determined based on how much it 'likes' the person.

Right now though, it just cycles through the function and does not respond to the sensor. My code is very inefficient because of all the functions, but it makes it more readable and more easily editable. With all my functions, the gesture sensor takes too long to respond to the actions.

What can I do to fix this? Can someone please help or give advice on how I can improve my code?

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

    int like_score = 3;//Score for how much the bot likes you: this will impact which voids are used.
    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);
    
    // fonts 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() {       //normal forward expression
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, normal);
      u8g2.sendBuffer();
    }
    void blinkL() {        //blinks
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blink);
      u8g2.sendBuffer();
    }
    void left() {          //looks left
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkleft);
      u8g2.sendBuffer();
    }
    void right() {         //looks right
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkright);
      u8g2.sendBuffer();
    }
    void angryL() {        //angry
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, angry);
      u8g2.sendBuffer();
    }
    void loveL() {         //in love
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, love);
      u8g2.sendBuffer();
    }
    void sleepL() {        //sleeping
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sleep);
      u8g2.sendBuffer();
    }
    void susL() {          //suspicious
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sus);
      u8g2.sendBuffer();
    }
    void stunL() {         //looks stunned
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, stun);
      u8g2.sendBuffer();
    }
    void upL() {           //Looks up
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, up);
      u8g2.sendBuffer();
    }
    void gleeL() {
      u8g2.clearBuffer();  // clear the internal memory
      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);  //Convert gesture number into     string description
        if (gesture == 256) {                                  //wave
          gleeL();
          delay(random(1000, 4500));
        } else if (gesture == 2 && like_score < max_like_score) {  //pet
          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);  // choose a suitable font
          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();
        }
      }
    }
5
  • Yes, thank you.
    – Renier Jr.
    Commented Jul 7, 2023 at 15:29
  • Thank you, I will do that.
    – Renier Jr.
    Commented Jul 7, 2023 at 15:41
  • @jsotola That looked very much like an answer to the question, not a request for clarifying information. Could you please turn it into an answer? Hint: cut and paste should work. Thanks!
    – Nick Gammon
    Commented Jul 8, 2023 at 6:22
  • My code is very inefficient because of all the functions ... - not at all. Using functions to make code readable is very common, and the slowdown is minimal.
    – Nick Gammon
    Commented Jul 8, 2023 at 6:23
  • @jsotola I'm just asking that your reasonable comment about using delay() be incorporated into an answer and not a comment. However if you wish provide more code, but that wasn't what I was requesting.
    – Nick Gammon
    Commented Jul 8, 2023 at 7:27

1 Answer 1

3

The code is being slowed down by the delay() function because it is a blocking function.

The delay function does not exit until delay time passes, so no other functions can run, such as sensor reading.

The simplest solution for your code may be an FSM library (finite state machine). It would look after all of the timing for you.

You could also replace the delay() functions with your own delay function, something like


void myDelay(int totalDelay) {

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

                           // do some housekeeping here, like reading sensors

      delay(100);          // this blocks for only 1/10 of a second
   }                       // adjust the delay value if housekeeping takes a lot of time
}

The delay gets broken into a lot of small delays with time to do other things in between.

Another way is to check at the begining of loop() to see how much time has elapsed. See blinkWithoutDelay example code in the Arduino IDE.

Here is an example in a simulator that may help you.

https://wokwi.com/projects/362275278547275777

1
  • Thank you! This definitely helps a lot!
    – Renier Jr.
    Commented Jul 8, 2023 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.