The CAN Bus may be sniffed by connecting to any unused CAN Bus connector. There's an unused connector at the top of the turret under a rubber plug. Any of the hit detectors may also be used to tap into the CAN Bus.
The CAN Bus connectors use a pair of differential signals similar to the RS-485 protocol. The other two pins of the Can Bus connection are ground and power (~12V). I use the following pin numbers when describing the connector.
Since CAN uses a differential signal, I tried using a RS-485 transceiver chip in an attempt to get a signal my Saleae Logic Analyzer could read. I had used the ISL3178EIBZ chip in several previous projects so I used a couple of PCBs with these chips to listen in on the CAN Bus and the M Bus. Here is a diagram of the pinouts of the chip.
I connected the logic analyzer to pin 1 of the RS-485 chip.
While there are lots of locations where the CAN Bus may be accessed, the M Bus doesn't have similar locations to tap into the signal. I found if one motor is disconnected, none of the motors would power on so I wanted to find a way of sniffing the M Bus will all four motors connected.
Here's a picture of a single pin and a two pin adapter I used to sniff the M Bus.
The first photo I took trying to show this adapter in use wasn't very clear so I made a second attempt of showing the adapter pins in use. I'm including both photos in hopes at least one will provide convey how the adapter is used.
The adapter pins where made by soldering a right angle header to an double length header. This resulted in a three way header pin.
In order to limit the number of parameters changing, I wrote a custom Scratch program to turn a single motor on at a few different speeds. Here's a screen grab of the Scratch program.
Here's the Python translation.
variable_motorSpeed = 0 def start(): global variable_motorSpeed robot_ctrl.set_mode(rm_define.robot_mode_free) while True: variable_motorSpeed = 20 chassis_ctrl.set_pwm_value(rm_define.pwm1, 8) chassis_ctrl.set_wheel_speed(variable_motorSpeed,0,0,0) time.sleep(0.5) variable_motorSpeed = 40 chassis_ctrl.set_pwm_value(rm_define.pwm1, 9) chassis_ctrl.set_wheel_speed(variable_motorSpeed,0,0,0) time.sleep(0.5) variable_motorSpeed = 0 chassis_ctrl.set_pwm_value(rm_define.pwm1, 7.5) chassis_ctrl.set_w
I added PWM commands to help identifying which section of code was being executed. I included the PWM1 output in the logic analyzer capture. I've included the logic analyzer data file in the "Files" section of this project. Here's a screen grab of a portion of the captured traces.
**Edit (9/1/19): I'm not so sure about the M Bus baud. It may not be exactly 921,600 bps.**
From analyzing the traces, I've learned the M Bus uses a baud of 921,600 bps (edit: unsure about this). The CAN Bus uses 2,000,000 bps.
DJI has several open source development boards. Hopefully the communication protocol used by the open source boards is similar to the S1's protocol. Here's a link to DJI's Github. DJI's development boards can be found at DJI's store as well as some other online robotics stores.
The above traces include the I2C lines used to communicate with the battery. Reddit user ReasonablyClever shared information he gathered from investigating this bus in the RobomasterS1 Reddit.
As ReasonablyClever found, the S1 will not work properly when powered from a different source than a Robomaster Intelligent Battery.
I've found the I can greatly extend the operational time of my S1 by wiring an external power supply in parallel with the battery. I make sure the external power has a matching voltage and robot doesn't complain as it used the combined power sources. While the normal battery has to be used, the external supply keeps the battery from being drained. An external power supply is really useful when experimenting with code and while attempting to sniff communication lines.