Saturday, January 30, 2010

"Demodulator" Updated

So, this thing now finally works for all intended purposes of getting any kind of data out of a Android device as it should, so it would be safe now to reveal some details.

Simple schematics and implementation:

And now some software tips. For this to work it is recommended to have pre-generated data samples, mostly because of the timing.

In this case, raw binary data of serial ASCII packets (start bit, payload, stop bit). You might make them like this:

ofstream outfile;
char * buffer = new char [55];
// Start bit (low)
for (int i = 0; i < 5; i++) {
buffer[i] = 25;

// What you need here in binary (low is 25, high is 230), just remember to reverse the order!

// Stop bit (hight)
for (int i = 45; i < 50; i++) {
buffer[i] = 230;
} ("snd.raw",ofstream::binary);
outfile.write (buffer,55);

Written for C, assuming the sound sampling frequency is 48000, because then one bit is 5 samples in length.

All of that produces this nifty image on the oscilloscope (blue being Schmitt trigger output and the yellow being serial output) :

Now to use it in an Android app:
  • we need direct access to the PCM stream and a buffer to generate what we want to output from the pre-generated samples:

private static final Integer minBufferSize =, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT);

private final AudioTrack oTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT, minBufferSize, AudioTrack.MODE_STREAM);

private byte[] sndBufferTrack = new byte[minBufferSize];

  • next we need an array for the samples (because of the faster read access) and then to read them in:
private byte[][] sndSamples = new byte[256][50];

try {
inputStream = getResources().openRawResource(R.raw.snd);[0]);
} catch (IOException e) {
//You'll all figure out how to do this for the rest 255 of them

  • then we fill the buffer with the generated data and play it:;
for (int i = 0; i < 50; i++) {
sndBufferTrack[i] = sndSamples[0][i];
oTrack.write(sndBufferTrack, 0, minBufferSize);

And all of this, with right polarity, correctly generated samples and the right amount of volume finally produces consistent and mostly artefact's free data transfer:

With end result being able to use G1's orientometer to control the plane in FlightGear simulator:

Saturday, January 23, 2010

The Second Half of the "Brain"

Started work on the servo control board to finally make the "demodulator" board feel useful:

Doesn't do much yet, but it doesalready blink on received data:

Altitude Test & Pictures

A few attempts later, it was time to see how high can it really go.

Now with snowy scenery from 500m:

And the usual data. Also fun fact, it appears that the spikes in speed data from the GPS are related to rapid altitude change more then speed variations, since a similar test with a car produced no such spikes, even with slower or higher speeds.

And as a bonus, thanks to ever growing Android Marketplace, some still photos as well:

Saturday, January 09, 2010

Talking the Language of Servo

Just fooling around to see what would happen if the RC receiver would be hooked up to baudline:

Now we know the timings for the most left and right position. Might be useful for controling the servos later!

P.s. Yes, the desktop changed, different computer, mystery solved.