#include <MsTimer2.h>
#include <Arduino.h>
// FMS PIC protocol for connecting a PPM stream to a PC.
// http://modelsimulator.com/
//
// Implements the 19200 baud FMS PIC protocol
// Converted from code by
// Richard.Prinz@MIN.at 3.2013
//
// This sketch will find the syncpulse and encode it as 0xFF, and encode
// the individual channels in sequence with the proportional value for each
// channel from 0x00 to 0xFE.
// The code will continue to encode channels regardless of their number
// until the next syncpulse.
//
// The PPM sigmal from the transmitter (or receiver, if it can suply a PPM signal)
// is connected to pin 3, external interupt 1. The Arduino board communicates with
// the computer through the serial port, thus being able to connect throug USB
// interface.
//
// The code uses the timer interrupt through the MsTimer2 library. This can be omitted
// if not wanted. It just adds the capability to send a "heartbeat" signal to the
// simulator if no PPM signal is detected for a while.
// http://playground.arduino.cc/Main/MsTimer2
//
// by Reynir Siik
// 2015-MAR-14, Pi day
//
#define MIN_MS 1000 //1000ul
/*
#define MID_MS 1500
#define MAX_MS 2000
#define RANGE_MS 1000
*/
#define CO 3.9215686
// 1000/255 == 3.9215686
uint32_t serial_timer;
// Variables used in interupt routine is declared volatile to survive task switching
volatile boolean nextPtr = 0;
volatile unsigned long time[2];
volatile boolean sem = false;
volatile byte numWDT = 0;
int ppm[6];
void flash() {
static boolean output = HIGH;
digitalWrite(17, output);
output = !output;
}
void setup()
{
Serial.begin(19200);
MsTimer2::set(100, ISR_WDTimer); // 100 ms timeout
//MsTimer2::set(1000, flash);
MsTimer2::start();
attachInterrupt(1, ISR1, FALLING); //Trigg on negative edge on pin 3
pinMode(13, OUTPUT);
pinMode(17, OUTPUT);
/*
PPM pulse train:
__ ___________________________________ _____ ____ _______ ___ //___ __________ __ HIGH
|_| Sync pulse > 3000 us |_| |_| |_| |_| // |_| |_|
Channel pulse 1000 to 2000 us LOW
Pulse start and end on falling edge. The end of one pulse is the begining of next.
Sync pulse translates to FF
Channel pulse length is encoded in the range 00 to FE, 1000 us is 00 and 2000 us is FE
*/
}
void loop()
{
if (sem == true)
{
sem = false;
int r = (time[!nextPtr] - time[nextPtr] - MIN_MS);
if (r > 3000) //sync pulse code 255
r = 255;
else { //channels encoded in range 0-254
r = (int)(r / CO);
if (r > 254)
r = 254;
// pinMode(13, OUTPUT);
}
Serial.write(r); // output FMS protocol
// Serial.println(r);
numWDT = 0;
}
if (numWDT > 2) // watch dog timeout
{
numWDT = 0;
Serial.write(255); // output FMS protocol
}
}
/* Pulse timing interupt routine */
void ISR1()
{
time[nextPtr] = micros();
nextPtr = !nextPtr;
sem = true;
}
/* Watch dog timer interupt routine */
void ISR_WDTimer() {
numWDT++;
}
serial_timer = nowtime + 50;
}
}
That’s the code I’m running on a Sparkfun Pro Micro. I have my RC receiver PPM output connected to the Arduino. It works great with crrcsim, an opensource RC flight simulator. What I want to do is use that Arduino serial output as an input method for processing. It’s 6 channels. It reads the falling edge of the pulses and counts the time between falling edges. When I output it in processing, I see the values when I println(inByte).
What I’m thinking is that I need to read the data into an array with each channel being an element of the array. Basically, a 255 value is the sync pulse followed by the 6 channel values.
Here’s what I tried in processing and it doesn’t work right.
/**
* Serial Duplex
* by Tom Igoe.
*
* Sends a byte out the serial port when you type a key
* listens for bytes received, and displays their value.
* This is just a quick application for testing serial data
* in both directions.
*/
import processing.serial.*;
Serial myPort; // The serial port
int inByte[] = new int[1]; //-1; // Incoming serial data
int Channel[] = new int[inByte.length+5];
void setup() {
size(400, 300);
// create a font with the third font available to the system:
PFont myFont = createFont(PFont.list()[2], 14);
textFont(myFont);
// List all the available serial ports:
printArray(Serial.list());
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// In Windows, this usually opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 19200);
}
void draw() {
background(0);
// text("Last Received: " + inByte, 10, 130);
while(inByte[0] !=255){
text("Last Received " + inByte, 10, 130);
for(int i=0;i<6;i++){
Channel[i] = inByte[0];
println(i,Channel[0],i,Channel[1],i,Channel[2]);
}
}
}
void serialEvent(Serial myPort) {
inByte[0] = myPort.read();
}
How do I read the inByte into an array that has 6 elements of only channel values?