Integration of Pixracer with Optical Flow PMW 3901

@ppoirier with my CX-OF sensor I read data coherent with inav driver, I wrote this Arduino sketch to test:

#include <SoftwareSerial.h>

SoftwareSerial ofSerial(10, 11); // RX, TX

uint8_t chr;
uint8_t buf[9];
uint8_t index = 0;
int X, Y;

void setup() {


void loop() {
  while (ofSerial.available() > 0) {
    chr =;

    if (index == 0) {
      if (chr != 0xFE) {

    buf[index++] = chr;
    if (index == 9) {
      if (buf[0] == 0xFE && buf[8] == 0xAA) {
        X = (int8_t)buf[2] * 256 + (int8_t)buf[3];
        Y = (int8_t)buf[4] * 256 + (int8_t)buf[5];
      index = 0;

and I obtain X and Y form OF. Follows an image from Arduino Serial Plotter, I was moving the sensor over my desktop in circle by hand

Cool Thanks @anbello ,
I will compare with my own test code tonight, and update here.
Thinking out loud for a moment; What about using an arrduino to emulate a PX4FLOW on I2C like a did for the TFMINI How to make the TFMINI rangefinder talk I2C? This way I am pretty sure that the EKF integration would be optimal…

With this type of board this is about the same footprint as the CX-OF

@anbello ok LOL now I remember why my code was different :slight_smile:


So I just ordered a Cheerson CX-OF because the above model is just 8 bit x-y values

The driver still needs to call it. The Skyviper F412 implementation is representative.
The key thing is that we have no means to configure the spi bus at runtime, so which is why the hwdef needs changing.

arducopter.apj (845.8 KB)
This is an fmu-v3 build with the pixartflow enabled on external SPI. Testing welcome please. It will only work for Pixhawk (and probably the mRo X2.1?), but not Cube, because the extra IMU on the Cube consumes that SPI bus (which is why there isn’t an external SPI port on the Cube carrier). I don’t have an fmu-v4 but will build a firmware so others can test. It turns out Revo-mini has an SPI port too, if that’s of interest to anyone.
Remember that you need a rangefinder as well, not just the flow sensor.
I’m still trying to decide the best way to push this, as it isn’t really desirable to consume the external SPI with a specific device. For fmu-v5 there is another problem, as the exposed SPI shares a timer for DMA with pwm 5 & 6, so you lose two DShot outputs if you enable the SPI (which is why its disabled by default).
The end state of all that is that at the moment I think it makes sense to have the hooks in OpticalFlow.cpp so that if the hwdef.dat defines the pixartflow, it will build for it, but not change the hwdef files in master: at least not until/unless the external SPI assignments get parameterised.

1 Like

arducopter-fmuv4.apj (806.1 KB)

This should work for Pixracer. Apart from adding in the defines for the device, SPI4 has been set up on the wifi port GPIO pins as below. The UART remains intact, so whilst the esp8266 that comes with the pixracer won’t fit if you have other cables in the connector, you could run a lead to it and it should still work. As above, I don’t have a pixracer, so this is untested.

define the 8266 port GPIOs as SPI4


1 Like

So others can see what I’ve done here, have a look at the following PR’s: - this adds a check for whether the board has HAL_HAVE_PIXARTFLOW_SPI defined, and if it does, builds in the driver. - this disables GPIO and adds in the SPI pin assignments on the wifi port, adds the device to the SPIDEV table and adds the HAL_HAVE_PIXARTFLOW_SPI define. Those changes are commented out, so that this doesn’t effect standard builds.

1 Like

Hi, i just wanted to ask, how do i edit and add codes? I am new here. Do I use a certain software for it?

Hi James, thank you for all the help you have given me so far, but how do i edit the CHibiOs programme


Start here to get the code:

Then follow the guide for your operating system to set up a build environment. I use Ubuntu.

When you’ve got all that sorted out and working, you need to find this file in your local copy of the source:

And make the changes I linked above.

The change to OpticalFlow.cpp is now in master, so you only need to change the hwdef.dat to set up the spi device and define HAL_HAVE_PIXARTFLOW_SPI



Hi James,
I wanted to ask… how to you read on write codes on the pixracer? Ive done the first two steps of your previous post.
And, i just wanted to say that I am very thankful for your time and help


It’s in the wiki, but once you’ve made the changes to the hwdef, from the top ArduPilot directory: “./waf configure —board fmuv4”, then “./waf copter —upload”, with the board connected on USB.
The dashes are double dashes (this forum doesn’t display them well).

The changes to set up the spi isnt as simple as adding

right? just to clariy


Like that,


Have a look here:

1 Like

Would uploading the .apj file above via missionplanner (load custom firmware) suffice? Or must I make changes. As i cannot open the .apj file, but i can click on the file via mission planner (load custom firmware)

Or can i just compile the codes that i have edited and change it into hex files, followed by uploading them as a custom firmware?

@rmackay9 Hi, um I wanted to ask how to upload the changes onto the pixracer. I am currently using arducopter 3.61. I made the changes to the hwdef text file that @james_pattison suggested. But im still not so clear as to how to upload it to the board. I saw online that you can load it as custom firmware. However, it wipes out the 3.6 version.

Hi, i am also facing the same issue. May i know how to upload the file into mission planner as i am using WSL (Windows Subsystem Linux) and it does not have access to USB serial peripherals, so the waf –upload option does not work over USB.
@rmackay9 @james_pattison
Is it possible to upload the changes in the hwdef file without wiping out the firmware already existing in the pixracer?

Thank you in advance.

Just compile a custom firmware with your changes using waf (you could easily find how-to with google). Then upload .apj to FC via MissionPlanner.