Close

A basic script to monitor the controller input sent to the quadcopter by UDP

A project log for Controlling a JJRC H37 Elfie quad from a PC

The JJRC Elfie Quadcopter comes with an Android/iOS app to control it from the phone. Can we control it from our own software?

adria.junyent-ferreadria.junyent-ferre 02/19/2017 at 20:030 Comments

I'm in the process of making a small program to read the control input from a USB gamepad and send the commands to the quadcopter but first I wanted to make sure I got the UDP protocol right. Therefore, I wrote a small Python script that can be combined with airodump-ng and tcpdump in order to read what the phone app is sending to the quadcopter by UDP and translate the controllers axes readings into something a human can read. The source code is attached below:

import sys

state=0
message=""
yaw=0
roll=0
pitch=0
throttle=0
commands=0
err=0
n=0

for line in sys.stdin:
	if state==0:
		pos=line.find("0x0010:")
		if pos!=-1:
			message=line[(pos+39):(pos+43)]+line[(pos+44):(pos+48)]
			roll=int(line[(pos+41):(pos+43)],16)
			pitch=int(line[(pos+44):(pos+46)],16)
			throttle=int(line[(pos+46):(pos+48)],16)
			state=1
	else:
		state=0
		pos=line.find("0x0020:")
		if pos!=-1:
			message=message+line[(pos+9):(pos+13)]+line[(pos+14):(pos+18)]
			yaw=int(line[(pos+9):(pos+11)],16)
			commands=int(line[(pos+11):(pos+13)],16)
			err=int(line[(pos+13):(pos+15)],16)
			n=n+1
			if n==10: #this is a little trick that only displays 1 out of 10 messages
				sys.stdout.write(message+" roll:"+str(roll)+" pitch:"+str(pitch)+" throttle:"+str(throttle)+" yaw:"+str(yaw)+" commands:"+format(commands,"08b")+" err:"+format(roll^pitch^throttle^yaw^commands,'x')+'\n')
				n=0
In order for this to work, the following commands have to be executed first:
# airmon-ng start wlan0
# airodump-ng -c 2 mon0
The first command puts the wifi adapter into monitor mode and creates the monitor interface. I'm not sure if this can work while the network-manager is running, so I stopped the network-manager beforehand using /etc/init.d/network-manager stop (under Debian). The second command above starts sniffing the traffic in the wifi channel #2. At this point I would turn on the quadcopter, connect my phone to the quadcopter's wifi network and start the jjrc app and the bsid of the quadcopter should appear in the terminal where airodump is running. It will look like this:
 CH  2 ][ Elapsed: 1 min ][ 2017-02-19 18:58 ][ WPA handshake: 42:D1:A4:C1:E5:A2                                      
                                                                                                                      
 BSSID              PWR RXQ  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID
                                                                                                                      
 01:C0:06:40:B2:32  -37   0      554     4901    0   2  54e. OPN              JJRC-A21494F                             
 A4:E7:22:14:5B:CD  -48  26      610        2    0   1  54e  WPA2 CCMP   PSK  BTHub6-RFPM
The next thing to do is to start tcpdump and pass the UDP traffic between the phone and the quadcopter to my python script:
# tcpdump -i 2 udp dst port 8895 -x -l | python ./my_script.py
This should produce an output that looks like this:
66807f0180007e99 roll:128 pitch:127 throttle:1 yaw:128 commands:00000000 err:7e
6667640180008299 roll:103 pitch:100 throttle:1 yaw:128 commands:00000000 err:82
6665630180008799 roll:101 pitch:99 throttle:1 yaw:128 commands:00000000 err:87
6665630180008799 roll:101 pitch:99 throttle:1 yaw:128 commands:00000000 err:87
66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f
66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f
66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f
66a6770080005199 roll:166 pitch:119 throttle:0 yaw:128 commands:00000000 err:51
66a6770080005199 roll:166 pitch:119 throttle:0 yaw:128 commands:00000000 err:51
6671620080009399 roll:113 pitch:98 throttle:0 yaw:128 commands:00000000 err:93
666b840080006f99 roll:107 pitch:132 throttle:0 yaw:128 commands:00000000 err:6f
66978e0080009999 roll:151 pitch:142 throttle:0 yaw:128 commands:00000000 err:99
66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f
66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f
By the way, I found out that the difference between the 30%, 60% and 100% settings in the app is the range of the roll and pitch control inputs one gets, they go from 1 to 255 when in 100% mode, from 68 to 187 in 60% mode and from 88 to 167 in the 30% mode. The throttle and yaw controllers are unaffected by the 30/60/100 mode setting.

Discussions