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;
}

outfile.open ("snd.raw",ofstream::binary);
outfile.write (buffer,55);
outfile.close();


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 = android.media.AudioTrack.getMinBufferSize(48000, 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);
inputStream.read(sndSamples[0]);
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
//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:
oTrack.play();
for (int i = 0; i < 50; i++) {
sndBufferTrack[i] = sndSamples[0][i];
}
oTrack.write(sndBufferTrack, 0, minBufferSize);
oTrack.stop();
oTrack.release();

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:

video

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:

video

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.