Close

The first working app that enables joystick control from the PC

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 21:550 Comments

I've finally put together the first working app that reads the joystick input from a USB joystick and sends the right commands to control the quadcopter. The application requires the pygame library to be installed and other basic Python dependencies and I've configured to use the axes and buttons that were convenient for my USB gamepad (a Logitech dual action). Basically, it uses the two analogue joysticks for the throttle+yaw and pitch+roll respectively, plus two buttons (7 and 8) for the "arm" and the "emergency stop" commands.

The procedure to make this work is quite simple: connect the computer to the wifi network of the quadcopter, connect the USB joystick and run the app (running with regular user permissions is ok).

import socket
import pygame
import time
from math import floor

def get():
    #pygame gives the analogue joystick position as a float that goes from -1 to 1, the code below takes the readings and
    #scales them so that they fit in the 0-255 range the quadcopter expect
    #remove the *0.3 below to get 100% control gain rather than 30%
    a=int(floor((j.get_axis(2)*0.3+1)*127.5)) 
    b=int(floor((-j.get_axis(3)*0.3+1)*127.5))
    c=int(floor((-j.get_axis(1)+1)*127.5))
    d=int(floor((j.get_axis(0)+1)*127.5)) 
    commands=(j.get_button(6)<<2)|(j.get_button(8)) #only two buttons are used so far: "arm" and emergency stop
    out=(102<<56)|a<<48|b<<40|c<<32|d<<24|commands<<16|(a^b^c^d^commands)<<8|153
    pygame.event.pump()
    return out

# The IP of the quadcopter plus the UDP port it listens to for control commands
IPADDR = '172.16.10.1'
PORTNUM = 8895

pygame.init()
j = pygame.joystick.Joystick(0)
j.init()
 
# initialize a socket
# SOCK_DGRAM specifies that this is UDP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
 
# connect the socket
s.connect((IPADDR, PORTNUM))

while True:
    s.send(format(get(),'x').decode('hex')) #ugly hack, I guess there's a better way of doing this
    time.sleep(0.05)

# close the socket
s.close()

Discussions