How Raspberry Pi Zero got Ardupilot, hopefully flies

Well, this is a story about how Raspberry Pi Zero got Ardupilot, hopefully flies away and gets back safely 🙂

I wanted to make this a professional looking PCB, with smd components, everything crammed on it, but for that, I might as well get a PXFMINI. I changed my thinking, and built a flight FC to be cheap, available, breadboard and DIY friendly, but still look professional. That’s why I use ready made breakout modules with sensors and had PCBs made by OshPark.

I bought an APM from 3drobotics a long time ago (well, at least technology-wise, it was a long time ago. 3 years maybe 🙂 ), and I really love it, still. I don’t really use all the features, but it’s nice to know they are there. I also really like like the opensource community behing it.

So, yeah, after a couple of years, it was time to upgrade. I wanted to get the Pixhawk, but then dad got me the tiny Intel Edison, and some time after that, the PiZero was announced. Needless to say, I did not get the Pixhawk. I didn’t want to use the Edison for testing, so I got me a PiZero from Pimoroni, and started googling on how to do it. I came across this website, from this guy. This made thing SOOOOOO much easier. Thanks Patrick!


Getting stuff (everything I used here)

Believe it or not, this is how I work… First I get an idea, then I buy the parts and finally figure out if it could work or not. Then buy proper stuff. I have lots of stuff haha 😀 I work on impulse 😀

Bare minimum needed:

  • PiZero (or any other Pi)
  • MPU-9250, 9-Axis Gyro+Accel+Magn
  • MS5611 barometric sensor
  • two sided proto PCB, if you dont want to test on ye’olde proto board
  • some wire and pins, female and male

Optional stuff, very useful

  • APM Power module to power the Zero
  • PCA9685 16 channel i2c pwm servo driver (already built module or the IC alone)
  • UBLOX gps module (be careful with chinese clones, some have the wrong flash IC, won’t save settings)
  • ADS1115 to provide voltage and amp measuring (already built module or the IC alone)
  • OLED ssd1306 I2C display (OR green, blue, amber leds with resistors. I chose the display, because it’s easy to connect, instead of those finicky little smd LEDs, plus it’s easier to read letters than blinky lights)
  • 1.5k resistor, 2.2k resistor
  • PWM to PPM converter if your RX doesnt have PPM
  • I also found MavPixel, a WS2812 I2C controller


Connecting it together part 1.

First, we connect the sensor modules, check if ArduCopter starts or not. If it does, we move to connecting the periferals.

GPIO broken out, connections to sensors

GPIO broken out, connections to sensors

APM piZero Proto

APM piZero Proto


Gyro and baro sensor are connected through same SPI bus, just have different CS (chip select) pin, which is controlled by software.

MPU9250 and MS5611 connections

MPU9250 and MS5611 connections

end part 1.


Getting ArduPilot software

You can use a different linux computer to get the software, edit the libraries to use the right orientation, cross compile and copy to PiZero…

Or you can compile on the Zero itself. Hassle-free, just takes longer… not much, tho. I’m going to go with that.

Install rasbian, download here, instructions also provided.
Connect to Pizero, either over ssh, or plug in your keyboard, type in:

sudo raspi-config

enter Expand Filesystem

enter Change User Password

enter Boot Options, Boot to CLI

enter Advanced Options, enable SSH, SPI, I2C, disable Serial.

add “enable_uart=1” in /boot/config.txt (this is to enable serial input for GPS)

save and restart


Now, we install RT-PREEMPT, which is RTOS patch, makes rasbian Real-time OS. Copy the commands from here, or even better, go to the original website, and check for new versions. This basically copies the precompiled kernel over our original one.

~$ sudo rm r /boot/overlays/

~$ sudo rm r /lib/firmware/

~$ cd /tmp

~$ wget

~$ tar xzf kernel4.4.9rt17.tgz

~$ cd boot

~$ sudo cp rd * /boot/

~$ cd ../lib

~$ sudo cp dr * /lib/

~$ sudo /sbin/reboot

Reboot and reconnect.

