Arduino Quadcopter Controlled by Gloves
by PernPops in Circuits > Arduino
104 Views, 1 Favorites, 0 Comments
Arduino Quadcopter Controlled by Gloves
For an electronics project, our group was tasked with making our own electronic device using the knowledge we learned throughout the course. So, we decided to create a quadcopter that is controlled by a pair of gloves. It should be known that this project is still a work in progress and does not perform to the full stated functionality yet. This instructable will be updated once it has achieved full operational ability. In this current state, we would like to provide a warning that the operation of a homemade drone can lead to damage to yourself, others, or property, and please take the proper precautions when working on a project such as this.
This project consists of a small, Arduino-controlled flight drone controlled by wearable tech (a pair of gloves with IMU and pressure sensors). The drone itself holds an Arduino, a LiPO battery, four motors, and four propellers, and an inertial measurement unit to supply acceleration and gyroscopic data. It includes auto-stabilizing installed software as well. This drone receives commands transponded through radio from a computer, which is the center of the functioning of the system. The computer takes in code from the glove (connected via HDMI) and transmits it to the drone (via radio). The glove collects and transmits gyroscopic, yaw, pitch, and roll data to the computer, which converts that to commands sent to the drone. With all parts functioning properly, the drone will mimic the rotation/direction/motion of your hand.
Many of the images are grouped together and will be referenced as image (#) throughout the steps.
Supplies
The supplies we used for this build are below:
For the drone-
Drone Base(Either purchased online or 3D printed)
- We used this drone body
Arduino Uno
4x 20A Electronic Speed Controllers
- We used these ESCs
4x 5 Inch 3 Blade Propellers, 2 CW, 2 CCW
- We used these propellers
4x 3S Brushless Motors, 2 CW, 2 CCW
- We used these motors
MPU 6050 Inertial Measurement Unit
2x REYAX RYLR998 UART Interface 868/915 MHz Lora Module
3S 2200 maH LiPo Battery
- LiPo batteries take a specific charger that we did not have, so we also purchased a LiPo battery charger
- The LiPo battery we purchased used a T connector to provide the main power, so we purchased T connector adapters to run current from the batteries
- We used these batteries
- We used this battery charger
General Circuitry Tools and Supplies
- Solder and Soldering Iron
- Electrical Tape
- Switch
- Wire Connectors
- Low and High Current Wire
For the gloves-
Arduino Uno
Pair of Mesh Gloves
Fingertip-sized Pressure Sensor
MPU 6050 Inertial Measurement Unit
5x 10k resistors (3 on the ground-based Arduino and 2 on the drone)
1 Breadboard
1 Parallel Splitter
Arduino-to-computer connector
Testing of Motors
This step is optional but recommended. We were brand new to working with brushless electronic motors, so we needed to test with one before we could work with all four motors. We recommend reading this tutorial before continuing if you are unfamiliar with ESCs and brushless motors.
This step should be replicated with all four motors in a parallel circuit in order to have the drone operate.
Motor startup process: Before connecting the battery, turn the motors to the upper limit of motor rotational speed (on a scale from 0 - 180 for these motors). Connect the battery to the circuit while the motors are in their high mode. You will hear a series of beeps from the ESCs of each motor. Once the beeps have finished (~5 seconds), decrease the value of the motor's rotational speed to 0. This is the lower limit of the motors. You will once again hear a series of beeps. Once these beeps are finished, the ESC will be calibrated. This means the motors will begin to respond to the values you input for the rotational speed of the motors. On a scale of 0 - 180, we recommend testing your motors at a speed of 60-80. This will not provide enough thrust to lift the drone but will give you a good understanding of whether or not your motors are responding as they should. Then, slowly increase the value to a max of 150. We chose the max value as 150 so that we allow motors a difference of 30 for motors to increase their speed to change the orientation of the drone. But the average thrust should be around 150 - 160. You will need to experimentally test out what thrust will be the average equilibrium thrust that will levitate the drone.
- Demonstrate that a single motor can be variably operated using an Arduino, a power supply, and a 10k resistor potentiometer:
- Attach brushless motor to brushless electronic speed controller (ESC).
- Using a mini female banana connector, connect the three wires coming out of the motor to the three input slots in the ESC. The order does not matter, but note that in order to switch the direction of the rotation of the motor, you can swap any two wires between the motor and the ESC.
- Connect the ESC to a voltage supply.
- Attach the positive and negative inputs of the ESC to the positive and negative ports on a voltage supply.
- Connect the ESC signal port to the Arduino Mega (we used a Mega during testing, but the Uno works the exact same).
- The ESC signal wires are the twisting black and white wires that connect to a female port with three slots. Connect the black side of the port to the ground, and the white side of the port to PWM port 9 (or any PWM port of your choosing, but make sure to change your Arduino code to match that) on the Arduino. The middle slot of the port will not be used.
- Connect a 10k resistor pot to the Arduino.
- There will be three wires coming out of the pot. The outermost wires should connect to GND and 5V ports. The middle wire should connect to the analog A0 port (or any analog port of your choosing). This pot will serve the purpose of adjusting the speeds of the motors before relying on a program.
- Download the code
- Connect your computer to the Arduino and use the code attached to this part in your Arduino software.
- Run the experiment
- Make sure to set your power supply to 11.1V (as that is the voltage of the battery we will use in our drone).
- Set your motor to the highest potential difference value supplied to the motors using the potentiometer. This will set the upper limit of the motor speed values and will “calibrate” the ESC (the motor will not run when you connect the battery).
- Connect the voltage supply and run the code through the Arduino with the potentiometer set at its highest limit. You will hear a series of beeps. Wait for these beeps to finish, then set your potentiometer to the lowest limit. You will hear another series of beeps. Once these beeps are done, the ESCs will be calibrated and you can begin to increase your pot values to increase the speed of the motor.
Downloads
Drone Assembly
We assembled the drone base according to the instructions that came with our drone body kit, however, this can apply to any chosen drone body as well. For all other components, wire according to the circuit diagram above and secure onto the drone body. Make sure to keep any wires and components out of the way of the propellers and tucked into the drone body.
Software Overview
Warning: The operation of a homemade drone can lead to serious injury or property damage. Software flaws may be the cause or a contributing factor in such incidents. The code provided and detailed here does not cause the drone to operate in a completely safe or risk-free manner. The code provided here may also contain errors that allow undesired/unanticipated behavior and not all edge cases have been thoroughly tested. Use at your own risk. Make sure you understand the code and this warning before operation.
Reading code is always preferable to reading about code. If descriptions of the code contained here differ from the code itself, defer to the code. The below is provided as a collection of helpful notes, but the ground truth is the code and reading it will almost certainly be helpful in understanding its operation.
Software Objectives
Key pieces:
- the drone needs to know its orientation - achieved
- the drone needs to initialize properly - achieved
- the drone needs to control itself in flight - mostly achieved
- the drone needs to take orientation instructions wirelessly - not yet achieved
Nice to have:
- the drone should output data about its status - achieved
- the drone should use a standardized communication protocol - achieved
- our tools should help us assess and tune the drone’s performance - achieved
Code Availability
The code referenced in the following sections can be found at
https://github.com/sagesanto/electronics_drone/.
Read the license.
Software Architecture
The drone carries an onboard Arduino UNO that is responsible for reading orientation data, setting motor speeds, and communicating with the ground. To help with this, the drone carries four electronic speed controllers (ESCs) and one MPU DMP6050 (an integrated gyroscope and accelerometer unit). We use the MPU as the input to our flight stabilization system, and the ESCs as our output.
The drone talks to the laptop by serial (USB) during testing and development. Over USB, the laptop sends initialization commands and receives flight data, which it displays to the user during development.
Also attached to the laptop by USB is an Arduino UNO that runs the glove-mounted MPU and pressure sensor. The Arduino sends orientation and pressure data over the radio to the drone, and debugging information over USB to the laptop.
This is visualized in the above image.
Drone Software
Initialization (drone_control.ino)
To initialize the drone, we need to initialize the MPU, attach the ESCs to their respective motors, initialize them by supplying a sequence of power levels, and set up the PID controller.
You can read more about MPU initialization in the MPU and Orientation section.
ESCs
We set up the ESCs by creating Servo objects and attaching them to their proper ports (image 1):
Then, we initialize them in the following way:
- With the battery unplugged, set the ESC to full power (180). This will not do anything yet - the batteries are not plugged in.
- Simultaneously plug in the battery and start the following initialization sequence by sending a character over the serial
- Hold the ESCs at their future high point for 3 seconds
- Hold the ESCs at their future low point for 10 seconds
The ESCs should sing a little song throughout this process. The motors may twitch but should not begin to spin during this sequence.
After this is done, the ESCs will know their high and low points(image 2).
PID
The PID controller relies on the ArduPID library by PB2 and on the SmartMotor class found in drone_control.ino. We make a PID object and SmartMotor object for each motor(image 3):
After this is done, the drone is ready to (attempt to) fly.
MPU and Orientation (drone_control.ino or MPU_Only.ino)
We’re going to use a library by Jeff Rowberg to communicate with our MPU. First, download this whole folder: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 and put the Arduino/MPU6050 folder into your Arduino libraries folder (for me it was C:\Users\[user]\AppData\Local\Arduino15\libraries\).
The MPU does onboard integration to measure its orientation - we do not need to do the integration ourselves. Instead, we just need to initialize the chip and then read out the values.
We initialize using recycled code from Jeff Rowberg(image 4):
We obtained the calibration values for the MPU with this MPU program: https://github.com/Protonerd/DIYino/blob/master/MPU6050_calibration.ino
At the beginning of loop() we check whether it initialized properly(image 5):
After the MPU is calibrated, it can be read with the following code(image 6):
PID Explained
The drone stabilizes itself using a PID (Proportional, Integral, Derivative) controller to adjust motor speeds, given its orientation as input. You must tune the kP,kI, and kD terms to make the drone stable - a very painful process (one that we did not master).
We defined an “x” axis as passing through the front and back clockwise (CW) motors, and a “y” axis passing through the front and back counter-clockwise (CCW) ones. You should notice a flaw here: the axes are not completely normal to each other. This will lead to some inherent problems with trying to isolate which rotations a motor was responsible for, but we forged ahead hoping that the PID could “figure it out”. If you have a square drone frame then this shouldn’t be a problem.
(Look at image 7)
When we affixed the MPU to the drone, we placed it at the origin and angled it so that the wires/pins pointed along the x axis. Then, we knew that the CW motors would either cause positive or negative rotation around the y axis, and CCW motors would be responsible for rotation around the x axis. To determine whether a motor caused positive or negative rotation around the axis, we ran pid_visual.py and then lifted a motor (as if it was thrusting) to see how the coordinates reacted. Our particular arrangement had FCW +y, BCW -y, FCCW -x, BCCW +x.
(Look at image 8)
DIST_FACTOR is a coefficient introduced to compensate for the fact that the motors are not equidistant from the center of the craft. See its definition in the code for more info.
Radio Communication
In the future, we will have the drone receive a target orientation (in the form of x and y values) from the glove Arduino over the attached LoRa radio. This target orientation would be used to update the PID’s target x and target y (currently constant at 0, 0). The code used for communication would look very similar to that on the gloves.
MIN and SERIAL Communication
This section and code above are optional - they improve the performance of display tools
To ensure that the data we were receiving over the wire was not corrupted, we sometimes used a modified version of the MIN protocol to communicate. If you find you get unreliable data back at high speeds and want to do the same thing, you can use the implementation in the code and add it to communications that we currently don’t use it for. The details aren’t terribly important here - the most important thing is that the data is MIN-encoded before being sent and MIN-decoded on receipt.
Laptop Software
Initialization
In setup() of drone_control.ino we included the following(image 1).
Thus, any program that we want to use to monitor the drone must send a character over serial to start the initiation sequence. In pid_visual.py, for example, we do the following(image 2).
MIN and Serial Communication
This section is optional - it improves the performance of display tools
To improve performance when displaying orientation data, we wrote a service in Rust that decodes messages over Serial, does quaternion math, and then posts the result to an internal web server. Then, we query that web server with our orientation Python visualization program,
(Image 3)
(orientation_display.py) and display the result. Our Rust MIN decode looks like this (min.rs):
(Image 4)
We then post this to a web server (main.rs):
(Image 5)
and our web server stores it for us (server.rs):
(Image 6)
Data Processing
We process the data that we receive from the drone in a couple of different ways. The first involves the Rust method (see above) and calculates the three axes for the orientation display (main.rs):
(Image 7)
Other times we just parse data we receive raw over the wire (pid_visual.py):
(Image 8)
Data Display
To tune our PID and get a better understanding of the drone’s operation, we display information from the drone on the laptop screen during operation. In the repository, we provide two different visualizers. We highly encourage you to make your own to display relevant information!
- orientation_display.py: this shows orientation data. it expects quaternions in the form provided by the Rust web server that we detailed earlier. To run:
- Build the Rust project (google this if you don’t know how)
- Run the compiled output of server.rs to host the web server
- In a different terminal window, run the compiled output of main.rs with the full port name as the only command-line argument (ex. “COM18” on Windows, “ttyS0” on Linux, “/dev/tty.usbserial-FTG6RCEJ” on MacOS)
- With those two running, run orientation_display.py . If everything worked, it should open a graph and display (close to) a real-time 3d orientation display.
- pid_visual.py: run this when the drone has been loaded with drone_control.ino. You will likely notice that it’s pretty slow - in the future, we hope that it will be changed to share the Rust infrastructure that orientation_display.py uses.
Glove and Radio Assembly
Our drone is sent instructions for desired orientation and motor power from a set of gloves via radio. There is a force sensor attached to one glove and an inertial measurement unit (IMU) attached to the other. The following diagram depicts the glove setup attached to an arduino with some additional circuitry components.
LoRa Radios:
- Test the LoRa radios using the simple LoRaSender and LoRaReceiver codes found in the LoRa library under Arduino > Examples. To do this, you’ll need to install the LoRa Arduino Library by Sandeep Mistry if you haven’t already. You’ll also need two Arduino Unos to wire the radios up separately and transmit information.
- Once the radios are communicating, attach one radio to the drone-based Arduino depicted in the first diagram and the other to the ground-based Arduino depicted in the second diagram. We want the ground-based radio to act as the transmitter of our glove instructions and the drone-based radio to receive these instructions and perform the desired action. We will do this by sending one set of transmitter code to the ground-based Arduino and another set of receiver code to the drone.
Glove Sensors:
- Assemble the circuit in the diagram above to attach the force sensor and IMU (MPU-6050) to the Arduino. Do not attach the sensors to the gloves yet.
- Once the LoRa transmitter is successfully working on the test code, send our Transmit code to the ground-based Arduino with the relevant libraries installed. This code will read the glove sensors, convert their output values into useful information, and transmit instructions to the drone. For now, we’ll use it to test that the force sensor and IMU are working.
- Notes about the code:
- There are two voltage dividers in this circuit: one to limit the voltage sent to the LoRa radio and the other to measure the pressure-variable resistance of the force sensor. The value of the resistor in series with the force sensor is important to the code. If you’re using a resistor with a value other than 10k, you’ll need to edit the voltage divider equation in the code that gives us the force exerted.
- This code utilizes checksums to detect errors in data transmission, which requires the user to download the CRC32 Arduino Library by Christopher Baker (https://github.com/bakercp/CRC32).
- If you’re using the MPU-6050 for inertial measurements, you’ll need to download Jeff Rowberg’s accompanying library (https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050). If you’re using a different IMU, you can find a range of relevant libraries at Jeff Rowberg’s github (https://github.com/jrowberg/i2cdevlib/tree/master/Arduino). However, please note that you’ll need to edit the code to call on the relevant libraries and functions if you are not using the MPU-6050.
- Next, test that the pressure sensor and IMU are working properly. When you first run the arduino code, hold the IMU still so that a stable zeropoint can be calibrated. Then, vary the pressure on the force sensor by pinching it, and changing the orientation of the IMU. On the serial monitor, you should see a continuous output with a value in Newtons and a set of coordinates. If you do not, check that the baud rate is set to 9600, all circuit components are wired properly, and all libraries listed in the code have been downloaded. If you see strange characters on the serial monitor, the write/read rates may be set too high. You can adjust these values in the code until the serial output looks normal.
- When the sensors are consistently outputting values to the serial monitor, you can attach them to the gloves. We’ve sewn the sensors onto a pair of sturdy mesh gloves, but any fastener that holds the sensors stable will do.
- At this point, you should have a working pair of gloves that send values to the Arduino, which then outputs over serial and transmits instructions to the drone.
Finalize
Once again, this project has not been fully completed yet and we strongly advise against taking on this project until we finish it or you have the ability to complete it yourself. If you decide to make this project and fully complete it, congrats! You now have a fully functioning drone that you can control with your hands!