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:
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.
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
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.
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.
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:
After these modifications were complete, running repack_ramdisk.sh will create a new version of initramfs3.gz with all these changes.
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.
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.
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.
ssh root@192.168.11.254
http://forums.parallax.com/showthread.php/149623-WiFi-SD-Card-hacked-useful-for-the-prop