Install required software and ArduCopter 


  1. Clone code from github

    ~git clone

  2. Install GNU awk

    ~sudo apt-get install gawk

  3. Change MPU9250 orientation

    Open file: ardupilot/libraries/AP_InertialSensor/AP_InertialSensor_MPU9250.cpp

    Find and replace
    , _default_rotation(ROTATION_YAW_270)

  4. Enable PWM
    Open file: ardupilot/libraries/AP_HAL_Linux/HAL_Linux_Class.cpp

    Find and replace
    static RCOutput_PCA9685 rcoutDriver(PCA9685_PRIMARY_ADDRESS, true, 3, RPI_GPIO_27);
    static RCOutput_PCA9685 rcoutDriver(PCA9685_PRIMARY_ADDRESS, false, 0, RPI_GPIO_27);

  5. Disable RGB leds and enable OLED
    Open file: ardupilot/libraries/AP_Notify/AP_Notify.cppFind and replace

    AP_BoardLED boardled;
    NotifyDevice *AP_Notify::_devices[] = {&boardled};

    Replace with
    Display_SSD1306_I2C display;
    NotifyDevice *AP_Notify::_devices[] = {&display};

    Go to ArduCopter dir for copter, or ArduPlane if you want to compile for a plane.
    ~$ make pxfmini
  7. Test!


Connecting it together part 2.

Now, that we have a working ArduPiCopterZeroDroneFlyingMiniLinuxComputer (I’m so clever with names, I know), we can start connecting the peripherals.

First, we will add ADS1115 to monitor the battery. ADS1115 uses I2C to communicate so connect

  • GND – GND
  • VCC – 5v
  • SDA – SDA
  • SCL – SCL
  • Voltage wire from Power module – A0
  • Ampere wire from Power module – A1
  • ADDR – GND (set address to ‘0x48’)
ADS1115 connections

ADS1115 connections

ADS1115 connections

ADS1115 connections


2. Next connect the Power Module
There is a 6 pin connector on the PM, pinout as follows
(PLEASE, test with a multimeter, chinese clones CAN have cables the other way around, so black is vcc and red is gnd)

pin PM        action               pin on APM
1,2               5V                     any 5v, to provide power to PiZero.
3                  Current [I]         A1 on ADS1115
4                  Voltage [V]        A0 on ADS1115
5,6               Gnd                   any ground


3. To drive the servos or ESCs, we need PCA9685. It’s an I2C enabled pwm driver, so just connect it to any I2c pins, maybe the easiest is to hook it up to ADS1115. As said SDA to SDA, SCL to SCL, 5v to 5v, gnd to gnd, no rocket science there.There is, however, a catch with 5v power rail… Wiring it like this does NOT provide to 5v pin on the ESC/servo connectors. For multicopters, leave it as is, but if you intend to use servos, connect 5v to vcc pin on the module, maybe put a fuse between PCA and RPI, just to be sure. Me, I just remove 5v wire from ESC, and connect vcc power to PCA. Your choice.


4. UBLOX gps module… I have one chinese and one original from 3DR. Shell out for the high quality one… That’s all i’m gonna say.
Bunch of useless shit needs to be done to clones, for them to work properly. Majority of them have THE WRONG eeprom chip installed. Well wrong isn’t exactly a right word, since it’s “just” a wrong orientation. Either way, with clones, you’re left with a couple choices:

  • Get the correct chip from the internets
  • rewire the wrongly oriented chip
  • send configuration string to gps with rc.local everytime the pi boots, and completely forget about eeprom 🙂

The last one is probably the easiest, since you don’t even have to configure the GPS in Windows over FTDI converter. And that’s the one I intend to use. I could go into detail on how to set it with U-center, but I won’t, since it’s been done already.

If you have the one that was put together like it was supposed to be, just connect power and RX to TX and TX to RX. Nothing more to it. If you want to test it, just enter

cat /etc/ttyAMA0

and you should see gps sentences being sent over to you. If not, probably switch RX and TX, or repeat step: Getting ArduPilot software.


GPS connections

GPS connections

GPS connections

GPS connections

