So I have this (long) code:
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <ezButton.h>
ezButton toggleSwitch(1); // create ezButton object that attach to pin 1;
enum Direction { left,
right,
front,
back };
int enA = 6;
int in1 = 7;
int in2 = 8;
// Motor B
int enB = 3;
int in3 = 4;
int in4 = 5;
int RightUltrasonicEcho = 16;
int RightUltrasonicTrigger = 17;
int LeftUltrasonicEcho = 12;
int LeftUltrasonicTrigger = 11;
int FrontUltrasonicEcho = 14;
int FrontUltrasonicTrigger = 15;
int BackUltrasonicEcho = 13;
int BackUltrasonicTrigger = 2;
int rotation = 0;
Servo FrontServo;
LiquidCrystal_I2C lcd(0x27, 16, 2);
bool CurrentlyMovingForward = false;
bool CurrentlySynchronous = false;
bool Parked = false;
String mode = "Driving";
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
pinMode(RightUltrasonicTrigger, OUTPUT);
pinMode(RightUltrasonicEcho, INPUT);
pinMode(LeftUltrasonicTrigger, OUTPUT);
pinMode(LeftUltrasonicEcho, INPUT);
pinMode(FrontUltrasonicTrigger, OUTPUT);
pinMode(FrontUltrasonicEcho, INPUT);
pinMode(BackUltrasonicTrigger, OUTPUT);
pinMode(BackUltrasonicEcho, INPUT);
FrontServo.attach(9);
FrontServo.write(90);
FrontServo.write(90);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print("Welcome");
delay(3000);
lcd.clear();
PrintBoilerplateToLCD();
//ScoutForOpeningsToParkIn();
toggleSwitch.setDebounceTime(50); // set debounce time to 50 milliseconds
}
// Utils
void PrintBoilerplateToLCD() {
lcd.setCursor(0, 0);
lcd.print("Mode:");
lcd.setCursor(6, 0);
lcd.print(mode);
}
void FloatDelay(float ms) {
unsigned long whole = ms;
int part = (ms - static_cast<int>(ms)) * 1000;
delay(whole);
if (part > 4) delayMicroseconds(part);
}
void LcdDebug(String text) {
lcd.setCursor(0, 1);
lcd.print(text);
}
void Button() {
toggleSwitch.loop();
if (toggleSwitch.isPressed() && mode == "Driving") {
mode = "Parking";
lcd.clear();
PrintBoilerplateToLCD();
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
CurrentlySynchronous = false;
return;
}
if (toggleSwitch.isPressed() && mode == "Parking") {
mode = "Following";
lcd.clear();
PrintBoilerplateToLCD();
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
CurrentlySynchronous = false;
return;
}
if (toggleSwitch.isPressed() && mode == "Following") {
mode = "Driving";
lcd.clear();
PrintBoilerplateToLCD();
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
CurrentlySynchronous = false;
return;
}
}
}
// Ultrasonic related
float ReadFromUltrasonicSensor(Direction direction) {
int echo;
int trigger;
if (direction == right) {
echo = RightUltrasonicEcho;
trigger = RightUltrasonicTrigger;
} else if (direction == left) {
echo = LeftUltrasonicEcho;
trigger = LeftUltrasonicTrigger;
} else if (direction == front) {
echo = FrontUltrasonicEcho;
trigger = FrontUltrasonicTrigger;
} else if (direction == back) {
echo = BackUltrasonicEcho;
trigger = BackUltrasonicTrigger;
}
digitalWrite(trigger, LOW);
delay(2);
digitalWrite(trigger, HIGH);
delay(10);
digitalWrite(trigger, LOW);
float timing = pulseIn(echo, HIGH);
float distance = (timing * 0.0343) / 2;
return distance;
}
// Car related
void MoveForwardTillObjectDetection(int speed, int time, float distance, Direction direction) {
unsigned long originalTime = millis();
CurrentlySynchronous = true;
// Stops proceeding if the speed is an invalid value
if (speed >= 256 || speed <= 0) {
CurrentlySynchronous = false;
return;
}
if (ReadFromUltrasonicSensor(direction) <= distance && ReadFromUltrasonicSensor(direction) >= 3) {
CurrentlySynchronous = false;
return;
}
// This function will run the motors in both directions at a variable speed and for a variable time.
// Turn on motor A.
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set motor A speed.
analogWrite(enA, speed - 30);
// Turn on motor B.
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Set motor B speed.
analogWrite(enB, speed);
// Wait the specified time in miliseconds.
for (unsigned long timer = 0; timer <= originalTime + time; timer = millis()) {
Button();
if (ReadFromUltrasonicSensor(direction) <= distance && ReadFromUltrasonicSensor(direction) >= 3) {
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
CurrentlySynchronous = false;
return;
}
}
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
CurrentlySynchronous = false;
}
void MoveBack() {
// Turn on motor A
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// Set speed to 200 out of possible range 0~255
analogWrite(enA, 200);
// Turn on motor B
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// Set speed to 200 out of possible range 0~255
analogWrite(enB, 200);
}
void MoveRight() {
// Turn on motor A
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enA, 200);
// Turn on motor B
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enB, 200);
}
void MoveLeft() {
// Turn on motor A
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enA, 200);
// Turn on motor B
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enB, 200);
}
void MoveForward() {
// Turn on motor
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enA, 170);
// Turn on motor B
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enB, 200);
}
void Stop() {
// Now turn off motors
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}
//Best accuracy is using this function in intervals of *under 90 degrees*.
void TurnCar(int degrees) {
rotation += degrees;
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
analogWrite(enA, 170);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(enB, 200);
FloatDelay(degrees * 5);
//FloatDelay(float(degrees) * 6);
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}
//Servo-related
String ScoutForObjectsWithServo() {
FrontServo.write(0);
delay(1000);
float DistanceToRight = ReadFromUltrasonicSensor(front);
FrontServo.write(180);
delay(1000);
float DistanceToLeft = ReadFromUltrasonicSensor(front);
FrontServo.write(90);
delay(1000);
if (DistanceToRight >= DistanceToLeft) {
return "right";
}
return "left";
}
void ScoutForOpeningsToParkIn(Direction direction) {
unsigned long originalTime = millis();
int OriginalDistanceLeft = ReadFromUltrasonicSensor(left);
int OriginalDistanceRight = ReadFromUltrasonicSensor(right);
int DistanceLeft = ReadFromUltrasonicSensor(left);
int DistanceRight = ReadFromUltrasonicSensor(right);
MoveForward();
for (unsigned long timer = 0; timer <= originalTime + 10000; timer = millis()) {
DistanceLeft = ReadFromUltrasonicSensor(left);
DistanceRight = ReadFromUltrasonicSensor(right);
if (direction == right && DistanceRight <= 50) {
OriginalDistanceRight = DistanceRight;
}
if (direction == left && DistanceLeft <= 50) {
OriginalDistanceLeft = DistanceLeft;
}
if (direction == right && DistanceRight - OriginalDistanceRight >= 30 || direction == right && DistanceRight <= 3) {
Stop();
StartParking(left, true);
return;
}
if (direction == left && DistanceLeft - OriginalDistanceLeft >= 30 || direction == left && DistanceLeft <= 3) {
Stop();
StartParking(right, true);
return;
}
DistanceLeft = ReadFromUltrasonicSensor(left);
DistanceRight = ReadFromUltrasonicSensor(right);
}
Stop();
}
void loop()
{
Button();
LcdDebug("drive");
if (mode == "Driving") { MoveForwardSmartly(); }
LcdDebug("park");
if (mode == "Parking" && Parked == false) {Parked = true; ScoutForOpeningsToParkIn(left); }
LcdDebug("follow");
if (mode == "Following") { ActLikeADoggy(right); }
}
// Main Code
void MoveForwardSmartly() {
LcdDebug("smartly");
CurrentlyMovingForward = true;
MoveForwardTillObjectDetection(200, 10000, 10.0, front);
if (mode != "Driving") { return; }
String DirectionResult = ScoutForObjectsWithServo();
if (DirectionResult == "right") {
TurnCar(90);
} else {
TurnCar(90);
delay(300);
TurnCar(90);
delay(300);
TurnCar(90);
delay(300);
}
if (mode != "Driving") { return; }
CurrentlyMovingForward = false;
}
void StartParking(Direction direction, bool vertical) {
if (direction == right & !vertical) {
// 2 iters
MoveRight();
delay(1000);
Stop();
MoveLeft();
delay(1000);
Stop();
MoveRight();
delay(1000);
Stop();
MoveLeft();
delay(8000);
Stop();
} else if (direction == left && !vertical) {
MoveLeft();
delay(1000);
Stop();
MoveRight();
delay(1000);
Stop();
MoveLeft();
delay(1000);
Stop();
MoveRight();
delay(1000);
Stop();
} else if (direction == right && vertical) {
MoveRight();
delay(1100);
Stop();
MoveForward();
delay(300);
} else if (direction == left && vertical) {
MoveLeft();
delay(1100);
MoveForward();
delay(300);
Stop();
}
Parked = true;
if (vertical = false) {
for (int FrontDistance = 0; FrontDistance <= ReadFromUltrasonicSensor(back); FrontDistance = ReadFromUltrasonicSensor(front)) {
MoveBack();
delay(50);
Stop();
}
}
}
void ActLikeADoggy(Direction direction) {
while (mode = "Following") {
Button();
while (ReadFromUltrasonicSensor(direction) > 15) {
switch (direction) {
case left:
MoveLeft();
break;
case right:
MoveRight();
break;
}
}
Stop();
while (ReadFromUltrasonicSensor(direction) < 10) {
switch (direction) {
case right:
MoveLeft();
break;
case left:
MoveRight();
break;
}
Stop();
while (ReadFromUltrasonicSensor(direction) > 10 && ReadFromUltrasonicSensor(direction) < 15) {
MoveForward();
}
Stop();
}
}
}
// Unit tests
// All motors should spin
void Test() {
// This function will run the motors in both directions at a fixed speed
// Turn on motor A
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enA, 200);
// Turn on motor B
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Set speed to 200 out of possible range 0~255
analogWrite(enB, 200);
delay(2000);
// Now change motor directions
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
delay(2000);
// Now turn off motors
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}
I have an lcd print line in loop, but the problem is, it seems the if condition before them are taking very long times to finish, despite simply being false.
While this doesn't affect the end result I do plan to showcase it to other people (this is for a school project), and having it take around 3 seconds to start up after pressing the button and switching it into another mode (via ezButton) would not be very ideal