DJI NAZA/Phantom/A2 CAN bus communication protocol - NazaCanDecoder Arduino library - RC Groups
Shop our Airplanes Products Drone Products Sales
Thread Tools
Jan 08, 2014, 03:18 PM
Makers gonna make...
pawelsky's Avatar
Discussion

DJI NAZA/Phantom/A2 CAN bus communication protocol - NazaCanDecoder Arduino library


After some time spent on decoding the DJI Naza GPS communication protocol I've decide to have a look at the CAN bus communication as well. To separate the two discussions I'm creating a thread dedicated to the CAN bus protocol.

Here is a picture with the NAZA v2 PMU CAN bus port pinout.
Name: pmu_can_port.jpg
Views: 622
Size: 86.6 KB
Description:
The connector used is Molex Micro-Fit 3.0, single row 4pin (43645-0400)
Make sure you do the connection right or you will fry your toys.

The CAN bus transciever inside the PMU is Texas Instruments HV232Q and the speed is 1Mbps.

From what I can see messages are sent in following format:

55 AA 55 AA ID ID ML ML <payload> 66 CC 66 CC

where
55 AA 55 AA is a message header
ID is a 2 byte message id
ML is a 2 byte (little endian) message payload length
66 CC 66 CC is a message footer

So far I've been able to receive messages with following ids:
ID = 03 10, ML = 3A 00 with CAN id 0x7F8 - which is the GPS data
Payload format is same as in the GPS module message 0x10, with the exception that no XORing is necessary.

ID = 04 10, ML = 06 00 with CAN id 0x118 - which is the compass data
Payload format is same as in the GPS module message 0x20, with the exception that no XORing is necessary.

ID = 21 09, ML = 0C 00 with CAN id 0x7F8 (sent every ~250ms) - which is the GPS module version data
Payload format is same as in the GPS module message 0x30

ID = 22 09, ML = 00 00 with CAN id 0x7F8 (sent every second) - it has no payload, seems to be PMU heartbeat

ID = 07 10, ML = 00 00 with CAN id 0x108 (sent every 2s) - it has no payload, seems to be OSD module heartbeat (causes the FC to send the following 3 messages)