5. We need to be able to control the FC, so we connect PWM to PPM converter
On the converter, there are three “out” wires , the usual servo connector, gnd, vcc, signal (ppm). Connect vcc to 5v, gnd to gnd. For the signal input, we will need a voltage divider, since Rpi GPIO has 3v3 input max. connect it like a-so.. where R1 is 1.5Kohm and R2 is 2.2Kohm. This lowers the high 5v to acceptable 2.973v. So, Vin is PPM, OUT is gpio4

Voltage Divider Circuit Schematic

Voltage Divider Circuit Schematic

Voltage Divider on the left

Voltage Divider on the left

6. OLED is a simple I2C device, so connect the I2C lines any where on the board, pins, rpi or servo controller. SDA to SDA, SCL to SCL and 5v power.

7. Besides that shiny, tiny OLED screen, I also wanted a different form of visual notification, the kind that you can see from outer space 🙂 Something like IRIS has, or the Phantom. I stumbled upon MavPixel. It’s a diy Arduino pro mini project, that scans the telemetry, and controls up to 12 WS2812 I2C rgb leds accordingly. It also comes with GUI configurator, which is basically a copy of Cleanflight’s Led configuration program, so it should be easy to figure out.

When I get the LEDs, I will make another post, just for MavPixel.


I had some PCBs made from OSHpark. As always, the result is BEE-E-A-utiful

[Parts List]

[OSHpark pcb link]

ArduPilot PiZero

ArduPilot PiZero

ArduPilot PiZero

ArduPilot PiZero



  1. So I’m confused as to how to wire both a receiver and the PCA9685 to a set of ESCs. Do I need to splice the signal wire from the ESCs into both to allow manual and autonomous control?

    • Hi

      no, you don’t splice the wire. I use the PCA9685 module, and just connect the three wires to the module. there is no direct “manual” control, passthrough is passed through he APM. Connections are the same.

  2. Hello Matic,
    First of all, congratulations for the excellent work!
    I already ordered the PCB at OSH park, it was sent on June 13, 2018, but it should take a while to get here in Brazil.
    I have some doubts:
    Do I need to solder any components on the board?
    How do I connect everything? Stacking PCA9685 on Pi Zero and Purple PCB ArduPiCopterZeroDroneFlyingMiniLinuxComputer on top? Like a sandwich?

    • HI, Thanks 🙂
      Im sorry for the late reply, the notification was sent to spam…
      Except for the modules, NO, nothing else to solder on the pcb. I glued the PCA on the bottom of the board, and the other two, I soldered to the top. That, I stacked on the PIZero.

      I did start making a new tutorial about this, since I use RealTimePi OS, and Ardupilot code has changed a bit…. it will take me some time to finish tho…

      • Hello
        I received the PCB on June 25, came fast, they are beautiful !!!
        I have also received the MPU-9250 and MS5611.

        “I did start making a new tutorial about this, since I used RealTimePi OS, and Ardupilot code has changed a bit … .it will take me some time to finish tho …” – Awaiting for …

        My Cheerson CX20 gave total loss after the last drop, APM and GPS PCB cracked, so I’ll use what’s left over, Motors, ESC’s, RX’s and Batteries …

  3. Hello this is a great project.
    I want to ask how to set all the electronic like ESC, battery, servo?
    I want to build my own flight controller for plane.

  4. hello,
    this is a excellent work, I have two questions:
    the ppm broken problem on raspberry pi zero since arducopter 3.5 is it fixed?
    is this possible use external magnetometer?
    Best Regards.

        • hi

          what do you mean? you have to run it on RPI.
          connect it to MP with telemetry. I have never tried it with on-board USB.

          Something like this (taken from here)

          Running APM
          To run APM use the following (change APMrover2.elf to ArduCopter.elf or ArduPlane.elf if needed):

          sudo ./APMrover2.elf -A udp:
          Where is the IP address of the device with the Ground Control Station – your laptop, smartphone etc.

          Arguments specify serial ports (TCP or UDP can be used instead of serial ports) :

          -A is for telemetry
          -B is for external GPS
          -C is for secondary telemetry
          If you would like to transfer secondary telemetry over the UART port on Navio you can specify it like this:

          sudo ./APMrover2.elf -A udp: -C /dev/ttyAMA0

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.