Showing posts with label drone. Show all posts
Showing posts with label drone. Show all posts

Sunday, June 21, 2020

The Falcon DS1 - BeagleBone Blue Drone (Part 3)

Construction


The hardest part of the build is coming up with a bracket to mount the BeagleBone on the Martian II air frame. In part 1 of these tutorials, I mentioned that there was an existing bracket design available. This doesn't fit for a number of reasons, including clashes with the XT60 socket, the propellers and the top deck of the air frame. But we will come to that...

Start off by putting the frame together. There is a very thorough video of how to do this on YouTube. They are using some different components (including the flight controller), but it does a great job of showing what goes where.

As shown in Figure 20, I labelled the front of the drone and motor number locations using electrical tape. This helps keep you oriented.

Figure 20. Martian II Frame Construction.

Once you have the arms attached to the bottom frame and the Power Distribution Board (PDB) mounted, you can add the quad 20A Electronic Speed Controller (ESC). The RaceStar ESC that I bought has mounting holes which line up nicely with the PDB. I assume that this isn't a coincidence but I admit that I fluked it. Figure 21, provides an overview of what the bottom layer of the drone will look like when we are finished.

Figure 21. Bottom layer Component layout

Figure 22, illustrates the Quad ESC in place above the PDB. Now comes the tricky part (for me, you will find it easy since I supply the bracket design), mounting the BeagleBone. Referring to Figure 21, you can see that there is only 10 mm clearance between the PDB and the propellers, so our bracket can't overhang much. In addition the XT60 socket and associated cables must remain accessible with the BeagleBone in place. If we are going to stick with a stock Martian II frame, the available distance between the top and bottom layers is 30 mm and with the ESC in place we have already used 20 mm of that. Finally, we want to keep the weight centred as much as possible.

Figure 22. Bottom layer components in place.

In the end, I wasn't able to satisfy all of these constraints. The BeagleBone is just too big, it requires 17mm even if you didn't have to make connections to the pin headers (which you do). In addition, to provide access to the XT-60 the BeagleBone needs to be offest from the centre line of the drone.

Typically with the Martian II build, the LiPo battery is attached to the top frame. Instead, I have placed it between the ESC and BeagleBone. As illustrated in Figure 23, it took 5 attempts but I eventually came up with a design that met most of the constraints.

Figure 23. BeagleBone mounting plate with LiPo.

The STL file for the mounting plate is available for download from Thingiverse.

Figure 24. BeagleBone Blue 3D Printed Mounting Plate.

Wire up the power and control cabling as per the schematics in Parts 1 and 2. As our build is a bit different to the standard Martian II, I will provide a few supplementary notes and guidelines based on my experience.

Mounting the Motors

We need to mount the four brushless motors to work out the correct wire length to the ESC. My RacerStar motors came with two sets of M3 screws, 8mm and 6mm. The thickness of the frame arms is 4mm, so use the 6mm screws to ensure they don't short out the motor coils. For now you can just do them up finger tight but eventually you will want to apply loctite to ensure that the motors don't fall off mid flight (bad).

The RacerStar ESC can be programmed using the BLHeliSuite software on PC. With that we can reverse the motor direction but you need compatible Flight Controller software. For our purposes, it is probably simpler to just swap two wires if the motor is going in the wrong direction.

My motors indicate their default rotational direction (clockwise or anticlockwise) by arrows on the top of the motor and different coloured propeller  nuts. The black nuts rotate clockwise and the red nuts anticlockwise. To minimise the amount of work, you should mount the motors in the configuration shown in Figure 25.


Figure 25. Required Motor Directions (X Configuration)

Once you have mounted the motors you can then wire them to the Quad ESC. While you are doing this, also solder the ESC battery connection to the appropriate pads (+ and -) on the Power Distribution Board and a connector to allow you to plug power into the flight controller.



The Falcon DS1 - BeagleBone Blue Drone (Part 2)

Control Wiring


The BeagleBone uses mostly JST connectors. We need the following:
  • Four (4) of the 2-pin 1.5 JST ZH female connectors, with attached 150mm 28AWG wires, for the motors,
  • Eight (8) of the 4-pin 1.0 JST SH female connectors, with attached 150mm 28AWG wires, for the encoders as well as the UART, I2C, CAN, and PWR busses, and
  • Four (4) of the 6-pin 1.0 JST SH female connectors, with attached 150mm 28AWG wires, for the SPI, GPS, GPIO, and ADC busses.
These connectors are small but they are also fiddly to crimp and a bit delicate. Nevertheless this is what we are stuck with. Despite a LOT of searching, I was unable to find a complete diagram which indicated all of the correct connections for using the BeagleBone Blue as a flight controller for ArduCopter. The best I was able to find was the Imfatant version, which he provides as part of his description regarding how to get ArduCopter onto the BeagleBone. I have reproduced his image below in Figure 12.

