Friday, August 21, 2020

Raspberry Pi-Zero ArduPilot PCA9685

Raspberry Pi-Zero ArduPilot

RZero




Index

Index 2

Introduction 3

DIY Raspberry Pi Zero Ardupilot  “R-ZERO” 6

Design Decisions 6

I2C ServoDriver 7

Technical Specification: 9

How to Start 10

Important Notice: 10

Conclusion 11

Useful Links 11



Introduction


Flight Control Board FCB is essentially a microcontroller board that reads input from sensors and

remote control  and processes these inputs based on algorithms that determine the output signals

that rotate servos and motors to drive/fly the vehicle.





FCB board normally contains beside a microcontroller some of sensors mainly gyro, acc, mag

& barometer on the same board. While GPS normally comes as a separate part and connects

to a socket on the board. 


So almost any board can be turned to FCB if we attach the right sensors and provide a way for

RC-in & RC-out. This is true. But from a Software perspective writing autopilot systems using

today's features is almost an impossible task for one person. And even if we have the talent. 

we will never have the time spent in testing and validating features by all ardupilot users.


Fortunately,  Ardupilot, the best open source autopilot already supports running on Linux.

Please check this here we find the following list:



The very nice thing about the above list is the existence of Raspberry Pi based boards such as NAVIO2. That is what we are looking for because since ardupilot is open source then we will find many reusable
modules for RPI and a model to follow to define our board. 




Even better we can find PXFmini board. It is a Raspberry PI Zero based board. 



DIY Raspberry Pi Zero Ardupilot  “R-ZERO”


From this point it seems we have a very good start. We will see how there are many reusable

Raspberry Pi codes. Most of them are very critical and not an easy task to write from scratch.

However as we mention above in our pseudo definition of FCB, FCB is processor & sensors

which is not the case for RPi-Zero. PXFmini consists of two boards, one of them is Raspberry Pi Zero

and the other is a board that holds sensors, RC-in & RC-out pins.


Now we only have Raspberry Pi Zero, and we need to make our second board. 


Our second board should contains:

  1. RC-in: to read signals from RX.

  2. RC-out: to output signals to motors.

  3. Sensors: to identify vehicle status and location.

    1. Gyro

    2. Acc

    3. Compass

    4. Barometer

    5. GPS

    6. Volt & Amp sensor for battery.

  4. LEDS to display status.



Design Decisions


Let us first start with GPS as it is the easiest part. We only need to connect GPS TX/RX with

Raspberry Pi Zero TX/RX and it will work with no code changes. We only need to add a parameter

in the ardurover command to initialize the serial port. So no extra hardware is needed here.


For RC-In the good news is that Ardupilot already has a reusable code, a class called RCInput_RPI

for this part, you can even edit GPIO ports to use and even determine if you want to use 4 or 8 channels

or a number in between. This class is complex and advanced. I am glad I found it ready to use.

Again no extra hardware is needed here.


For LEDs again we can find a reusable code, a class called GPIO_RPI that is ready to use.

Although there is no extra hardware interface but we had to add LEDs each LED is connected in

series with a 10K resistor to limit the current and avoid burning out GPIO bin.


Now let's discuss harder parts. I used GY-80 with the following sensors:

  1. L3G4200D (3Axis Gyroscope  2.4-3.6V)

  2. ADXL345 (3 Axis Accelerometer. 2v- 3.6v)

  3. HMC5883L (3-Axis Magnetic compass 2.16v-3.6v)

  4. BMP085  (Pressure Sensor. 1.62v- 3.6v)


Again we are lucky as all these drivers already exist in Ardupilot code. Unfortunately Gyro & Acc

composite driver has some issues in implementation in the original Ardupilot repository.

So I had to rewrite it in a new way that is compatible with the way Ardupilot handles drivers

and their definitions. Technical details of these changes can be found here.

The reason I believe why this driver was somewhat buggy is due to it not used at all in the code so

it seems to be obsolete. However I found later an upgrade for this driver in another forked repository

but I believe my update is more compatible with the latest code style they use to call drivers.


This part was the first part I work on in this project, so I spent some time figuring out how to define a

board and attach sensors to it. Also what a correct driver software layout is. The problem I faced here

was that I use a composite sensor with I2C connection. PXFmini uses SPI connection and another

MPU sensor which is by the way available to buy but it was not available in the store at that time.


RC-out: This should not be the hardest part. Actually it should be a trivial part. Raspberry Pi boards

uses a 16-channel-pwm-servo-driver called PCA9685  this part has a defined driver in Ardupilot code

in a class named RCOutput_PCA9685. The last piece of this driver was sold moments before I asked

for it. And I failed to find it in electronic shops where I live. So I decided to build my own RC-output.

The system I have built is actually heavily based on multiwii code.

Multiwii is a very famous quadcopter firmware that can run other vehicles. It has been left with no

updates since 2016. CrazyFlight and similar firmwares are descended from Multiwii but support

STM32FX based flight controllers.



