High Tech Lawn Mower(Tricopter) build

by David Kim
Project Github link So after fiddling around with an Arduino for about a month, I decided I wanted to make a multicopter. Specifically a tricopter, the reason being that it had great yaw control. Not only did I want to make a tricopter, I wanted to program the flight controller myself. I also had a lot of resources online, mainly by David Windestål from RCExplorer.se http://flitetest.com/articles/tricopter-scratch-build http://rcexplorer.se/projects/2013/01/the-tricopter-v2-6hv-delux/ http://rcexplorer.se/projects/2012/07/the-tricopter-v2-6hv/ http://rcexplorer.se/projects/2011/09/the-tricopter-v2-5/ http://rcexplorer.se/projects/2010/11/the-tricopter-v2-2 http://rcexplorer.se/projects/2010/03/the-tricopter-v1-and-v1-5/

Part List

From looking around those links, I decided to go with: Hobbyking hexTronik DT750 Brushless Outrunner 750kv (3x) Hobby King 20A ESC 3A UBEC (3x) The bluebird servo wasn't in stock so I went with this servo: Turnigy Digital high torque bearing servo 15.8g/3.9kg/0.13sec Turnigy 2200mAh 3S 25C Lipo Pack PolyMax 3.5mm Gold Connectors 10 PAIRS (2 Packs) Front Wheel Steering Arm & Mount Set 40mm XT60 to 3 X 3.5mm bullet Multistar ESC Power Breakout Cable 10CM Servo Lead Extension (JR) 26AWG(10pcs/bag) Peel-n-stick foam double sided tape 10x5inch 4mm thick Turnigy 5mm Heat Shrink Tube - BLACK (1mtr) Turnigy 5mm Heat Shrink Tube - RED (1mtr) Electrical Zip / Cable Ties 4xL150mm - 100/bag (Orange) Don't forget the battery charger(I ended up just getting a cheap one): Turnigy 12v 2-3S Basic Balance Charger (This actually melted while charging my battery for the first time) The following I got from Chinese eBay dealers (beware, the shipping time is unreliable): 10x4.7in propellers (1 CW and 2 CCW) Arduino nano (It says DDCduino on my board) MPU6050 Gyroscope/Accelerometer PCB Board 6CH Flysky remote/receiver (I had this before the build, you can probably find a better remote on Hobbyking) Lipo low voltage alarm 3S Some wires(just for the Arduino, it won't run a lot of current) Note: Stranded 26 awg, different colors will help Home Depot: 1/2 inch square dowels 10x8 Lexan sheet Screws/Locknuts for the frame(matching set) M4 Screws(for the motors) Misc: Battery strap Epoxy Locktite Things you may need: Multimeter Caliper Something to cut out your frame(I used a scroll saw) Filer Drill and some bits Dremel Soldering Iron Sanding paper

Build

First thing's first, I've never flown anything RC. I actually recommend if you have never done any quadcopter flying before, don't make one. Also this is a good time to put a disclaimer, I don't know what I'm doing. Use this article at your own risk. Before committing to this build, I did some research on PID controllers and was working on small Arduino sketches. After I was a bit more confident, I ordered the parts. A few days later, I got the main HobbyKing order. The Chinese eBay orders took quite a while. While waiting for the eBay orders to come in, I started on the frame and soldered the bullet connectors onto the ESC and motors Following David Windestål's advice, I mixed in epoxy and put it on the wires by the shaft of the motor(check the flitetest video) While waiting for the motors to dry, I started cutting out the Lexan frame using a scroll saw. The frame design is also from David Windestål: http://assets.flitetest.com/article_files/Tricopter_1365353510.pdf I cut out two pieces, for the top and bottom. Be sure to cut out some landing gears as well. The dowels are cut at the lengths of 35cm(2 pieces) and one 37cm(back). Using my calliper I figured out the center point of the two dowels and drilled through it. The hole should be big enough for the frame screw to fit through it, it doesn't matter too much if it's loose or not as the booms are supposed to fold back. I filed screw holes on the back boom to fit the frame(make sure this is straight). I screwed in all the parts to the frame and ended up with: The arms fold back as well. This is great in crashes because the arm will most likely fold back instead of breaking. The motors should have male bullets and the three motor wires on the ESC should have the female connectors. This is important so when the motors come loose(from let's say a crash), it won't short the ESC easily.

The yaw mechanism

Before I started breaking parts off my new servo, I wanted to make sure it's working. I plugged it into my Arduino board(running the example servo code) and it turns out it doesn't want to move. After a while I figured out it was because the Arduino can't supply enough current. I hooked up an external battery source and lo and behold it worked. I ran the Servo/Sweep example with this circuit Since it was working, I cut off the end plastic piece above the wire. Following the Flitetest video, I used the wheel mount set to create the yaw mechanism. I fastened it with a long screw instead.

Testing the motors

I already know the servo works at this point but does the ESC+Motors work? I had to find out. I directly connected the ESC connector to a motor and my RC receiver. I plugged in the LiPo battery and heard a few beeps(I had no idea it was going to do that). I wasn't sure what the beeps meant but a few seconds later my ESC exploded and magic smoke came out. I unplugged the battery immediately. I wish I recorded it happening. I'm sitting there thinking what the fuck happened. Turns out I forgot to add the sleeves onto my connectors and it shorted. At this point I'm hesitant to test another ESC considering my first one exploded. Eventually, I tested the second ESC WITH SLEEVING; it started up, beeped and started spinning the motor. What a relief.. I did the same with the other ESC/motor. I also tested the motor that was connected to the ESC that exploded. They all seem to work so I reordered another ESC. Motor testing circuit: Connect the servo pins to the throttle of the RC receiver, in my case it was channel 3. The 3 wire connection doesn't matter for the motor to the ESC. Keep the throttle on the lowest setting on your remote and be sure to turn your remote on before powering the ESC. You might also want to clamp down the motor somehow.

Programming!

Time to program! Do keep in mind that a lot of the programming here is generally written for multicopters and not just tricopters. Resources for programming(open source) Aeroquad Ardupilot Multiwii Dr Gareth Owen's Build I'd like thank the open source community for providing me with all these resources to learn from.

Gyroscope Programming:

At this point I'm wondering where the fuck my gyroscope is, several days later it finally came in. The seller actually sent me one more, lucky me. Now that I have my gyroscope, I can start programming it.. but how do I even connect this thing and interface with it? I looked up the specs and found: http://www.i2cdevlib.com/devices/mpu6050#source Oh hey, someone already wrote a library for it. I wanted to save the headache of writing my own library for the MPU6050 so I made use of this. Gyro Vcc to 3.3V (DO NOT CONNECT THIS TO 5V) Gyro G to G Gyro SCL to A5 Gyro SDA to A4 Gyro INT to D2 Some related things I found: Arduino Playground for MPU6050 Kalman filter for MPU6050 So a gyroscope can read the rate of change in it's orientation, an accelerometer can read which way force is being applied to it. This is all nice but they both have their own problems. Gyroscope data tends to drift while the accelerometer data is noisy(it will pick up tiny vibrations). There's methods to combine it using methods like the Kalman filter, complementary filter, directional cosine matrix, etc. That doesn't really matter right now because the library handles all that for us! The library can output quaternion data as well. It also turns out the MPU6050 has drift countering built into the hardware(Video by geekmomprojects) What information do we need from the gyroscope/accelerometer? The rate of change in the orientation as well as it's current orientation What's the difference between orientation and the gyroscope rate of change? The orientation is it's current position, while the rate of change is the amount it's turning at it's current state. If the multicopter is tilted to the side and not moving, the orientation values will be some angle while the rate of change will be zero since it's not changing. Why do we need the rate of change? In order to keep the orientation of the multicopter steady, we need to figure out how much to compensate for the change in angle. This is so the multicopter tries to resist moving out of the current orientation(by it's own motors or by external forces like the wind). Why do we need the orientation? This is more for stable mode, knowing where the ground is will help return to a hovering state.

RC Receiver Programming

The remote receiver outputs a PWM signal to each channel pin. Some resources I've found for this: RCArduino: How to read RC receivers RCArduino: How to read multiple RC channels These signals are valued from 1000us to 2000us and 1500us being neutral. When the sticks on the controller is centred, it outputs around 1500 on each channel. A multicopter needs at least 4 channels to operate, however the Arduino only has a few interrupt pins. From RCArduino's blog, the PinChangeInt library is perfect for this. Arduino Playground: PinChangeInt This library will change all the pins to interrupt pins. I wrote my own RC receiver code where all the channels have separate handlers: RCChannel.h RCControl.h Note: Disabling interrupts will cause problems for the servo library Here's a test program to see if your RC receiver works:
int rcPinA = 5;
int ledPin = 11;

void setup()
{
  pinMode(rcPinA, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  int inputState = pulseIn(rcPinA, HIGH, 25000);
  int ledBright = map(inputState, 1200, 1800, 0, 255);
  analogWrite(ledPin, ledBright);
  Serial.println(inputState);
}
You may have noticed from the Serial output, that your controller does not output values near 1000 or 2000. In my final code I have scaled my minimum and maximum values so it is converted to angles in degrees. Another thing is that pulseIn is a blocking function, therefore it can't be used with multiple channels. In the RCChannel/RCControl code I have used interrupts instead.

Controlling the Motors

Luckily the ESCs interface with PWM signals(which is why you can connect a receiver directly to the motor). Also on top of it, the Arduino Servo library sends out PWM signals. My job got a lot easier! I made a sample program to run my RC signal through the Arduino out to the ESC to turn the motor on at whatever speed. Basically a relay. If I can make the Arduino handle the motor output using the radio input, I'm almost there! You can use writeMicroseconds to send direct PWM values to the ESC When I ran the program, nothing happened. Turns out these ESCs need to be armed before they can spin the motor. I need to send a throttle down command to the ESC when they start up. I can do this by sending it a command of 1000 since the minimum value from the RC controller is 1000(around there). Rerunning the program with this new change has worked! Note: Unless you can start the ESC with the Arduino, plug the ESC into the battery after the program starts. You will have 10 seconds. I've found that my ESC doesn't arm otherwise.
#include <Servo.h>

Servo esc;
int j;

void setup()
{
  esc.attach(9);
  delay(1);
  //Arms the ESC
  esc.write(40);
  delay(10000);
}

void loop()
{
  
  for(j=0; j<180; j++)
  {
    esc.write(j);
    delay(20);
  }
  for(j=180; j>=0; j--)
  {
    esc.write(j);
    delay(20);
  }
  esc.write(0);
  //Stop running
  while(1);
}
I only used angles here because it was a small test program.

Putting it all together

If we send a 1500 PWM signal to each ESC, it might give one motor a little more thrust than another causing it to flip over. We need to use PID controllers to auto correct the copter's orientation. A PID controller is a feedback mechanism that controls the output to get a proper output. For example a hot tub needs to check the temperature of the water and needs to decide if it needs to cool down or heat up. Balancing robots use the same concept. Here's a cool video of a PID controller PID controllers are amazing! Some resources: Arduino Playground: PIDLibrary I ended up modifying the Aeroquad PID code since I liked how it worked. Now what may be confusing at this point is, what values do I use for the PID? Well, every multicopter is different. Even the same multicopter can have different optimal PID values. There are a lot of videos on Youtube on PID tuning for quadcopters You will need a separate PID object for stable mode, here's a good link: Aeroquad Stable Mode Explained by wilafau The multicopter's PID will read the rate of yaw/pitch/roll from the gyroscope and make adjustments. Remember, this is the rate not the current orientation. The more it's spinning, the more the PID controller will need to compensate for the counter force. Each axis will have it's own PID controller(yaw/pitch/roll). The outputs will simply be sent to the motor. The PID values will scale the error value to an output value. In this case, the error will be the difference in angle from the controller to the gyro rate. This error value will then be multiplied by a coefficient that turns it into the output for the motor(s). For example: If you move the pitch stick up and the multicopter is not moving, the error value will just be, rcPitch - 0. This error value is then multiplied by a coefficient, let's say 1.5; rcPitch*1.5. If the rcPitch from the controller is at 10 degrees, the PWM output will be 10*1.5=15. Later this value will get added/subtracted to the thrust.

Yaw Pitch Roll to motor values

Since I'm running a tricopter, I control the motors differently from a quadcopter.
frontLeftValue = throttleValue - outputRoll + outputPitch*2/3;
frontRightValue = throttleValue + outputRoll + outputPitch*2/3;
rearValue = throttleValue - outputPitch*4/3;
yawCommand = MIDCOMMAND + outputYaw
The throttleValue is the scaled amount from the receiver MIDCOMMAND is 1500, as it is the state in which the servo is centred Notice that the outputRoll is subtracted on the frontLeft and added on the frontRight, this is so it can pivot on the center of the tricopter without the rear motor changing the orientation. The outputPitch values are fractional because there's only one motor controlling the rear and two in the front. You might think the rear will end up doing more work, however since the front provides more thrust, the PID will "self balance" the amount of power to give out. Here's an example of the loop: The tricopter will take the throttle signal and scale it from 1000(min) to 2000(max) The controller channels for yaw pitch roll will all be scaled from PWM signals to angles, in my case I used -45 to 45 degrees for pitch/roll The gyroscope will read the rate of change in all three axis as angles The PID controller will compare the gyroscope rates with the scaled controller values and output a PWM difference for each axis These outputs from the PID controller will then get merged into the motor outputs which include the scaled throttle value I should note that my motor orientation is set so: That's pretty much the gist of it. I ended up soldering all the electronic components together. I also zip tied everything down(zip ties will break instead of major components when the multicopter crashes). I will be adding some updates to this page/Github in the future.

Final Circuit

The pins are: Connect all the ESCs to the appropriate motor and the red/black power wires to the power distribution wire Left ESC Servo wire: GROUND to Arduino Ground 5V into Arduino 5V(I didn't use the Vin pin because the voltage regulator needs at least 6V) Note: It is possible to connect the battery into Vin, however you will need to use a 11.1V battery. The voltage regulator will drop the 11.1 to 5v and eventually heat up. Signal Pin to D9 Right ESC Servo Wire Ground to Arduino Ground 5v NOT CONNECTED Signal Pin to D10 Rear ESC Servo Wire Ground to Arduino Ground And Yaw Servo Ground 5v into the yaw servo 5V, This will provide power to the yaw servo Signal Pin to D11 Yaw Servo Wire Ground connected to one of the ESC ground 5v connected to one of the ESC 5v Signal Pin to D5 Receiver Connection Do not connect the 5v and grounds of the channels to anything CH1 to D3 (Aileron / Roll) CH2 to D4 (Elevator / Pitch) CH3 to D6 (Throttle / Thrust) CH4 to D7 (Rudder / Yaw) CH5 to D8 (AUX1, Optional) CH6 to D12 (AUX2, Optional) 5V Pin (Battery pin) to Arduino 5V G Pin to Arduino Ground Gyroscope/Accerometer Vcc to Arduino 3.3V (DO NOT CONNECT THIS TO 5V) G to Arduino Ground SCL to Arduino A5 SDA to Arduino A4 INT to Arduino D2 IMPORTANT NOTE: Do not connect the USB port while the battery is plugged in! Tricopter Code via Github The maiden flight video, P is set to 1.3, I and D are 0 The tricopter gets a bit unstable, I need to lower the P and add some I and D values.

Updates

10-28-14 I have flashed the ESCs with simonk firmware and I realized it doesn't like the servo library The PWM signal from the servo library is rated for 50hz while simonk is rated closer to 500hz. It's much better to send the ESCs the data more frequently. This can be done with analogWrite. My oscilloscope reading Top is the 50hz servo library, bottom is the analogWrite command on specific pins from the Arduino. This depends on which Arduino, for my case it was the same pins as I had the motors connected to. I changed the servo library to an interrupt command found in the AeroQuad tricopter code, with some changes I didn't realize my PID values were so off when I changed these things I think what happened was that the I value was too high and it was gaining too much error while on the ground Flies much better now Finally getting the hang of it Still needs a bit more tuning, it doesn't feel sensitive enough More updates coming