0

For a school project I have to control my RC plane from my computer using Java. The way I want to achieve this is by connecting my remote to my MacBookPro via a 3.5mm cable (remote's trainer port).

The way I have to communicate with the remote, is via a PPm signal, which looks like this:

enter image description here

Here's a bit more info about the PPM signal: https://www.insecure.ws/2010/03/09/control-rc-aircrafts-from-your-computer-for-0/#toc-2

What I want to know now, is how I can generate said PPM signal with Java. It has to be a chunky signal with a specific amplitude.

Would anyone here be able to help me with this?

EDIT:
Let me answer some of the questions asked below here:

That site explains it better that I thought I'd be able to, but I'll try anyways.

I want to control my RC plane with my computer. For now, I only want my throttle to work. The rest will follow later.

Each frame is 22.5ms long, as that's the format RC stuff uses. Each frame consists of 8 channels with 0.4ms stops between them, and a blank signal to fill up the time it's got left.

Each channel has an amplitude of 1.3Volts, which I'll achieve by trial and error (play with my volume until the annoying beeping stops), and is 0.7 - 1.5ms.

What I want to achieve, is to have a default signal, with 7x 1.1ms and 1x 0.7ms (7x middle position for all servo's, and 1x throttle minimum), that changes when the users hits a button on the keyboard (1 would change the throttle's signal length to 0.7 + 0.1 ms => 0.8ms). Until the user presses 0, 1, 2, 3 or 4, the signal would keep repeating (1 frame per 22.5ms), with the changed length of channel 1.

I have posted what I have so far on github.

Pim16aap2
  • 1
  • 2
  • 1
    Can you explain the technical details and constraints of the signal here instead of linking off-site? – nanofarad Nov 16 '13 at 13:30
  • 1
    So you mean a [square wave](http://en.wikipedia.org/wiki/Square_wave)? – Andrew Thompson Nov 16 '13 at 13:36
  • Doesn't look quite square here. Possible that it's Pulse-width modulated? – marko Nov 16 '13 at 15:19
  • If you could please post more information. Generating a signal to output through Java Sound is relatively easy but it sounds like you are asking how to generate the control signal. The specifications are not clear enough for us to tell you how to make samples out of it. For example there are 8 channels. How are they formatted? The amplitude is specified as a voltage level output from the sound card. Do you know the integer value or do you need to take measurements with a test signal? Are you planning on doing this in real time (more complicated)? Etc. – Radiodef Nov 16 '13 at 20:11

1 Answers1

1

To do what you ask for you will have to:

  1. Open audio output in Java according to your settings - proper sampling rate, number of channels and so on
  2. Generate PCM (WAV) waveform with your signal
  3. Push the generated waveform through the output line

You will also have to disable any form of post-processing in your OS and check if your sound card is capable of generating the signal accurately at specified frequencies. I don't have any experience working with sound with Java on MacBooks, but seeing that the Windows and/or sound drivers can be wonky, it's better to be prepared.

Opening audio output in Java

To open audio output in Java, you will have to select one of the supported audio formats and then use part of standard JDK API to open "Source Data Line" (audio output).

Side note: Audio API in JDK wasn't changed in quite some time; it has few things that are not neccesarily self-descriptive or intuitive. For example audio output is called "Source Data Line", while audio input is called "Target Data Line".

This snippet should help you to open the default audio output using JDK API:

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.SourceDataLine;

[...]

// Constructs a Mono, 48kHz, 2-bytes per sample, one sample per frame format */
AudioFormat af = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, 48000.0f, 16, 1, 2, 48000.0f, true );

SourceDataLine output = AudioSystem.getSourceDataLine( af );
output.open();
output.start();  
// `output` should be ready for writing

Generate PCM (WAV) waveform of your signal

The website you have linked to has Python snippet that should generate a signal. If that is exactly the signal you want, you should rewrite that piece of code to Java. You said that it's for your school project and from the description I can assume that this is the main part of the assignment, so let's leave it as exercise left for reader :-)

Push the generated waveform through the output line

Basically, you will have to write the PCM samples to the audio output:

// Initialization
final int byteBufferSizeBytes = AUDIO_BUFFER_SIZE_SAMPLES * af.getFrameSize();
byte bbuf[] = new byte[byteBufferSizeBytes];

// Inner loop
while ( output.isActive() ) {
    // Read/generate piece of your data here and write it into bbuf array

    // Write contents of bbuf (PCM samples) to audio output
    output.write( bbuf, 0, byteBufferSizeBytes );
}

Personal plug

I wrote a Java program some time ago that reads the input from the microphone, analyzes its perceived loudness according to ITU-R BS.1770-3 recommendation, and displays information when a pre-set loudness threshold is surpassed. It has a bit of a GUI, and under Windows 7 it used less than 1% of CPU.

The code is on GitHub, but please be warned that it was written during an all-nighter, so it may not be 100% consistent (and let's be honest, I still think I could write it better). I would recommend you to start with class AudioProcessor, as it does the input/output initialization.

Tomek
  • 21
  • 2
  • Thank you very much! I'm going to try this out now. – Pim16aap2 Nov 17 '13 at 15:21
  • I am still a bit confused about how to generate the PCM exactly (having a hard time converting it to Java :s), and even when that's done, I am not quite sure how I could output it. I have browsed through your project, but I cannot really get it working with that. – Pim16aap2 Nov 17 '13 at 16:35