I2C ServoDriver


Well, this is considered an independent project that can be used in many other projects.

However, I had to build it as part of R-Zero project.

As I mentioned Multiwii is a very famous flight control firmware. However its feature is

not our concern here. What we really care about is its code for controlling actuators such as

servo and motors. And its built in configurations for many vehicles.

Besides it is a relatively very easy code to explore compared to Ardupilot.

I used to play with Multiwii many years ago, I have even  transferred it to ArduinoDUE.

Anyway this was in the past, now we need to think of this code as a motor driver,

that we can send to it commands via I2C and it translates it to meaningful signals for

motors and servos. So I started by removing all unnecessary code from Multiwii.

And I added I2C slave code that receives code from Raspberry Pi via I2C.

Received values are directly injected into motors and servos with no mixing.

A safety feature was added to send MINCOMMAND value to motors if no signal is received

from I2C with a defined timeout.


I also had to write a driver basically cloned from RCOutput_PCA9685

called RCOutput_MW_I2C. It uses simpler commands but basically the same approach.


Using config.h we can define our vehicle actuators. I had to add MW_I2C_Rover as rovers

were not defined in this code. But many other vehicles are defined. However I must highlight that

I tested only on rover. So please check it carefully before you connect motors and propellers.

You can use simple small blue servos for testing, and you might need to remap output channels

in a function called mixTable().


Code for this project can be found here.


Problems

I found some problems with I2CServoDriver maybe because of conflicts between i2c slave

and timers used to generate pwm. Servos glitches with no good reason.

Anyway I could finally get PC9685 board and I activated RCOutput_PCA9685 and it worked

like a charm.

Technical Specification:


  1. MPU GY-80 communication using I2C protocol with I2C Device Addresses:

    1. I2C Address 0x1E is the HMC5883L

    2. I2C Address 0x53 is the ADXL345

    3. I2C Address 0x69 is the L3G4200D

    4. I2C Address 0x77 is the BMP085

  2. GPS UBlox connected to TX/RX directly.

  3. RC-In: using GPIO:  GPIO 5, 6, 12, 22, 27, 20, 21, 26.

  4. RC-out: using Arduino D11, D9, D3 & D10. where D9 is a motor output for Throttle. & D11 for Steering in the rover.

  5. For PCA9685 channels 1 & 3 are used and GPIO27 is used for enable the chip (not used in my code).


How to Start

First we need to compile ardupilot RZero branch. Using command: $ make rzero-rover

Then we can find the binary in subfolder ardupilot/build/rzero/bin/ardurover



We need to copy this file to Raspberry Pi Zero in /home/pi you can copy it in many ways, one of them is to open SDCard on your laptop and manually copy the file. Another easier way is to copy it using scp command.


scp ./build/rzero/bin/ardurover pi@YourRPI_IP:.


That is it.


When I run ardurover I choose it not to start until I connect to it using MissionPlanner or QGroundControl -my favorite- so that I can monitor each and every step.


sudo ./ardurover -A tcp:MyLapIP:wait -C:/ttyAMA0


You can also use other options such as:


sudo ./ardurover -A udp:MyLapIP:bcast -C:/ttyAMA0


Notice: If you make your mobile Wifi Hotspot  it will take IP 192.168.43.246 which so you can add this network to your RPI zero and make it connect to your QGC on your mobile phone.


You can choose to remove “wait” and ignore initializing GPS in your first tests.



AutoRun Service

Create a file at: /lib/systemd/system/ardurover.service



[Unit]

Description=My Sample Service

After=multi-user.target

[Service]

Type=forking

ExecStart=/home/pi/ardurover -A udp:192.168.1.100:10100:bcast -C udp:192.168.1.139:14550:bcast

Restart=on-failure

[Install]

WantedBy=multi-user.target



Important Notice:


In the above version I ran ardupilot on pure linux. But Ardupilot need RealTime OS so we need to update the Raspberry PI OS and add Real Time Features. 


To do that you need to follow steps from this link. It is straightforward yet not easy.


IMPORTANT real-time OS is not mandatory if you only run ardupilot without running extra apps. At least for rovers.

The Fatal Bug

This was totally unexpected. I found a bug that crashes ardupilot on RPIZero randomly. I was due to using RCInput_RPI class. I took me a while to figure it out but I could finally fix it in this
[AP_HAL_Linux: Fix RCInput_RPI Segmentation Fault #14842].

Conclusion

In this project I learnt how to define a board of in Ardupilot, adding and updating sensors. It also required decisions about design and wiring.

Useful Links


  1. Building an autopilot from scratch using Raspberry Pi Zero: Mini Zee.

  2. PXFmini.

  3. Code with PCA9685 enabled with segmentation fault fixed https://github.com/HefnySco/ardupilot/tree/ppr_RaspberryZ_PCA9685

  4. Code with Arduino MW-I2C enabled with segmentation fault fixed

https://github.com/HefnySco/ardupilot/tree/ppr_RaspberryZ