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();
}
}
}
1 Answer 1
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.
-
Thank you! This definitely helps a lot!Renier Jr.– Renier Jr.2023年07月08日 13:05:42 +00:00Commented Jul 8, 2023 at 13:05
Explore related questions
See similar questions with these tags.
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.