I'm working on this little project to read and decode the PPM signal from my old RC-transmitter by using the trainer port. I'm having some trouble to read the signal properly, I'm using attachInterrupt() to read the signal when it changes from low to high, but it doesn't work and I'm getting loads of faulty data.
This is the kind of trainer port I'm trying to hook it upto. (Ignore the lines and the transistor, this is the best picture of my port I could find that also shows the pin layout.)
So I'm trying to directly hook ground on the port to ground on the Arduino, and PPM to port 2. I'm probably doing something wrong here, I'm pretty new at electronics. Do I need a pull-up resistor or something? Please, tell me.
This is the code I've got so far:
volatile int signal = LOW;
boolean test = false;
long currentmils = 0;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, state, RISING);
currentmils = millis();
}
void loop()
{
if(test==true)
{
currentmils = millis() - currentmils;
Serial.println(currentmils);
test = false;
}
}
void state()
{
test = true;
}
This is the kind of output it gives me on the serial monitor:
15
0
35
0
55
0
75
0
95
and so on...
I've not even bothered with trying to decode the signal, first I'd like to get an actual signal, I'm only trying to get the time between pulses in this sketch so far.
It even gives me random output when it's not connected to anything, why is that?
There's a problem with your method; at 9600, it takes as long to print one character as the minimum pulse width of a standard R/C.
You should really be using micros for your timing.
Have a look at DuaneB's notes on R/C decoding.
Allright, I will implement your tip into my program. DuaneB's quides are also very useful for the decoding! But my main trouble right now is to actually get the encodes signal from the transmitter, do you (or anyone else) have any idea on how to do that?
RubinGrolsch:
Unfortunately not, is it possible to use the arduino or some other pc program as a substitute?
I would have thought the Arduino would do that easily enough. Just write a sketch that detects each time the input changes (either by polling, or interrupts) and records the old state and interval since the last state change. When you're collected enough transitions - a couple of dozen would be enough, I'd have thought - print out the state and the duration in micros for each transition. That should be enough to show you the nature of the signal you're dealing with - I'd have thought it'd be one pulse per channel repeating at 50 Hz but the sketch will tell you either way. Do this a few times varying the position of each control and I think you'll vert soon figure out the signal format.
Hi,
Not so long ago I promised a number of people that I would write a variation of the code here (see link below) that would read PPM.
The reason I haven't until now is that I do not have a receiver which outputs PPM.
However the code is simple enough so I have written something which should work - if anyone has the time and hardware to test the code, PM me for a copy.
Keep in mind that a PPM stream decoding function requires two different process to happen, frame start/stop detection and the individual channel number's width information . First before it can accurately process the individual channel data it has to 'sync' up with the PPM framing rate so that it will knows which pulse represents which channel consistently. After the last channel there will always be a longer zero period that fills out to the end of the 20-25msec frame period. Only after your decoder's algorithm has detected the end of the frame will it know that the next 1 to 2msec wide pulse represents the channel 1 information, and each in order after that until the end of the PPM frame.
retrolefty:
Keep in mind that a PPM stream decoding function requires two different process to happen, frame start/stop detection and the individual channel number's width information . First before it can accurately process the individual channel data it has to 'sync' up with the PPM framing rate so that it will knows which pulse represents which channel consistently. After the last channel there will always be a longer zero period that fills out to the end of the 20-25msec frame period. Only after your decoder's algorithm has detected the end of the frame will it know that the next 1 to 2msec wide pulse represents the channel 1 information, and each in order after that until the end of the PPM frame.
That make sense?
Lefty
Yes, I had found that out in the meantime as well, you mean like the synchronisation frame as shown is this picture right?
I have since then adapted my code to further decode the signal:
volatile int signal = LOW;
volatile boolean signalIn = false;
volatile long timeBetweenPulse1 = 0; //pulse lenght channel 1
volatile long timeBetweenPulse2 = 0; //pulse lenght channel 2
volatile long timeBetweenPulse3 = 0; //pulse lenght channel 3
volatile long timeBetweenPulse4 = 0; //pulse length channel 4
volatile long timeBetweenPulse5 = 0; //pulse lenght of the synchronisation pulse
volatile long timeLastPulse = 0; //time in microseconds of the last pulse
volatile int counter = 1; //counts from 1 to 5, and makes the channel correspond with the pulse
void setup()
{
Serial.begin(9600);
attachInterrupt(0, state, RISING);
}
void loop()
{
if(signalIn == true)
{
Serial.print(timeBetweenPulse1);
Serial.print(" ");
Serial.print(timeBetweenPulse2);
Serial.print(" ");
Serial.print(timeBetweenPulse3);
Serial.print(" ");
Serial.print(timeBetweenPulse4);
Serial.print(" ");
Serial.println(timeBetweenPulse5);
signalIn = false;
}
}
void state()
{
if (counter == 1)
{
timeBetweenPulse1 = (int)(micros() - timeLastPulse);
timeLastPulse = micros();
counter = 2;
} else if(counter == 2)
{
timeBetweenPulse2 = (int)(micros() - timeLastPulse);
timeLastPulse = micros();
counter = 3;
} else if(counter == 3)
{
timeBetweenPulse3 = (int)(micros() - timeLastPulse);
timeLastPulse = micros();
counter = 4;
} else if(counter == 4)
{
timeBetweenPulse4 = (int)(micros() - timeLastPulse);
timeLastPulse = micros();
counter = 5;
} else
{
timeBetweenPulse5 = (int)(micros() - timeLastPulse);
timeLastPulse = micros();
counter = 1;
signalIn = true;
}
}
I'm still having trouble with getting the right signal, even when the cables aren't connected to anything I still get signals with about 20000 of microseconds time between them. How should I connect the arduino to my transmitter in a way that there is a common ground?
I'm still having trouble with getting the right signal, even when the cables aren't connected to anything I still get signals with about 20000 of microseconds time between them. How should I connect the arduino to my transmitter in a way that there is a common ground?
I can't answer your question without more details about the transmitter's ppm signal output. The ground would simply wire to a arduino ground pin, that should not be an issue. But we lack info on the PPM signal itself. Is it a 0 to +5vdc signal or 0 to battery voltage signal? What is the logic of the PPM signal, that is, is a HIGH a bit on condition (true logic) or is a LOW a bit on condition (negative logic)?
These things have to be known before proper electrical interfacing can be performed and before your software can properly decode the data stream. Making assumptions on these things makes debugging between hardware and software bugs or possible both a difficult task.
If I was taking on such a project, I would first get out my old analog scope and check out the PPM signal until I fully understood it's properties.
PM Sent, you will need to set the correct number of channels in the code I sent and also let me know how you get on, I used another library to generate the test signal so have not been able to test against a receiver.
I have sent this code out to a few people and have others asking for it, I have only been able to test it against my own PPM Generation library so has anyone tested in against a receiver yet ? Is it doing what you hoped ?