ID = 02 10, ML = 78 00 with CAN id 0x090 (sent every 10ms) - seems to be OSD data message (see post#12 for details)

ID = 09 10, ML = B8 00 with CAN id 0x108 (sent every 20ms) - input/output message (see post#15 for details)

ID = 01 10, ML = 0E 00 with CAN id 0x090 - raw gyroscope data (see post#7 for details)

ID = 00 10, ML = 34 00 with CAN id 0x108 - TBD

ID = 26 09, ML = 23 00 with CAN id 0x7F8 (sent every 200ms) - Phantom smart battery data (see this post for details)

ID = D1 C0, ML = 04 00 with CAN id 0x1FE (sent every second) - looks like Phantom smart battery firmware version (see this post for details)

Following projects use findings from this thread:
- RemzibiOSD adapter
- MinimOSD adapter
- iOSD Naza-M v2 log to GoogleEarth KML converter
- PSEPA's Minim based OSD
- k7m's Naza Conncetivity

Data can be decoded using e.g. Teensy 3.1 board (you can get it for $17 from OSH Park)




You'll also need CAN transciever and 3.3V regulator (and optionally a MicroSD card for logging the data). Picture below shows the general wiring diagram.




To make things easier I've created an All-In-One shield (version 0.2 currently) with CAN transceiver, 3V3 power regulator and MicroSD socket. It fits nicely under the Teensy board and make the setup easy and compact. It has the CAN interface, 4 analog lines and 2 full serial ports broken out. You can build this shield yourself, the design is shared on OSH Park:
https://oshpark.com/shared_projects/VeJFD9qA

There is also a version for Teensy 3.2 (also in version 0.2 currently), that does not need the voltage regulator (as it uses the one built into Teensy 3.2), but adds built-in resistor dividers for the IO lines instead:
https://oshpark.com/shared_projects/MemVgGXH

Note that they ARE NOT meant for commercial use. You can download the designs, modify them and build the boards for yourself, but anyone selling it will violate this only restriction that I have.

So be fair and enjoy



Together with a tiny voltage divider (shown on the picture above) it can also be used to measure various voltages (e.g. from additional LiPos or sensors).
These dividers come in two flavors: one for 0-18.7V range and one for 0-5.4V range. You can find a library that simplifies the usage of the divider in this post.


If you want to experiment with the CAN bus data you can find a logger sketch for Teensy and a PC tool to read the logged data in this post.


Attached below you'll find a NazaCanDecoder library, that can be used to decode data sent by Naza v1/v2 + PMU via the CAN bus. To use it you will need:
* Adruino IDE 1.0.5 (other versions are incompatible with Teensy)
* TeensyDuino (tested with version 1.20)
* FlexCAN library (included in Teensyduino since v1.20 - see https://www.rcgroups.com/forums/show...&postcount=481, you can also download it separately from here)

NOTE: If you plan to use Teensyduino 1.34 or higher - READ THIS NOTE

In this post you will also find a beta version of the A2CanDecoder library which can be used to decode data sent by A2 controller.


Note that you should not power Teensy from USB and CAN bus at the same time as the power regulators will fight with each other, so don't connect the USB cable when the CAN shield is connected to the PMU and vice versa!

If you have to do that (e.g. to read the serial output via USB) you have two options:

1) disconnect the CAN +6V wire
2) cut the VIN-VUSB pad at the bottom of Teensy (note that after you do that you'll need to power Teensy from the CAN bus, or other external source every time when uploading a new sketch). Picture on the left is for Teensy 3.1, picture on the right is for Teensy 3.2

Name: vin_vusb_cut.jpg
Views: 292
Size: 40.5 KB
Description: VIN - VUSB cut for Teensy 3.1 Name: teensy_3.2_vin_vusb_cut.jpg
Views: 147
Size: 60.7 KB
Description: VIN - VUSB cut for Teensy 3.2

When compiling make sure you've selected Teensy 3.1, serial whichever you use and the CPU speed "96MHz (Overclock)"

Name: arduino_ide_config.jpg
Views: 770
Size: 71.8 KB
Description:

When writing your own code make sure the setup and loop functions have the following structure

Code:
void setup()
{
  // Initialize the CAN interface
  NazaCanDecoder.begin();
  <YOUR OTHER INITIALIZATIONS HERE>
}

void loop()
{
  // Read CAN messages
  NazaCanDecoder.decode();
  
  <YOUR CODE HERE>
 
  // Send heartbeat to the FC so it keeps sending the datata (not needed when you have iOSD connected as it sends this heartbeat itself)
  NazaCanDecoder.heartbeat();
}
The library is capable of reading smart battery data (overall voltage, charge percentage and individual cell voltage) from Phantom controller. This feature is disabled by default, to enable it the GET_SMART_BATTERY_DATA define shall be uncommented in NazaCanDecoderLib.h as shown below:

Code:
// Uncommnet to read smart battery data (if available) e.g. on Phantom controller
#define GET_SMART_BATTERY_DATA

NazaCanDecoder library changelog
------------------------------
Version 20171104
[FIX] fixed compensated heading calculation which is now using quaternions correctly
[FIX] minor correction in comments

Version 20160420
[NEW] added function getMotorOut to return motor outputs

Version 20150211
[FIX] extended roll angle range to -180 ~ 180 degrees
[FIX] using compensated heading calculated by FC
[NEW] added installation and wiring diagrams for AllInOne v0.2 shield
[NEW] updated comments

Version 20150111
[FIX] corrected the 0926 message id (was 2609).

Version 20150108
[NEW] added reading smart battery data (e.g. from Phantom controller). Use GET_SMART_BATTERY_DATA define to enable.

Version 20140921
[FIX] fixed inverted east/west heading
[NEW] updated examples to include DGPS fix indication
[NEW] added IO_1 - IO_4 defines for IO pin on AllInOne board v0.2
[NEW] added SPI.h include to logger example for compatibility with Teensyduino 1.20

Version 20140628
[NEW] added functions to get HDOP and VDOP (getHdop/getVdop)
[NEW] added DGPS fix indication
[FIX] corrected sign of the VSI value from GPS

Version 20140621
[NEW] added function to return non-tilt compensated heading (getHeadingNc)
[NEW] added fuction to return VSI from GPS (getGpsVsi)
[FIX] VSI (barometric) is now taken from message 1002 instead of 1009
[NEW] added additional comments
[NEW] added connection diagram with shields

Version 20140504_beta
[NEW] added heading tilt compensation
[NEW] added example that logs data to SD card
[NEW] added selection of output serial port in examples (SERIAL_PORT define). Deafault is the Teensy's USB port.

Version 20140414_beta
initial beta version of the library
Last edited by pawelsky; Nov 05, 2017 at 05:18 AM.
Sign up now
to remove ads between posts
Jan 10, 2014, 11:14 AM
Registered User
I'm very interested in that.

Did u manage to decode any data? I have a couple of STM32 boards and I'll make a simple CAN -> USART bridge to be able to encode/decode Naza CAN messages.

My plan is to get CAN data and feed a FSK Modem to send it trough my VTX audio channel and have a poor man telemetry.
Jan 10, 2014, 11:22 AM
Makers gonna make...
pawelsky's Avatar
Quote:
Originally Posted by trunet
I'm very interested in that.

Did u manage to decode any data? I have a couple of STM32 boards and I'll make a simple CAN -> USART bridge to be able to encode/decode Naza CAN messages.

My plan is to get CAN data and feed a FSK Modem to send it trough my VTX audio channel and have a poor man telemetry.
Yes, I'm using MCP2515 + TJA1050 16MHz CAN adapter connected to Arduino and I'm able to see the messages (including GPS and compass) coming.

Unfortunately they are incomplete, but that is probably because of the timing issues (Arduino is barely able to deal with messages coming at that speed). Will share results once I have something solid.
Jan 13, 2014, 02:38 PM
Makers gonna make...
pawelsky's Avatar
Arduino is not able to cope so I decided to give Teensy 3.1 a try (ordered, waiting for it to arrive). The power of ARM should be enough here, the price is reasonable, and it has build in CAN (no good library yet though) so no CAN controller should be necessary (only transceiver).

In the meantime I've done some analysis with the logic analyzer and I can confirm that the format of GPS, compas, and module version messages payload is the same as data coming from GPS. To make things simpler it is not mangled in any way so no XORing is necessary anymore.
Jan 18, 2014, 03:58 AM
Makers gonna make...
pawelsky's Avatar
After analyzing some logs (thanks Marv) I've managed to convince the FC to send messages as if there was an OSD connected by sending an empty payload message
ID = 07 10, ML = 00 00 with the CAN id 0x108
After that I started receiving following 3 messages:
ID = 02 10, ML = 78 00 with CAN id 0x090
ID = 09 10, ML = B8 00 with CAN id 0x108
ID = 01 10, ML = 0E 00 with CAN id 0x090

Once my Teensy arrives, we'll see what's inside of these messages
Jan 18, 2014, 04:53 AM
SirEdward
blimppilot@ph's Avatar
like
Jan 24, 2014, 03:37 PM
Makers gonna make...
pawelsky's Avatar

Message ID = 01 10 (CAN id 0x090)


OK, I think I know what the ID = 01 10 message means. It seems to be gyroscope raw data followed by sequence number.

Values in the message are stored in little endian.

55 AA 55 AA 01 10 0E 00 GX GX GX GX GY GY GY GY GZ GZ GZ GZ SN SN 66 CC 66 CC

HEADER
-------------
BYTE 1-4: message header - always 55 AA 55 AA
BYTE 5-6: message id (01 10 for gyro message)
BYTE 7-8: length (little endian) of the payload (0x000E hex or 14 decimal for the gyro message)

PAYLOAD
--------------
BYTE 9-12 (GX): gyroscope X axis raw data (x100, degree/s)
BYTE 13-16 (GY): gyroscope Y axis raw data (x100, degree/s)
BYTE 17-20 (GZ): gyroscope Z axis raw data (x100, degree/s)
BYTE 21-22 (SN): sequence number, increases with every message

FOOTER
-----------------
BYTE 23-26: message footer - always 66 CC 66 CC
Last edited by pawelsky; Feb 05, 2014 at 05:28 AM.
Jan 27, 2014, 05:46 AM
Makers gonna make...
pawelsky's Avatar
Teensy 3.1 has arrived, looks like I'm going to have a busy evening
Jan 27, 2014, 08:07 PM
Makers gonna make...
pawelsky's Avatar
Connected everything together and it seems to work. Looks like Teensy is fast enough and I'm getting all the messages that are being sent by Naza. So far so good...
Feb 02, 2014, 06:37 PM
sillygoo.se
ianwood's Avatar
Just found this thread having been interested in seeing if the messages on the CAN bus could be picked up using the Teensy. Well, done. Have you been able to identify any more of the messages? I'm curious if any of the flight control positions are reflected there and what other raw data may be present. Any chance of sharing some of your code?
Feb 03, 2014, 02:49 AM
Makers gonna make...
pawelsky's Avatar
Quote:
Originally Posted by ianwood
Have you been able to identify any more of the messages?
I think I've found the accelerometer values.

Quote:
Originally Posted by ianwood
I'm curious if any of the flight control positions are reflected there and what other raw data may be present.
So far I did not observe any values that would change in sync with the stick movements.

Quote:
Originally Posted by ianwood
Any chance of sharing some of your code?
No, no plans to share it at the moment.
Feb 03, 2014, 02:44 PM
Makers gonna make...
pawelsky's Avatar

Message ID = 02 10 (CAN id 0x090)


Message ID = 02 10 seems to contain data used by the OSD. Below what I've found so far:

Values in the message are stored in little endian.

55 AA 55 AA 02 10 78 00 LO LO LO LO LO LO LO LO LA LA LA LA LA LA LA LA AG AG AG AG AX AX AX AX AY AY AY AY AZ AZ AZ AZ GX GX GX GX GY GY GY GY GZ GZ GZ GZ AB AB AB AB Q0 Q0 Q0 Q0 Q1 Q1 Q1 Q1 Q2 Q2 Q2 Q2 Q3 Q3 Q3 Q3 XX XX XX XX XX XX XX XX XX XX XX XX NV NV NV NV EV EV EV EV DV DV DV DV XX XX XX XX XX XX XX XX XX XX XX XX CX CX CY CY CZ CZ XX XX XX XX XX XX XX XX XX XX NS XX SN SN 66 CC 66 CC

HEADER
-------------
BYTE 1-4: message header - always 55 AA 55 AA
BYTE 5-6: message id (02 10 for OSD message)
BYTE 7-8: length (little endian) of the payload (0x0078 hex or 120 decimal for the OSD message)

PAYLOAD
--------------
BYTE 9-16 (LO): longitude (double, radians)
BYTE 17-24 (LA): latitude (double, radians)
BYTE 25-28 (AG): altitude from GPS (float, meters)
BYTE 29-32 (AX): accelerometer X axis data (float, g)
BYTE 33-36 (AY): accelerometer Y axis data (float, g)
BYTE 37-40 (AZ): accelerometer Z axis data (float, g):
BYTE 41-44 (GY): ? gyroscope X axis data (float, radians/s):
BYTE 45-48 (GY): ? gyroscope Y axis data (float, radians/s):
BYTE 49-52 (GZ): ? gyroscope Z axis data (float, radians/s):
BYTE 53-56 (AB): altitude from the barometric sensor (float, meters)
BYTE 57-60 (Q0): attitude quaternion (float)
BYTE 61-64 (Q1): attitude quaternion (float)
BYTE 65-68 (Q2): attitude quaternion (float)
BYTE 69-72 (Q3): attitude quaternion (float)
BYTE 73- 84 ???
BYTE 85-88 (NV): averaged northward velocity, or 0 when less than 5 satellites locked (float, m/s)
BYTE 89-92 (EV): averaged eastward velocity, or 0 when less than 5 satellites locked (float, m/s)
BYTE 93-96 (EV): downward velocity (barometric) (float, m/s)
BYTE 97-108 ???
BYTE 109-110 (CX): calibrated magnetometer X axis data (signed)
BYTE 111-112 (CY): calibrated magnetometer Y axis data (signed)
BYTE 113-114 (CZ): calibrated magnetometer Z axis data (signed)
BYTE 115-124 ???
BYTE 125 (NS): number of satellites
BYTE 126 ???
BYTE 127-128 (SN): sequence number, increases with every message

FOOTER
-----------------
BYTE 129-132: message footer - always 66 CC 66 CC
Last edited by pawelsky; Nov 16, 2017 at 12:18 AM.
Feb 05, 2014, 11:39 AM
Registered User
francischie's Avatar
Interesting.

I'm already using teensy 3.1 to extract mavlink APM telemetry to send to Taranis . It would be nice if this can be also done on Naza. There is already a code to send the data to S.Port of frysky receiver, what missing is replacing the extraction code for Naza which seems what your working right now.

Taranis telemetry is very nice backup for OSD telemetry which rely on your video signals tramission.

http://diydrones.ning.com/forum/topi...ource=activity
Feb 05, 2014, 12:05 PM
Makers gonna make...
pawelsky's Avatar
Quote:
Originally Posted by francischie
I'm already using teensy 3.1 to extract mavlink APM telemetry to send to Taranis.
Is there any particular reason for which you use Teensy instead of much cheaper Arduinos (e.g. $4 Pro Mini)?
Feb 05, 2014, 02:31 PM
Makers gonna make...
pawelsky's Avatar

Message ID = 09 10 (CAN id 0x108)


Message ID = 09 10 I'll call input/output for now (as it contains RC input and motor output data). Below what I've found so far:

Values in the message are stored in little endian.

55 AA 55 AA 09 10 B8 00 XX XX XX XX M1 M1 M2 M2 M3 M3 M4 M4 M5 M5 M6 M6 F1 F1 F2 F2 XX XX XX XX R? R? RA RA RE RE RR RR RU RU RT RT R? R? R1 R1 R2 R2 R8 R8 XX XX XX XX XX XX XX XX XX XX XX FM XX XX XX XX XX XX XX XX HL HL HL HL HL HL HL HL Hl Hl Hl Hl Hl Hl Hl Hl HA HA HA HA SN SN XX XX RS RS RS RS PS PS PS PS ST ST ST ST XX XX XX XX AA AA AA AA AE AE AE AE AT AT AT AT BA BA BE BE XX XX XX XX CM XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX DV DV DV DV AB AB AB AB RO RO RO RO PI PI PI PI 66 CC 66 CC

HEADER
-------------
BYTE 1-4: message header - always 55 AA 55 AA
BYTE 5-6: message id (09 10 for I/O message)
BYTE 7-8: length (little endian) of the payload (0x00B8 hex or 184 decimal for the I/O message)

PAYLOAD
--------------
BYTE 9-12: ???
BYTE 13-14 (M1): motor 1 output (unsigned, 16920~35000 range)
BYTE 15-16 (M2): motor 2 output (unsigned, 16920~35000 range)
BYTE 17-18 (M3): motor 3 output (unsigned, 16920~35000 range)
BYTE 19-20 (M4): motor 4 output (unsigned, 16920~35000 range)
BYTE 21-22 (M5): motor 5 output (unsigned, 16920~35000 range)
BYTE 23-24 (M6): motor 6 output (unsigned, 16920~35000 range)
BYTE 25-26 (F1): motor 7 output (unsigned, 16920~35000 range)
BYTE 27-28 (F2): motor 8 output (unsigned, 16920~35000 range)
BYTE 29-32: ???
BYTE 33-34 (R?): RC controller unused channel 1 input (signed, always 1001)
BYTE 35-36 (RA): RC controller A channel input (signed, about -1000~1000 range)
BYTE 37-38 (RE): RC controller E channel input (signed, about -1000~1000 range)
BYTE 39-40 (RR): RC controller R channel input (signed, about -1000~1000 range)
BYTE 41-42 (RU): RC controller U channel input (signed, about -1000~1000 range)
BYTE 43-44 (RT): RC controller T channel input (signed, about -1000~1000 range)
BYTE 45-46 (R?): RC controller unused channel 2 input (signed, always 1001)
BYTE 47-48 (R1): RC controller X1 channel input (signed, about -1000~1000 range)
BYTE 49-50 (R2): RC controller X2 channel input (signed, about -1000~1000 range)
BYTE 51-52 (R8): RC controller CH8 when using SBUS or PPM, unused when traditional connection is used (signed, about -1000~1000 range, 1001 when unused)
BYTE 53-63: ???
BYTE 64 (FM): flight mode (0 - manual, 1 - GPS, 2 - failsafe, 3 - atti)
BYTE 65-72: ???
BYTE 73-80 (HL): Home latitude (double, radians)
BYTE 81-88 (Hl): Home longitude (double, radians)
BYTE 89-92 (HA): Home altitude from barometric sensor + 20m (float, meters)
BYTE 93-94 (SN): sequence number, increases with every message
BYTE 95-96: ???
BYTE 97-100 (RS): attitude stabilizer roll input to the system, merged with aileron input, flight mode dependent (float, -1000 ~ 1000 range)
BYTE 101-104 (PS): attitude stabilizer pitch input the system, merged elevator input, flight mode dependent (float, -1000~1000 range)
BYTE 105-108 (ST): altitude stabilizer throttle input to the system based on flight mode and arm state (float, about -1000~1000 range)
BYTE 109-112: ???
BYTE 113-116 (AA): ??? actual aileron feed to the system based on mode and arm state (float, about -1000~1000 range)
BYTE 117-120 (AE): ??? actual elevator feed to the system based on flight mode and arm state (float, about -1000~1000 range)
BYTE 121-124 (AT): ??? actual throttle feed to the system based on flight mode (float, about -1000~1000 range, changes to -200 in failsafe)
BYTE 125-126 (BA): battery voltage (unsigned, millivolts)
BYTE 127-128 (BE): BEC voltage (unsigned, millivolts)
BYTE 129-132: ???
BYTE 133 (CM): control mode (0 - GPS/failsafe, 1 - waypoint mode?, 3 - manual, 6 - atti)
BYTE 134-176: ???
BYTE 177-180 (DV): downward velocity? (float, m/s)
BYTE 181-184 (AB): altitude from the barometric sensor (float, meters)
BYTE 185-188 (RO): roll (float, radians)
BYTE 189-192 (PI): pitch (float, radians)

FOOTER
-----------------
BYTE 193-196: message footer - always 66 CC 66 CC
Last edited by pawelsky; Jul 02, 2014 at 03:49 PM.


Quick Reply
Message:

Thread Tools