Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# KDE
.directory

# Personal files
TODO.txt

# VSCode configuration files
.vscode/

# Compiled files
build/
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# arduino-robot-car
Repository for a 4-wheel robot car based on Arduino for the "Elegoo Smart Robot Car Kit V3.0 Plus" and similar ones.
Source code to control a 4-wheel robot car based on Arduino Uno. The code has been tested for the "Elegoo Smart Robot Car Kit V3.0 Plus", but can be easily adatped for other similar ones.

## Requirements
The robot consists of a 4 DC motors driven by a H-Bridge with dual output, connecting the two left wheels and the two right ones to its outputs. The car is remotely controlled either by Bluetooth, through the Elegoo Tool app, or by infrared. An ultrasonic sensor attached to a servo motor measures the front distance to objects. A line tracking sensor on the base, with 3 pairs of LED + photoresistors, allows to follow a line drawn on the floor.
Some functionalities have been added in the software to the official Elegoo release.

## Requirements
Apart from the standard Arduino libraries, some other ones must be installed:
- ArduinoJson: https://arduinojson.org
- IRRemote: https://github.com/z3t0/Arduino-IRremote
- Servo: https://www.arduino.cc/reference/en/libraries/servo/

## Installation

1. Install the required libraries.
2. Download the repository and flash the Arduino. For VSCode, modify the includePath to use the downloaded libraries; if using the Arduino IDE, change the name of the src folder to something appropriate.

## Usage

The oficial Elegoo Tool application for Android must be downloaded to interact with the robot. Nevertheless, changing the initial robot mode will allow you to use it without the app.

## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Expand Down
61 changes: 61 additions & 0 deletions src/IRreceiver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @file IRreceiver.cpp
* @author José Ángel Sánchez (https://github.com/gelanchez)
* @brief Library for receiving data from the IR sensor.
* @version 1.0.0
* @date 2020-08-22
* @copyright GPL-3.0
*/

#include "constants.h"
#include "IRreceiver.h"

IRreceiver::IRreceiver(): m_irrecv{ Constants::IRPin }, m_isEnabled{ false },
m_previousKey{ 0xFFFFFFFF } // Member initializer lists; it can't go inside the constructor
{
}

IRreceiver::~IRreceiver()
{
}

void IRreceiver::enable()
{
if (!m_isEnabled)
{
m_irrecv.enableIRIn();
m_irrecv.blink13(false); // Disable blinking the LED 13 during reception
m_isEnabled = true;
}
}

RemoteOrder IRreceiver::decodeIR()
{
if (m_irrecv.decode(&m_results))
{
unsigned long pressedKey = m_results.value;
m_irrecv.resume();

if (pressedKey == 0xFFFFFFFF) // Repeat previous key
pressedKey = m_previousKey;
else
m_previousKey = pressedKey; // Update previous key to current key

switch (pressedKey)
{
case Constants::okKey:
return RemoteOrder::STOP;
case Constants::upKey:
return RemoteOrder::FORWARD;
case Constants::downKey:
return RemoteOrder::BACKWARD;
case Constants::leftKey:
return RemoteOrder::ROTATELEFT;
case Constants::rightKey:
return RemoteOrder::ROTATERIGHT;
default:
return RemoteOrder::UNKNOWN;
}
}
return RemoteOrder::UNKNOWN;
}
37 changes: 37 additions & 0 deletions src/IRreceiver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @file IRreceiver.h
* @author José Ángel Sánchez (https://github.com/gelanchez)
* @brief Library for receiving data from the IR sensor.
* @version 1.0.0
* @date 2020-08-22
* @copyright GPL-3.0
*/

#ifndef IRRECEIVER_H
#define IRRECEIVER_H

// To avoid using old versions of Arduino IDE, which used WPProgram.h instead or Arduino.h
// Also possible #define IRPRONTO
#ifndef ARDUINO
#define ARDUINO 108012 // Arduino IDE version used when writing the program
#endif

#include "constants.h"
#include <IRremote.h>

class IRreceiver
{
private:
IRrecv m_irrecv; // Receiver object
bool m_isEnabled;
decode_results m_results; // Struct to store the received information
unsigned long m_previousKey; // Store previous order for repeating key

public:
IRreceiver();
~IRreceiver();
void enable();
RemoteOrder decodeIR();
};

#endif
11 changes: 11 additions & 0 deletions src/constants.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @file constants.cpp
* @author José Ángel Sánchez (https://github.com/gelanchez)
* @brief Constants used along the program.
* This file is only used because if not, program doesn't compile (it can't find constants.h)
* @version 1.0.0
* @date 2020-08-22
* @copyright GPL-3.0
*/

#include "constants.h" // A code file should #include its paired header file (if it exists)
119 changes: 119 additions & 0 deletions src/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* @file constants.h
* @author José Ángel Sánchez (https://github.com/gelanchez)
* @brief Constants used along the program
* @version 1.0.0
* @date 2020-08-22
* @copyright GPL-3.0
*/

#ifndef CONSTANTS_H
#define CONSTANTS_H

#include <Arduino.h>

namespace Constants
{
// MOTORS
// Right motors pins
const uint8_t motorsEnA(6);
const uint8_t motorsIn1(11);
const uint8_t motorsIn2(9);
// Left motors pins
const uint8_t motorsEnB(5);
const uint8_t motorsIn3(8);
const uint8_t motorsIn4(7);
// Motors min speed (measured)
const uint8_t crankSpeed(140); // Around 120 @ full battery
const uint8_t idleSpeed(90);

// DEFAULT speeds
const uint8_t moveSpeed(170);
const uint8_t rotateSpeed(150);
const uint16_t rotate90Time(650); // Time to rotate 90deg @ moveSpeed @ full battery
const uint16_t rotate180Time(1200); // Time to rotate 180deg @ rotateSpeed @ full battery

// OBSTACLEAVOIDANCE constants
const uint16_t updateInterval(250); // Default update time for states
const uint16_t minDistance(30);

// LINETRACKING constants
const uint8_t ltLeftPin(2);
const uint8_t ltMidPin(4);
const uint8_t ltRightPin(10);
const uint16_t minDetourDistance(10); // Distance to keep with the obstacle
const uint16_t updateUltrasonicInterval(20);
const uint16_t extraTime(100); // Extra time to keep moving the robot to pass the object
const uint16_t extraTimeLine(50); // Extra time to pass the line
const uint16_t timeUntilLost(1000); // Wait time until LOSTLINE and turn back
const uint16_t timeLost(5000); // Time lost to find a new line
const uint8_t marginObject(1); // Margin +- distance to the object

// PARK mode constants
const uint16_t timeMoving(500);
const uint16_t timeMoveAway(150);

// SERVO
// Servo pin
const uint8_t servoPin(3);
// 0deg and 180deg PWM positions
const uint16_t servo0(500); // Calibration 450, default 544
const uint16_t servo180(2400); // Calibration 2430, default 2400

// ULTRASONIC SENSOR
const uint8_t trigPin(A5); // Pin 19
const uint8_t echoPin(A4); // Pin 18
const float soundSpeed(0.0343); // cm/s
const uint16_t maxDistance(250); // Maximun distance to meassure in cm
const uint16_t maxDistanceLineTracking(100); // Maximun distance to meassure in cm to be used in the linetraking mode

// IRCONTROL constants
const uint8_t IRPin(12);
const unsigned long okKey(0xFF02FD);
const unsigned long upKey(0xFF629D);
const unsigned long downKey(0xFFA857);
const unsigned long leftKey(0xFF22DD);
const unsigned long rightKey(0xFFC23D);
const uint16_t IRMovingInterval(500); // Default time for moving in IR
}

/**
* @brief Different modes for the robot
*/
enum class RobotMode
{
REMOTECONTROL,
IRCONTROL,
OBSTACLEAVOIDANCE,
LINETRACKING,
PARK,
CUSTOM,
};

/**
* @brief Orders for the RemoteControl and IRControl modes
*/
enum class RemoteOrder
{
STOP,
FORWARD,
BACKWARD,
ROTATELEFT,
ROTATERIGHT,
UNKNOWN,
};

/**
* @brief States for the different Robotmode
*/
enum class RobotModeState
{
START,
FORWARD,
OBSTACLE,
ROTATE,
BLOCKED,
LINELOST, // Only used in linetracking
};

#endif
57 changes: 57 additions & 0 deletions src/linetracking.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @file linetracking.cpp
* @author José Ángel Sánchez (https://github.com/gelanchez)
* @brief Library to handle the linketracking sensors.
* @version 1.0.0
* @date 2020-08-22
* @copyright GPL-3.0
*/

#include "constants.h"
#include "linetracking.h"

LineTracking::LineTracking()
{
pinMode(Constants::ltLeftPin, INPUT);
pinMode(Constants::ltMidPin, INPUT);
pinMode(Constants::ltRightPin, INPUT);
}

LineTracking::~LineTracking()
{
}

bool LineTracking::leftLine()
{
return !digitalRead(Constants::ltLeftPin);
}

bool LineTracking::midLine()
{
return !digitalRead(Constants::ltMidPin);
}

bool LineTracking::rightLine()
{
return !digitalRead(Constants::ltRightPin);
}

bool LineTracking::anyLine()
{
return (leftLine() || midLine() || rightLine());
}

bool LineTracking::allLines()
{
return (leftLine() && midLine() && rightLine());
}

void LineTracking::printLines()
{
Serial.print(leftLine());
Serial.print(" ");
Serial.print(midLine());
Serial.print(" ");
Serial.print(rightLine());
Serial.println();
}
29 changes: 29 additions & 0 deletions src/linetracking.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @file linetracking.h
* @author José Ángel Sánchez (https://github.com/gelanchez)
* @brief Library to handle the linketracking sensors.
* @version 1.0.0
* @date 2020-08-22
* @copyright GPL-3.0
*/

#ifndef LINETRACKING_H
#define LINETRACKING_H

class LineTracking
{
private:

public:
LineTracking();
~LineTracking();
bool leftLine();
bool midLine();
bool rightLine();
bool anyLine();
bool allLines();
void printLines();
};


#endif
Loading