This blog will document the steps taken in converting a Hubsan X4 RC Quadcopter from analog control, to full control over wifi. Inspired by, and using many of the same steps as this blog. Steps taken are:

  1. Replace the RC controller with a laptop + Arduino combination, using an A7105 transceiver chip to interact with the copter.
  2. Replace the Arduino from the previous step with a hacked wifi SD card which interfaces an A7105 transceiver chip.
  3. Add code to the wifi SD card, so that the copter can be controlled in real time via wifi commands.
  4. Mount the wifi SD card on the quadopter itself, and control the whole mechanism by sending commands over wifi.
  5. Add support for automatic pathing.

Parts List

Setting up the Arduino

To install the executables necessary to compile for the Arduino, run the following command:

sudo apt-get install arduino-mk

Make sure to add /usr/share/arduino to the $PATH, as it is required in order to use ard-parse-boards. All code for the quadcopter and Arduino testing lives in my github repo. I prefer to use the commandline to compile and load the code, so there may be some code differences if you plan to use the GUI.

To test the Arduino setup, we will compile a small file named blink.ino and push it to the board. We also need to create a Makefile, so that the code can be compiled. If successful, we will be able to change the rate that an LED blinks on the boards. An important note - though the Arduino files end with .ino, they are really just C++ code.

A note on the Makefile - it includes another makefile named Arduino.mk, which can be considered the "parent" file. Depending on your system setup, the line

include ../Arduino.mk

may need to be changed to

include /usr/share/arduino/Arduino.mk

To find out which USB device my Arduino was connected to in order to set _ARDUINOPORT, I watched the output of dmesg while plugging in my device, using dmesg | less , then hitting SHIFT+F to go into follow mode. In my case, this was /dev/ttyUSB0.

blink.ino

// Blink void setup(void) { pinMode(13, OUTPUT); } void loop() { digitalWrite(13, LOW); delay(1000); digitalWrite(13, HIGH); delay(1000); } int main() { init(); setup(); while(true) { loop(); } }

Makefile

BOARD_TAG = atmega328 ARDUINO_PORT = /dev/ttyUSB0 ARDUINO_LIBS = ARDUINO_DIR = /usr/share/arduino include ../Arduino.mk

Someone familiar with Arduino code may be wondering what int main() is doing - since the GUI automagically creates this loop, it is not usually necessary to code it explicitly. However, because I am compling and uploading from the command-line, it is necessary to add this loop in.

Once everything is ready, simply type make. This will compile the code. To upload to the attached arduino device, simply type

sudo make upload

sudo is necessary due to the permissions settings for /dev/ttyUSB0 - you could easily change this with sudo chmod 666 /dev/ttyUSB0

Soldering the A7105 Trasceiver Chip

Arduino to A7105 Pin Mapping

Image of Arduino + A7105 setup

Our final code will use an offshoot of the Deviation project, which has reverse engineered the packet structure for the Hubsan. The code can be found here - it should compile and upload just like the previous example code. Once compiled and uploaded, we should be able to control the copter via the Arduino.

Setting up the Transcend Wifi SD Card

This work is based on 3 key links from Hack-A-Day about hacking the Trascend WiFi SD Card: 1, 2, 3. Based on these posts, specifically 2, we want to take the "next step", using one of these SD cards as a mobile brain for controlling the quadcopter, so that we do not require constant radio contact. Rather, we would prefer to control the quadcopter over wifi, either using direct controls with a stable fallback (i.e. hold position) on failed radio communication, or simple directional commands like "GO UP 10ft, GO LEFT 20ft, HOLD". While this is currently a long ways off, each step in this blog is an attempt at getting closer to this overarching goal.

The first step was making modifications to the boot ramdisk. Thanks to Dmitry's work, this is pretty straightforward.

I have hosted a github repo with the complete code that will upload to a Transcend SD card and (hopefully) act as a wifi brain.

Step 1: Modifications

To make initial modifications to the ramdisk, clone my github repo, cd to transcend/core/ and run unpack_ramdisk.sh. This will create a folder named unpacked - in here is all the goodies that the card will boot with once it is flashed.

His root password by default is (thanks CNLohr): _dmitry.grWiFiSD

Modifications I made:

  • Changed root password to toor following this example with openssl
  • Replaced existing busybox with a more fully featured version with things like vi, etc. Compiled from source with my choice of applets - see below instructions for details

After these modifications were complete, running repack_ramdisk.sh will create a new version of initramfs3.gz with all these changes.

Step 2: Upload

The next question is - how do we get these files to the card? There are 4 key files: image3, initramfs3.gz, _mtdjffs2.bin and program.bin. NOTE: These names should not be changed! Change the filenames at your own peril.

The way these interact is covered on Dmitry's blog, but the gist of it is that program.bin is uboot, which then launches image3 as the kernel and uses initramfs3.gz as the ramdisk on boot. By unpacking, then repacking the ramdisk, we make modifications to the booted operating system.

Once the card is plugged in, I once again watch the output in dmesg and see this line:

[406507.218041] sd 7:0:0:2: [sdd] 31504384 512-byte logical blocks: (16.1 GB/15.0 GiB)

This gives enough information to run the following command:

sudo mount /dev/sdd1 /mnt

Now typing mount shows that the card has been mounted successfully!

/dev/sdd1 on /mnt type vfat (rw)

But how do we actually "flash" the card? Luckily, Dmitry has us covered.

(From Hack A Day comments) Dmitry Grinberg says: September 20, 2013 at 1:45 am Ah, I forgot to explain the update process, so unless you read the doc you’ll be lost. Place my files on card. wait 1 min. remove card. reinsert card. wait 6 min (very important). remove card. reinsert card. wait till “wifisd” network shows up. connect to it “wifisd1.6″ means card is updating – you cannot connect to it

For me, this meant running the following command from the directory containing image3, initramfs3.gz, _mtdjffs2.bin and program.bin

for i in image3 program.bin initramfs3.gz mtd_jffs2.bin; do sudo cp $i /mnt; done

This is wrapped up in the copy_to_mnt.sh script.

After the copy was finished, I followed Dmitry's instructions, though I ended up waiting ~15mins for the flash to be complete.

Addendum: Cross-Compiling a better Busybox

Based on this link, I wanted to compile a custom Busybox for two reasons: to get more familiar with cross-compilation for this device, and to get exactly what I wanted (busybox from Dmitry didn't have vi or netcat!).

Fist, we need to install crosstool-ng. Following these instructions and these instructions, too got everything going set up very nicely, by doing the following steps.

sudo apt-get install -y autoconf automake libtool libexpat1-dev libncurses5-dev bison flex patch curl cvs texinfo build-essential subversion gawk python-dev gperf

The next step was to download the busybox source by running

wget http://www.busybox.net/downloads/busybox-1.22.0.tar.bz2

Once this was done, compilation and configuration was the next stage.

I have also scripts to my github repository to faciliatate downloading, configuring, and building busybox from source.