Using a PIC32 MCU
Small quadcopter-style drones represent one of the most exciting areas of embedded system design in recent years. Learn how these three Cornell students designed, constructed and tested an autonomous quadcopter that uses a Microchip PIC32 MCU as its flight controller and acquires data from an onboard IMU. They also built a ground station with a PIC32, to downlink the IMU data through radio and send commands to control the quadcopter’s flight time.
We designed, constructed and tested an autonomous quadcopter that uses a Microchip PIC32 microcontroller (MCU) as its flight controller and acquires data from an onboard IMU. We also built a ground station with a PIC32 to downlink the IMU data through radio, and send commands to control the quadcopter’s flight time. We wanted the drone to be able to take off, stay in air for a user-defined time and then land. We used a 3D-printed chassis to house all the quadcopter electronics and an off-the-shelf electronic speed controller (ESC)—which receives PWM signals from the PIC32—was used to control four motors.
Initial calculations and tests, shown in Table 1, were used to determine the feasibility of the project. For ease of testing, we chose to make our quadcopter as small as possible, just big enough to carry the PIC32 MCU, associated electronics and the power supply. The estimated total mass for the quadcopter was 0.348 kg. This meant that the chosen motor, battery and propeller combination must be able to lift this mass with a thrust-to-weight ratio greater than 1.
We found several motors weighing around 10 g that met this requirement, so building a quadcopter of this size seemed feasible. The major constraint for the drone was between the lift power and its weight. We wanted to minimize the weight by reducing unnecessary hardware, and by using a battery with higher voltage within the limit.
To ensure that our flight control algorithm had enough time to correctly balance our quadcopter, we performed our PID (Proportional, Integral, Derivative) control in an Interrupt Service Routine (ISR). We estimated the natural period of our quadcopter to be milliseconds, and the motor time constant was around 10 to 20 ms. Therefore, we could check the drone state at the frequency above 1 kHz, so the length of the ISR had to be within 1 ms, which is the maximum delay we expected that would still keep the quadcopter under control. This 1 ms incorporated collecting data from the IMU, along with the PID calculations.
We chose to use a brushless DC motor, because these motors are so common in the world of Remote Control (RC) aircraft and drones. This allowed us to choose from a wide variety of off-the-shelf controllers that are designed for controlling these motors in small aircraft applications. The BE1104 motor from DYS was a good candidate, because of its small size and weight (11 mm diameter and 6 g mass). Additionally, because this motor is frequently used for small aircraft, it has documented test data with particular propellers and batteries. The data shown in Table 2 is from www.getfpv.com, a website about model aircraft and drones.
Based on the data in Table 2, we chose to use a 3020R propeller with a 3” diameter. We bought a 2-cell, 7.4 V LiPo battery and a 3-cell, 11.1 V LiPo battery to test the lift power. It takes at least 4.5 A for a 7.4 V-battery or 5.4 A for an 11.1 V-battery to lift up the quadcopter’s 348g estimated mass. This allowed us to size the batteries for reasonable flight times. At 4.5 A per motor (18 A total), a flight time of 1 minute requires a 7.4 V battery with a capacity of 112.5 mA-hours. We bought a battery with 450 mA-hours to avoid a large depth of discharge, which can also help to increase the battery life. The most suitable 11.1 V LiPo battery we could find had a capacity of 350 mA-hours. Both batteries had a discharge coefficient of 20 C, which was qualitatively sufficient for current draws of the drone we were building.
ELECTRONIC SPEED CONTROLLER
We chose a DYS F18A Electronic Speed Controller (ESC), because it was the smallest and lightest 4-in-1 ESC we could find, and 18 A per motor was more than sufficient. Most off-the-shelf ESCs take in a servo pulse, which consists of a 50 Hz PWM signal with 1-2 ms pulses. A 1 ms pulse corresponds to minimum throttle (motor does not spin), and a 2 ms pulse corresponds to full throttle (maximum motor speed). The ESC converts this servo pulse into PWM signals that it uses to control MOSFETs arranged in a bridge.
Each pair of power MOSFETs controls the switching of one phase of the 3-phase brushless DC motor. The DYS F18A ESC that we used had four circuits, one for each motor. Each circuit accepted an independent PWM signal, but all were powered by the same battery. A secondary function of the ESC was to step-down the battery voltage from 7.4 V or 11.1 V, and provide a 5 V output. On RC aircraft, this is used to power the receiver, but we used it to power the PIC32.
The IMU read the raw data from the sensor chips, combined it and converted the results to usable values. We chose to use the 6050 IMU from Invensense to measure acceleration and gyroscope readings for our PID. The PIC32 used I2C to communicate with the IMU. To retrieve data from the IMU, we used the PIC32 I2C library  with high-level I2C read and write helper functions. We used three gyro values and three accelerometer values on our drone. Each measurement value was divided into two bytes stored in two registers. We read char type data for lower byte and higher byte, then concatenated them to a 16 bit integer. To get a more reliable gyro data, we sampled the gyroscope over an extended period of 50 ms and averaged it. We read the IMU inside the ISR to get the gyro rate of the drone, and fed it into PID controller to adjust the drone’s position.
We used a Nordic Semiconductor nRF24L01+ Radio  to communicate between the drone and the base station. To construct the entire radio system, we placed one of the two radios on our base station. The base station included a PIC32 mounted on a PCB board with a thin-film-transistor liquid-crystal display (TFT LCD), so we could see the down-linked data (Figure 1). We also included a 10 kΩ potentiometer that was used to select the desired flight time for the quadcopter to hover. There was also a switch on the board that sent a start signal to the quadcopter and signaled it to start the PID algorithm and lift off. We mounted the other nRF24 on the drone, and used it to transmit IMU data and receive commands. The schematics of the ground station and the drone are shown in Figure 2 and Figure 3, respectively.
To make sure we had the correct order of IMU data displayed on the TFT screen, we designed a synchronization protocol, which is as follows:
1) The radio on the drone starts off at receive mode (RX mode), awaiting the start signal.
2) The radio on the base station, starts off in transmit mode, waiting for the user to toggle the switch up.
3) As soon as the switch is toggled, the flight time is transmitted, and the base station goes into RX mode, awaiting the IMU data from the drone.
4) Upon receiving the start signal, the drone switches into transmit mode. It downlinks the IMU data and the flight time, which are printed on the TFT screen of the base station.
5) The drone also transmits a known sequence to the base station, to notify when there is a new round of data coming, to ensure that both radios are synchronized.
After the selection of electronics, we moved on to the mechanical layout. Important considerations for the mechanical layout included minimizing weight and balancing the quadcopter. Its center of mass was positioned at the center of the four motors, making altitude control easier. The 3D-printed chassis was designed with simplicity and weight savings in mind. Its size was based on the 3” propeller diameter, to give ample room for the electronics and battery in the center (Figure 4). Figure 5 shows the drone’s motor and ESC test setup.
The key part of the drone is the control algorithm. We used a PID algorithm to control the motors. In our orientation of IMU on the quadcopter, pitch is defined as the rotation along the X-axis, and roll is defined as rotation along Y-axis. The quadcopter determined its altitude by integrating gyro data in these two axes to get two angle measurements θX and θY. After reading the gyro, the angle was determined by Euler integration:
An initial gyro offset was removed when the IMU was set up by taking two gyro readings 50 ms apart and averaging them. This procedure was done only once, in the main loop when the quadcopter was sitting still on the ground before takeoff.
We employed several methods to compensate for gyro drift. First, we reset the integral term to 90% of its current value whenever the rate changed the sign, to improve the accuracy of integral term over a period of time. Second, a complementary filter used accelerometer data to correct the gyro readings. 98% of the angle reading comes from the previously mentioned gyro data integration, and 2% comes from accelerometer determination of altitude in relation to the direction of gravitational acceleration. Accelerometer readings in each direction are represented by αX, αY and αZ.
Two PID controllers ran independently—one for X-axis rotation and one for Y-axis rotation. Both controllers worked to maintain the angle of the quadcopter at takeoff. The initial angle was taken as θX=0, θY=0, and during the flight, the controller tried to drive the angle back to zero. Figure 6 is a block diagram of the PID control for each axis.
The control signal can be calculated by the following equations where intx and inty represent the integral in X-axis and Y-axis, respectively.
We converted control signals to PWM signals by assigning two motors to each axis and increasing or decreasing their PWM signals in proportion to the control signal on that axis. Note that we had a prescaler of 16, and the clock speed for PIC32 was 40 MHz, so the new clock speed was 2.5 MHz. Therefore, 1 ms corresponded to 2,500 cycles. The length of pause of the PWM signal was between 1 ms and 2 ms, where 1 ms resulted in the off state and 2 ms resulted in full-speed state.
In these equations, M0 denotes a set point where the motors should stay if the quadcopter is close to an angle of zero. This set point should be high enough that the quadcopter can still lift off if all the motors run at that speed. We ramped the set point up and then down again at takeoff and landing, to make flight smoother and to prevent noise spikes associated with rapid motor acceleration. The set point started at zero and ramped up to 1,500 during flight. By limiting the PWM (pulse width modulation) signals to the range 2,500-4,500 cycles (1 ms servo pulse to 1.8 ms pulse), there was a 1,500 cycle range on each side of the set point for the PID controller to work with.
TESTING AND RESULTS
The fully constructed quadcopter and controller are shown in Figure 7. For the first stage of PID control testing and tuning, we powered two motors at a time and controlled just one axis of rotation. We held the quadcopter steady along one axis, and displaced it from horizontal to observe how well it recovered. Low frequency of the servo pulse control (50 Hz) led to problems in integrating the gyro data and stabilizing the quadcopter. We increased the frequency from 50 Hz to 500 Hz, even though the ESC was only rated for 50 Hz.
Although the threshold for the motors turning on decreased slightly and motor speed overall increased, we saw no significant adverse effects. Note that 500 Hz is the maximum frequency, because a 2 ms servo pulse must have a period greater than 2 ms. We used 1.8 ms as our max pulse width, so 500 Hz worked fine. After the control frequency was increased to 500 Hz, the quadcopter was able to successfully integrate gyro data to obtain angle measurements and control its angle at a high enough bandwidth to fly reasonably level.
We chose our initial PID controller gains so that for each axis at an angle of about 30 degrees off horizontal, the servo pulse on one motor would be at max (1.8 ms) and the servo pulse on the other motor would be at minimum (1 ms). We observed the width of the servo pulses on an oscilloscope without the motors connected, and tilted the quad copter to find these gains. In this initial estimate, the gain—especially proportional gain—proved to be much too high. Before flight testing, we hung the quadcopter from a string and connected two motors with a lower battery voltage, so they would balance the quadcopter but not cause it to take flight. This turned out not to be the best method of testing, since the string occasionally got tangled up in the propellers. But it allowed us to see that the best strategy was to use quite low gains (KP = 10, KD = 50, KI = 0.04). Table 3 shows the results from different PID settings. Our goal was to vertically take off, hover and land at the same place. The last set of settings gave us the best performance.
We found that high motor speeds or fast motor acceleration created noise spikes that caused the PIC32 to reset during the test. To prevent this, we limited the servo to 1.8 ms, which is 90% of the maximum motor speed, and ramped the PWM set point slowly, less than 10 PWM cycles per ISR cycle. This problem still posed a serious limitation to the design, because a disturbance torque caused, for example by wind, could cause the PID controller to request a large change in motor speed and to reset the PIC32. A more robust design would eliminate this problem. The PIC32 could be powered from a separate battery, and opto-isolator circuits could be introduced to isolate the PIC32 controller ground and motors ground. Alternately, we could buy a better ESC, with its battery ground isolated from the 5 V out ground and signal ground.
Adding altitude control would also be a major improvement to stabilize the flight. Although we tried twice to integrate the accelerometer data, it proved to be unstable, and altitude readings were inconsistent. The position readings drifted so severely that the quadcopter could not tell whether or not it was at the correct altitude.
In this project, we designed a drone and made it fly. This could be an initial attempt for anyone who is interested in making a small-scale quadcopter. A PIC32 and other accessible hardware are able to support the basic flight operation. We also built the communication system for the drone and the ground station. Time constraints kept us from reaching one original objective of making the drone hover for a defined time, and there’s still room to improve the flight performance of the quadcopter.
For detailed article references and additional resources go to:
References  and  as marked in the article can be found there.
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • DECEMBER 2019 #353 – Get a PDF of the issue