Figure 12. BeagleBone Blue Connections (ref: https://github.com/imfatant/test)


I ended up doing my own drawing, to ensure I knew what connected to what. I needed this in order to work out the best layout on the airframe and what cables and connectors are required.

Figure 13. BeagleBone Blue Control Wiring.

Note that the front of the drone is towards the top of the diagram in Figure 13. The motor numbers match up with the nearest motor outputs on the QUAD ESC. The control wires for each motor (S1, S2, S3 and S4) then go to the corresponding servo/ESC connections on the BeagleBone Blue.

Now that we have the connections worked out we can load up some software and start testing our rig.

Loading ArduCopter on the BeagleBone Blue


The most comprehensive guide to loading the ArduCopter software onto the BeagleBone Blue is found at the Imfatant Github repository. There is also a summarised version of these instructions on the Mirkix Github repository (Mirko Denecke's port of ArduPilot).

Figure 14. Checking the BBB Connection to the Mac.


I don't intend to reproduce what has already been written in these guides but I will point out areas where things have changed or if I had difficulties.

PART 1 - Preparation

  1. The first issue I found in the Imfatant Guide is that the recommended console image is no longer available at  https://rcn-ee.net/rootfs/bb.org/testing/. I used the latest version that I could find: https://rcn-ee.net/rootfs/bb.org/testing/2019-06-30/stretch-console/bone-debian-9.9-console-armhf-2019-06-30-1gb.img.xz Download this and flash it to a microSD card using Etcher (or equivalent). I used a Toshiba 16GB class 10 card so that I would have plenty of room and speed.
  2. I inserted the SD card (it only goes in one way) and booted up the BeagleBone Blue (BBB from here on), by connecting it to my Mac via the micro USB connection. As suggested in the instructions I tried "ssh debian@192.168.7.2" but the operation timed out. It appears that there are two drivers that you have to download and install for this to work on the Mac. 
  3. Download the two drivers: Network: https://beagleboard.org/static/Drivers/MacOSX/RNDIS/HoRNDIS.pkg and Serial: https://beagleboard.org/static/Drivers/MacOSX/FTDI/EnergiaFTDIDrivers2.2.18.pkg and then install them. The Serial driver may ask you to reboot your computer (it did for me).  The Beaglebone Blue creates a network connection and emulates an Ethernet adapter. Your computer will receive IP addresses 192.168.7.1 and 192.168.6.1. The Beaglebone Blue has IP addresses 192.168.7.2 and 192.168.6.2. You can check whether this has worked by looking at Networks in system preferences (ref: Figure 14).
  4. You should now be able to ssh in ("ssh debian@192.168.7.2") without difficulty. Password is "temppwd" (see Figure 15 to view a successful first log in).  If you receive a “REMOTE HOST IDENTIFICATION HAS CHANGED” error, you have probably previously connected to a different computer on 192.168.7.2 (like another BBB). Remove the old ECDSA key with: "ssh-keygen -R 192.168.7.2".
  5. Next thing you need to do is get WiFi up on the BBB. Follow the Imfatant instructions for this but I found that I had to power the device down and reboot before the changes would take effect. Make sure you "sudo shutdown -h now" before powering down. While you have the power off, CAREFULLY turn the antennas around so that they face off the board. They swivel so don't just try and bend them up and over. You can unplug and replug the antennas if you prefer. Once you power back up, you should have the central green LED lit to indicate a WiFi network connection (ref: Figure 16). 
  6. To get the WiFi IP address of your BBB, I usually use "hostname -I" or "ip addr show wlan0". Alternatively, you can just have a look on your router. Terminate your usb connection and ssh back in using the WiFi IP address. The password is the same. Verify that you have an internet connection using "ping -c 3 google.com".
  7. The remainder of the Imfatant Part 1 Preparation instructions went smoothly for me.
Figure 15. Logged into the BBB via USB.



Figure 16. Green WiFi LED on indicating a connection.


Part 2 - Installing ArduPilot


Follow the Imfatant instructions for setting up the ArduPilot environment configuration file, /etc/default/ardupilot.

The switch -A in the ardupilot config file maps ArduPilot's "Console" serial port (SERIAL0, default 115200) to a target IP address and port number of one's choosing. For example, this allows MAVLink data to be transmitted over WiFi for test purposes. This data stream is auto-sensed by ground control station software like Mission Planner (Windows) and QGroundControl (Windows, OS X, Linux, iOS and Android).

To get the IP address of your Mac, from the Apple menu pull down “System Preferences” and click on the “Network” preference pane. The IP address for your WiFi connection will be shown on the right (see Figure 17).

Figure 17. Getting your Mac IP address for WiFi.


For Windows, press the Windows Start key to open the Start screen. Type cmd and press Enter to launch the command prompt. Type ipconfig at the command prompt to check the network card settings. See Figure 18, you want the IPv4 address.


Figure 18. Getting IP address for Windows


The next tricky bit is getting the latest ArduCopter executable, built specifically for the BBBlue's Arm architecture, onto the BBB. The Mirko Denecke link no longer works but the Imfatant one will allow you to download arducopter v3.6.

Once you have the file downloaded, there are a few different ways you can copy it to the BeagleBone. You can use SCP, just copy it onto a USB drive and then plug that into the BBB, or you can use something like FileZilla. I took the last approach. Depending on permissions, this may be as easy as dragging the file across (Figure 19).

To check the current permissions on the file type, "ls -ld /usr/bin/ardupilot". My initial result was:

drwxr-xr-x 2 root root 4096 Aug  6 08:29 /usr/bin/ardupilot

Which is a problem because the directory's owner and group is root and we have FTP'ed in as debian. In the string displayed above, the first character indicates if we are looking at a directory (d), file (-) or link (l). After that, the folder and file access rights are divided into three categories:

xxxyyyzzz
xxx are access rights for the owner
yyy are access rights for the owner's group
zzz are the access rights for everyone else
The access rights symbols will indicate whether you can read (r), write (w), execute (x) or are missing a right(-). Based on our results, the only person who can write a file into this directory is the owner (i.e. root). We can use chmod to fix this. In terminal type: "sudo chmod o+rwx /usr/bin/ardupilot" The "o" switch applies this change to all users and we are adding (+rwx) read, write and execute rights for this directory. Check with "ls -ld /usr/bin/ardupilot". You should get something like:

drwxr-xrwx 2 root root 4096 Aug  6 08:29 /usr/bin/ardupilot

You should now be able to drag across the arducopter executable into the /usr/bin/ardupilot directory as shown in figure 19. Username and password is the same as for ssh. Use port 22.

Figure 19. Copying the arducopter executable to the BBB using FileZilla.


After this we "sudo systemctl enable arducopter.service" and rebooted the BBB. Job done! You can check that arducopter is enabled with "systemctl is-enabled arducopter".

In Part 3 we will start putting everything together.

The Falcon DS1 - BeagleBone Blue Drone (Part 1)

Flight Controller


Figure 1. BeagleBone Blue Flight Controller


This project will document the construction of a self built drone using the BeagleBone Blue as a flight controller.

An objective of the build was that the drone should be modular, open sourced hardware and software and include an API to allow mission control.

My preference would be to use a board that I already have experience with (e.g. Arduino or Raspberry Pi) as a flight controller.

Unfortunately even though ArduCopter firmware was originally designed for the Arduino, the consensus seems to be that it doesn’t have enough grunt these days (ref: https://dojofordrones.com/drone-flight-controller/).

I like the Navio2 & Raspberry Pi, as the hardware platform for the flight controller. The only problem is that it is expensive ($299 for the HAT alone). Also the Navio2 is not open source hardware.

The PXFmini is a pHAT designed for the Raspberry Pi Zero/Raspberry Pi Zero W but is also compatible with other models from the Raspberry Pi family. It was more affordable (approx. $74) but is now discontinued. The good news is that it is open source hardware and the schematics are available. You could develop your own HAT or pHAT based on this design. It would be great to get hold of one but I haven’t been able to track it down. An issue with this design is that all the soldering is surface mount, which is a pain without the right gear (and great eye sight).

I haven’t used the BeagleBone, but the BeagleBone Blue looks like a pretty good option. It is relatively cheap at $130 delivered and includes most of the sensors you need on the board. The exception is a GPS (the recommended module is the u-blox M8N GPS - $60 from Hobby King). There is an ArduCopter build available for the BeagleBone.

Based on the above I am going to try out the BeagleBone for my initial prototype. The build documentation is very sketchy, so there is going to be a bit of trial and error.

Air Frame


Figure 2. Power Distribution Board on frame.


For my prototype I propose using a Martian II 220mm frame, because that is what BeagleBone suggest in their half documented project. Half documented is probably generous, apparently they never actually got this design flying, nevertheless there is nothing like a challenge to get the juices flowing!

There is a 3D printable case, designed for the BeagleBone for use on a drone, available from Thingiverse (Figure 3).

Figure 3. BeagleBone drone mounting case.


There are plenty of videos documenting how to build the Martian II air frame and its various clones so I wont go into that in detail, except where you need to do something different to utilise the BeagleBone. This happens pretty early in the build.

Figure 4. Airframe with front and motor numbers.


The first thing that you will notice is that the yellow XT60 socket mounted on the power distribution board (Figure 2) prevents you from using the 3D printed case in Figure 3. So we need to do some modifications.

It is a good idea to mark your air frame with the forward direction and motor numbers (Figure 4). This will assist with layout and help ensure that you mount boards in the correct locations.

Technology Stack


The proposed technology stack is shown in Figure 5. We now need to work out the specifics, there wont be a camera in the initial build, in fact my first objective is just to get things working on the bench. I will then be in a better position to work out where the various modules can fit on the airframe. 

Figure 5. Falcon Drone Technology Stack.


Power Distribution


Figure 6. Turnigy 1300mAh 2S 20C Lipo Pack


All of the drones power comes from our 2S 1300 mAh Lithium Polymer battery (Figure 6). The specifications for our battery are:

Minimum Capacity: 1300mAh
Configuration: 2S1P / 7.4v / 2Cell
Constant Discharge: 20C
Peak Discharge (10sec): 30C
Pack Weight: 81g
Pack Size: 73 x 35 x 17mm
Charge Plug: JST-XH
Discharge plug: XT60

At 3.7V per cell our 2S battery will deliver a nominal 7.4V from the contacts on the power distribution board. The 2S indicates that we have two cells in series so the sum of the two cells voltage is the output voltage. As an aside, cells in parallel add to the batteries capacity (i.e. mAh) not voltage.

Figure 7. BeagleBone connected to LiPo

The BeagleBone Blue includes a 2-cell LiPo battery charger with balancing, and an LED state-of-charge monitor. The state of charge LED's are shown in Figure 7. They are just above the 3-pin JST XH battery charging connector.

One of our considerations when mounting the BeagleBone is that we will need access to the JST XH connector in order to get power off the micro-controller. We will also need access to the XT60 in order to power down the distribution board. Ideally the battery needs to be less than 50mm from the BeagleBone or we will need to extend the charging cables.

Figure 8. Racerstar Quad 20A ESC.

The other modules we will need to power are:

  • The Racerstar BLHeli_S 20A Quad Electronic Speed Control - shown in Figure 8 (connects to the battery, receiver and the four motors). It doesn't have a BEC (Battery Elimination Circuit) to provide a regulated supply but the BeagleBone does.
  • The UBLOX Micro M8N GPS Compass Module - shown in Figure 9. This module expects a regulated 5V on VCC but control voltages are 3.3V (see Figure 10). The BeagleBone supplies 3.3VDC and 5VDC power output via 4 pin JST connector.
  • The FrSKY X8R 2.4Ghz SBUS Receiver. The receiver will also need to be connected to the regulated 5VDC bus.

Figure 9. The UBLOX Micro M8N GPS Compass Module.


The overall power distribution block diagram is shown in Figure 11. The 3 wire LiPo charging cable will connect directly to the BeagleBone as mentioned above. We will then have two power buses, 7.4VDC which powers the ESC and 5VDC to power the GPS and Receiver modules.

Figure 10. GPS Compass Module connections.


When building robots I have had problems when there is a common supply for the motors and the micro-controller. The current surge when starting the motor can bring down the voltage to the micro-controller and cause it to reboot. It may not be an issue with the drone since the motors are always on. The bench test will demonstrate whether this is going to be a problem.

In part 2 we will cover the control wiring required for our drone.



Figure 11. Falcon DS1 Power Distribution.

Monday, August 19, 2019

Tello Drone, Swift and State Machines (Part 2)

Stop Rolling Your Own State Machine Code



FIGURE 1. The Flight Plan iOS App


This sub heading is aimed at me to serve as a reminder to stop reinventing the wheel! A lot of the apps that I write benefit from having a Finite State Machine computational model. In an earlier article I wrote about controlling the Tello drone remotely using Swift. If you have a look at this code you will see that I have implemented a simple state machine to track the state of the drone. You need this because you can't send the drone a command unless WiFi is connected and the drone is in command mode (activated by sending it the "command" string via UDP). Thus our app responds differently depending on what state the drone is in.

I felt justified in writing my own state machine code because the initial application was relatively simple. If I was writing a game then I would always use GKStateMachine, the state machine class provided by Apple as part of game kit, but because this is a utility and I was in the UIKit headspace as opposed to the SceneKit/GameplayKit space I didn't think about it. But there is no reason you can't use GameplayKit classes in your UIKit app and in retrospect that is what I should have done (and just spent a day refactoring my code to do). Insert face palm emoji here!

I have continued to add functionality to my drone control app and as the complexity increased my home grown state machine started to become part of the problem and not the solution. Due to the organic development process (i.e. unstructured), I ended up with two state machines which were not scaling well. More importantly the app was acting weird and ending up in undefined states. Of course I could have fixed this in time, but I realised that Apple have already spent a lot of time putting together a robust state machine class and I should be using that!

FIGURE 2. Drone State Machine Diagram

The collateral benefit of having to refactor my code using GKStateMachine was that it made me sit down and plan out what states I needed and what would cause a transition. In other words I needed to develop a state transition table or diagram (Figure 2). After doing this exercise it became apparent that I didn't need two state machines, I just needed to add two states to the original machine. In addition, being forced to come up with the table made me think about some states and/or transitions that I wasn't handling.

TL;DR - Use GKStateMachine even for simple applications!

To demonstrate how easy it is, I will include the boiler plate code for my drone app.

STEP 1 - Create the state classes


For every state in your FSM you need a class to handle transitions, etc. Typically you will need to override the functions shown. I have included the outline for the disconnected state class below. The other state classes have exactly the same format but with different names.

//
//  DisconnectedState.swift
//  FlightPlan
//
//  Created by David Such on 18/8/19.
//  Copyright © 2019 Kintarla Pty Ltd. All rights reserved.
//

import Foundation
import GameplayKit

class DisconnectedState: GKState {
    unowned let viewController: ViewController
    
    init(viewController: ViewController) {
        self.viewController = viewController
        super.init()
    }
    
    override func didEnter(from previousState: GKState?) {
        viewController.statusLabel.text = "DISC"
        viewController.WiFiImageView.image = UIImage(named: "WiFiDisconnected")
        
        if !UserDefaults.standard.warningShown {
            viewController.showAlert(title: "Not Connected to Tello WiFi", msg: "In order to control the Tello you must be connected to its WiFi network. Turn on the Tello and then go to Settings -> WiFi to connect.")
            UserDefaults.standard.warningShown = true
        }
    }
    
    override func willExit(to nextState: GKState) {
        
    }
    
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {
        return (stateClass == WiFiUpState.self) || (stateClass == PlanningState.self)
    }
    
    override func update(deltaTime seconds: TimeInterval) {
        
    }

}

A couple of points. Firstly, make sure that you import GameplayKit. Second, note the constant definition:

unowned let viewController: ViewController

In my app this is the main view controller which contains the UI and will never be NIL. To prevent a retain cycle we use unowned (and not weak since that view controller can never be NIL).

This constant is used to update the UI based on state changes (alternatively you could use a delegate).

STEP 2 - Define the State Machine


Next, within the view controller referred to in step 1, you need to define your state machine.

//
//  ViewController.swift
//  FlightPlan
//
//  Created by David Such on 3/6/19.
//  Copyright © 2019 Kintarla Pty Ltd. All rights reserved.
//

import UIKit
import GameplayKit

class ViewController: UIViewController {
    
    lazy var stateMachine: GKStateMachine = GKStateMachine(states: [
        DisconnectedState(viewController: self),
        WiFiUpState(viewController: self),
        CommandState(viewController: self),
        PlanningState(viewController: self),
        ManualState(viewController: self),
        AutoPilotState(viewController: self)
        ])

As shown above, this is very straight forward. A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration. We need this so that we can assign a pointer to the class containing our state machine (i.e. viewController which is an instance of ViewController) after it has been initialised.

STEP 3 - Use the State Machine


Now we can use our new state machine to keep track of the drone state and handle transitions between states. The first thing you will want to do is to set the initial state. For our drone this is the disconnected state.

stateMachine.enter(DisconnectedState.self)

You will probably do this in the viewDidLoad method of viewController. Then you can change states when the appropriate event is triggered. For example, the following method is called when the take off button is tapped.

@IBAction func takeOffTapped(_ sender: UIButton) {
        switch stateMachine.currentState {
        case is DisconnectedState:
            showAlert(title: "Not Connected to Tello WiFi", msg: "In order to control the Tello you must be connected to its WiFi network. Turn on the Tello and then go to Settings -> WiFi to connect.")
        case is WiFiUpState:
            showAlert(title: "Awaiting CMD Response", msg: "We haven't received a valid response to our initialisation command. Try sending again from Setup.")
        case is CommandState:
            tello.takeOff()
            stateMachine.enter(ManualState.self)
        case is PlanningState:
            if tello.flightPlan.count == 0 {
                let zoom = scrollView.zoomScale - 0.25
                let pitch = dronePointer.frame.size.height
                
                tello.flightPlan.append(CMD.takeOff)
                dronePointerCenter.y -= pitch
                UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut, animations: {self.dronePointer.center = self.dronePointerCenter}, completion: nil)
                scrollView.setZoomScale(zoom, animated: true)
            }
        default:
            break
        }

    }

Depending on the current drone state (stateMachine.currentState) we want to perform different actions. To take off manually, we need to be in the command state. In the planning state, we add the take off command to our flight plan, and animate the action on our viewController.

One last tip. In the example above we are using switch for program control to handle the various states. If you want to check the current state against only one state don't use "==". It wont compile. You need to use "is" instead. For example, to check if the current state is Auto Pilot, you would use:

if stateMachine.currentState is AutoPilotState {
            tello.stopAutoPilot()
}

That's it. Next time you need a state machine, don't write your own! Hop on over to GameplayKit and grab GKStateMachine.

Saturday, June 8, 2019

Programming the Tello Drone using Swift (Part 1)

The Tello Drone




In this article we will explore how to write a simple iOS app in Swift to allow control of the Tello.

Tello is a mini drone equipped with a HD camera that is manufactured by Ryze Robotics and includes a flight controller with DJI smarts. It is a great drone to learn to fly on as you can use it indoors and because it is so light (80 grams), crashing is fairly painless if you have the prop guards on. I have crashed mine (a lot) and the worst that has happened is that a propeller came off, which is easy to replace. It is also relatively inexpensive. You can manually control it using either an app (iOS or Android) on your phone, or a combination of the app and a dedicated Bluetooth remote. Either works fine. If you do get the Bluetooth remote be careful of not moving out of Bluetooth range of your phone while you are flying the drone.

Tello Specifications


Tello is Powered by a DJIGlobal flight control system and an Intel processor (Movidius MA2x chipset). The MA2x is based on a SARC LEON processor which has two RISC CPUs to run the RTOS, firmware, and runtime scheduler (Ref: RyzeTelloFirmware). The other specifications are:

  • Weight: Approximately 80 g (Propellers and Battery Included)
  • Dimensions: 98×92.5×41 mm
  • Propeller: 3 inches
  • Built-in Functions: Range Finder, Barometer, LED, Vision System, 2.4 GHz 802.11n Wi-Fi, 720p Live View
  • Port: Micro USB Charging Port
  • Max Flight Distance: 100m
  • Max Speed: 8m/s
  • Max Flight Time: 13min
  • Max Flight Height: 30m

Programming - Firmware Versions


Apart from being a good platform to earn your flying chops, the best thing about the Tello from my perspective is that you can write a script or a program to control the drone remotely. This opens up a lot of possibilities.

Note that there are three different Tello's that you can buy (the Tello, the newer Tello EDU and the Ironman Edition), and they use slightly different API's. So make sure that you use the appropriate version for your drone.

You can work out which firmware you have by connecting your mobile to the Tello WiFi, opening the Tello app, tapping on settings (the gear icon), then tap on the More button, and finally tap on the "..." button to the left of the screen. This should bring up the screen shown below which includes the firmware and app version numbers. My Tello is running firmware version 1.03.33.01. You can download the relevant SDK document for this version.



The Tello EDU uses version 2.0 of the SDK. You can download a PDF of the V2 SDK from here.

Commands that are available in SDK v1.3 but not v2.0 are:

  • height?
  • temp?
  • attitude?
  • baro?
  • acceleration?
  • tof?

Conversely, commands that are available in SDK v2.0 but not v1.3 are:

  • stop (hover)
  • go x y z speed mid (same as go x y z speed but uses the mission pad)
  • curve x1 y1 z1 x2 y2 z2 speed mid (same as curve x1 y1 z1 x2 y2 z2 speed but uses the mission pad)
  • jump x y z speed yaw mid1 mid2 (Fly to coordinates x, y and z of mission pad 1 and recognize coordinates 0, 0 and z of mission pad 2 and rotate to the yaw value)
  • mon
  • moff
  • mdirection
  • ap ssid pass
  • sdk?
  • sn?

The Tello EDU also has a swarm mode if you want to control a bunch of drones.

Programming - Python


There are plenty of examples on how to use Python to control your Tello. For drones running v1.3 have a look at the DroneBlocks code. For the Tello EDU (i.e. v2.0 SDK), Ryze Robotics provide some sample code for you to download and try out.

I uploaded the DroneBlocks code using my Raspberry Pi connected to the Tello WiFi and it worked a treat. Given that there are lots of Python examples, I thought I would put together something in Swift and work up to an app which provides additional functionality not found in the official Tello app.

Programming - Swift (iOS)


We access the Tello API by connecting to the airframe via a WiFi UDP port. Once a connection is in place, the drone is controlled using simple text commands.



The first thing we want to determine is whether our device is connected to the Tello WiFi. There are a couple of Swift functions which can assist with establishing this. The Tello SSID name contains the string "TELLO" (see image above), so this is what we will use to determine wether we are connected to the correct WiFi network.


We can use the code above in our ViewController to ensure that we are hooked up to the Tello, and if not provide an alert. The screenshot below shows this implemented in my proof of concept app.


The code for the ViewController is shown next. It should be fairly self explanatory.



UDP


UDP (User Datagram Protocol) is a communications protocol, similar to Transmission Control Protocol (TCP), but used primarily for establishing low-latency, low-bandwidth and loss-tolerating connections. UDP sends messages, called datagrams, and is considered a best-effort mode of communications. With UDP there is no checking and resending of lost messages (unlike TCP).

Both UDP and TCP run on top of the Internet Protocol (IP) and are sometimes referred to as UDP/IP or TCP/IP.

UDP provides two services not provided by the IP layer. It provides port numbers to help distinguish different user requests and, optionally, a checksum capability to verify that the data arrived intact.

The Tello IP address is 192.168.10.1. The UDP Services available are:

UDP PORT: 8889 - Send command and receive a response.
UDP SERVER: 0.0.0.0 UDP PORT: 8890 - Receive Tello state.
UDP SERVER: 0.0.0.0 UDP PORT: 11111 - Receive Tello video stream.

If you want to send and receive via UDP on iOS then the two main libraries in use appear to be SwiftSocket and GCDAsyncUDPSocket.

Swift Socket looks to be the simpler of the two libraries, so I used that for my initial attempt. I put together a Tello Swift class to do the heavy lifting. It is reproduced below and works as advertised. You will need to put together your own UI but if you hook up the relevant buttons in the View Controller then you shouldn't have any problem reproducing what I have done.

I will add a bit more functionality to the app (e.g. video) and then stick it up on the app store for download.



Wednesday, April 11, 2018

Arduino Self Levelling Drone (Part 5)

Loading the QuadCopter Firmware




The first step is to download the firmware and save it in your Arduino library directory. This zip file will include 3 Arduino sketches:

  1. YMFC-AL_setup.ino
  2. YMFC-AL_esc_calibrate.ino
  3. YMFC-AL_Flight_controller.ino

Download the setup sketch to your Arduino and open up the IDE serial monitor (Tools -> Serial Monitor) and follow the instructions. If you get any errors then the firmware author has an FAQ. DO NOT connect the battery at this stage.



The complete setup will look something like the following. Make sure that you assign the pitch, roll and yaw functions to different receiver channels. The usual setup is called mode 2 which assigns pitch to the right stick up/down, roll to the right left/right, throttle to the left stick up/down and yaw to the left stick left/right.

Make sure that you check the high, low and centre values for the four digital input channels from the receiver. The low should be close to 1000, the middle near 1500 and the high around 2000. I had to run setup a few times before the correct values were recorded.

===================================================

Your
  Multicopter
    Flight
      Controller

YMFC-AL Setup Program

===================================================
For support and questions: www.brokking.net

Have fun!

===================================================
System check
===================================================
Checking I2C clock speed.
I2C clock speed is correctly set to 400kHz.

===================================================
Transmitter setup
===================================================
Checking for valid receiver signals.. OK

Place all sticks and subtrims in the center position within 10 seconds.
9 8 7 6 5 4 3 2 1  

Center positions stored.
Digital input 08 = 1492
Digital input 09 = 1492
Digital input 10 = 1516
Digital input 11 = 1492


Move the throttle stick to full throttle and back to center
Throttle is connected to digital input 10
Channel inverted = no


Move the roll stick to simulate left wing up and back to center
Roll is connected to digital input 8
Channel inverted = no


Move the pitch stick to simulate nose up and back to center
Pitch is connected to digital input 9
Channel inverted = yes


Move the yaw stick to simulate nose right and back to center
Yaw is connected to digital input 11
Channel inverted = no


Gently move all the sticks simultaneously to their extends
When ready put the sticks back in their center positions
Measuring endpoints....


High, low and center values found during setup
Digital input 08 values:1008 - 1492 - 1984
Digital input 09 values:1004 - 1492 - 1988
Digital input 10 values:1012 - 1516 - 1988
Digital input 11 values:1492 - 1492 - 1500
Move stick 'nose up' and back to center to continue

===================================================
Gyro search
===================================================
Searching for MPU-6050 on address 0x68/104
MPU-6050 found on address 0x68

===================================================
Gyro register settings
===================================================
Register 0x6B is set to:0
Register 0x1B is set to:1000

===================================================
Gyro calibration
===================================================
Don't move the quadcopter!! Calibration starts in 3 seconds
Calibrating the gyro, this will take +/- 8 seconds
Please wait....................
Axis 1 offset=-99.78
Axis 2 offset=-66.14
Axis 3 offset=-60.42

===================================================
Gyro axes configuration
===================================================
Lift the left side of the quadcopter to a 45 degree angle within 10 seconds
OK!
Angle detection = 1
Axis inverted = no
Put the quadcopter back in its original position
Move stick 'nose up' and back to center to continue


Lift the nose of the quadcopter to a 45 degree angle within 10 seconds
OK!
Angle detection = 2
Axis inverted = yes
Put the quadcopter back in its original position
Move stick 'nose up' and back to center to continue


Rotate the nose of the quadcopter 45 degree to the right within 10 seconds
OK!
Angle detection = 3
Axis inverted = yes
Put the quadcopter back in its original position
Move stick 'nose up' and back to center to continue

===================================================
LED test
===================================================
The LED should now be lit
Move stick 'nose up' and back to center to continue

===================================================
Final setup check
===================================================
Receiver channels ok
Gyro axes ok

===================================================
Storing EEPROM information
===================================================
Writing EEPROM
Done!
Verify EEPROM data
Verification done
Setup is finished.
You can now calibrate the esc's and upload the YMFC-AL code.

After the setup is completed all the settings are stored in the EEPROM of the Arduino.



Checks and Calibration


The following is reproduced from the web site of the firmwares author.

To make sure that everything is working correct it's necessary to run some basic checks. Remove the props, disconnect the flight battery and upload the ESC calibration program to the Arduino. Open the serial monitor at 57600baud.

Receiver input check


Send the letter 'r' to start the receiver monitor. Now move the sticks and see if the values on the screen correspond with the movements of the sticks.


All the channels should read 1000us till 2000us with a center position of 1500 (+/-8).


Gyro / accelerometer angle check


After the receiver check is completed send the letter 'a' to start the angle check.


Don't move the quadcopter because the gyro needs to calibrate itself. After the calibration the roll and pitch angles are shown. The yaw value is the output of the gyro and will go back to zero if the yaw rotation stops.


Check if the angles correspond with the movement of the quadcopter:

Nose up is positive pitch and nose down is negative pitch.
Left wing up is positive roll and left wing down is negative roll.
Nose right is positive yaw and nose left is negative yaw.

Calibrate the ESC's


Electronic speed controllers or ESC's for short are controlled with a 1000us till 2000us pulse. 1000us means off and 2000us means full throttle. To make sure that all the ESC's react the same way it's important to calibrate the 1000us and 2000us point. Without calibration the motors will perform different and the quadcopter doesnt fly well or might even crash.


Remove the props and upload the ESC calibration program to the Arduino. Disconnect the USB cable and follow the instructions in the manual to calibrate the ESC's.




In most cases ESC Calibration works as follows:
  1. Throttle to minimum and turn on the transmitter.
  2. Place the throttle stick in the upper position (full throttle).
  3. Connect the flight battery.
  4. Wait for your ESCs to emit a musical tone, the number of beeps indicates your battery’s cell count (i.e. 3 for 3S, 4 for 4S) and then an additional two beeps to indicate that the maximum throttle has been captured.
  5. Pull the transmitter’s throttle stick down to its minimum position.
  6. The ESCs should then emit a long tone indicating that the minimum throttle has been captured and that calibration is complete.
  7. f the long tone indicating successful calibration was heard, the ESCs are now “live” and if you raise the throttle a bit they should spin. Test that the motors spin by raising the throttle a bit and then lowering it again.
  8. Disconnect the flight battery

If possible check the manual of your specific ESC for the correct calibration procedure. The ones I purchased didn't come with any instructions but the above procedure worked.

It was at this stage that I smoked a couple of my ESC's and motors. I don't know what caused this but replacing them got everything working. I suspect that the cheap ESC's and motors may have some quality control issues. If you do buy the cheap ones that I purchased then I suggest getting an extra set. In retrospect I would probably buy better quality ESC's and motors to avoid the aggravation of having to re-solder everything. If smoke starts coming out of your ESC's or motors (or anything for that matter) disconnect the battery immediately! If smoke is just coming out of the motors, replace both the ESC and the motor, I burnt out an extra motor because I didn't do this.

Burnt out ESC - you can see where it melted through the heat shrink.

It is also possible to calibrate the ESC's individually but you need to do this before you cut off the servo plugs on the ESC control cables and solder them to the Arduino. For completeness the procedure for individual calibration is:

  1. Plug one of your ESC three-wire cables into the throttle channel of the RC receiver. (This is usually channel 3.)
  2. Turn on the transmitter and set throttle stick to maximum (full up).
  3. Connect the LiPo battery
  4. You will hear a musical tone then two beeps.
  5. After the two beeps, lower the throttle stick to full down.
  6. You will then hear a number of beeps (one for each battery cell you’re using) and finally a single long beep indicating the end points have been set and the ESC is calibrated.
  7. Disconnect battery. Repeat these steps for all ESCs.
  8. If it appears that the ESC’s did not calibrate then the throttle channel on the transmitter might need to be reversed.
  9. If you are still having trouble after trying these methods (for example, ESCs still beep continuously) try lowering your throttle trim 50%.

You shouldn't need to do individual calibration but it is available if the all at once method doesn't work.

Attach the Propellers


Attaching a collet style prop adapter is not obvious the first time you attempt it. This is probably one of the most common prop adapter you see people using. It has a collet that grabs the smooth motor shaft when propeller nut and washer is tightened down.

The first step is to slip the collet onto the motor shaft. This should be a tight fit, otherwise it is difficult to screw down the nut without everything spinning. Some people suggest putting Loctite on the shaft, this is probably not a bad idea but wait until you have performed all the tests below and are doing the final tighten up before flying. I tried it without Loctite but on the first flight the propeller spun off, luckily it was still on the ground at the time. So I went back and put Loctite on the motor shaft and the propeller nut. Make sure that none of it drips down into the motor. I used the blue Loctite so that there was some chance I could get it off when I needed to replace a propeller. The red Loctite requires heat to remove it, which is a problem if you have plastic propellers.



Next slip on the spacer which grabs the bottom of the propeller. Make sure that you put it the right way around.



Finally put on the propeller and screw down the prop nut to keep everything in place. Note the props are designed to be clock wise or counter clockwise. They normally come in pairs. Make sure you mount the correct prop on each motor (refer to Figure 1 below). You want the leading edge of the props to face in the direction of the rotation shown below. The leading edge is the highest edge on the prop.



You can use a drill bit or similar to tighten the prop nuts, these need to be secure but be careful not to strip the aluminium thread. Finger tight should work.



Check Rotation Direction and Balancing the Propellers


The next step is to check that the props are spinning in the right directions and that they are balanced. Adjacent props spin in the opposite direction to keep the drone from yawing. This provides a similar function to the tail rotor on a helicopter. The props need to be balanced to minimise vibration which will prevent the gyro and accelerometer from self levelling.



We will again use the ESC calibration software for these checks. For convenience we have reproduced the balancing instructions from the Brokking.net web site. You shouldn't need to reload the ESC calibration software.

Make sure that you hang onto the drone when you test with the propellors mounted. Learn from my mistake - even one propellor has enough lift to flip the drone off the table and onto the floor!

TAKE CARE WHEN DOING THE FOLLOWING TESTS - THE DRONE CAN BE DANGEROUS WITH THE PROPELLERS INSTALLED!!! MAKE SURE YOU TAKE APPROPRIATE PRECAUTIONS, KEEP FINGERS CLEAR OF PROPS AND WEAR SAFETY GLASSES.

Mount the props on the motors and check if the counter clock wise and clock wise props are in the right position. Upload the ESC calibration program and open the Arduino serial monitor at 57600baud. Send '1' via the serial monitor and wait for the response "Test motor 1 (right front CCW.)".

The numbers that are printed on the screen represents the amount of vibration measured by the accelerometer. This is not a standardized value and should only be used to minimize the amount of vibration of your YMFC-AL quadcopter.

Hold the quadcopter firmly down, place the throttle in the lowest position and connect the flight battery. Now slowly increase the throttle until motor 1 starts to spin. Check the direction of rotation and that the prop produces upward thrust. If the motor rotates in the wrong direction you need to switch two of the three motor wires. Put the throttle in the lowest position to stop the motor.

Now hold the motor frame firmly in your hand and increase the throttle to half throttle. Check the numbers on the screen and also memorize the vibrations that you feel with you hand that is holding the motor frame.

Stop the motor and put a small piece of tape on one of the blades and run the test again. Check if the vibrations reduce. If nor try a piece of tape on the other blade. Keep doing this until the motor and prop run as smooth as possible. This can sometimes be a daunting task but the reward is a very stable flying quadcopter. So take your time and get it perfect!

When done with motor 1, send a '2' via the Arduino IDE and start the process again for motor / prop 2. And after that, send a '3' for motor number 3 and a '4' for motor 4. By sending a '5' all the motors will run together as a final test.




Flight Controller Software


We are finally ready to load the flight controller software. Disconnect the battery and upload the YMFC-AL_Flight_controller sketch to the Arduino. When done, disconnect the USB cable and find a spot to test your drone.

Always turn on your transmitter (with throttle in the minimum position) before connecting the flight battery. This is a good habit to get into.

Hold the quadcopter firmly in your hand and start/stop the motors with the following sequence:

Start = throttle down and yaw left
Stop = throttle down and yaw right

If you have flown any DJI drones this may be the opposite to what you are used to. We want to test the start/stop function before we do anything else.

Start the engines again and increase the throttle up to the point when it almost starts to become weightless. The quadcopter should now try to level itself. If you move the quad it should start to counteract the movement until it is level again. This is an important step, you need to make sure that the drone is balanced and able to self level before you try and fly it in the wild. If you don't it may be very difficult to fly - I learned this the hard way...

When the roll or pitch stick of the transmitter is moved the quadcopter should move in the same direction. If this is not the case redo the setup procedure and double check the settings.



Next up we will cover the procedure for the first flight. You need to become familiar with the rules for flying drones in your local area, particularly if you are going to be stupid enough to post a video on YouTube of you doing the wrong thing. CASA is watching!