Skip to content

Instantly share code, notes, and snippets.

@S-Bartfast
Created November 29, 2017 17:18
Show Gist options
  • Save S-Bartfast/97a20c25165cec84c73ec849e77a44e7 to your computer and use it in GitHub Desktop.
Save S-Bartfast/97a20c25165cec84c73ec849e77a44e7 to your computer and use it in GitHub Desktop.
Arduino Sketch that combines multiple PPM streams into one single stream.
/**
* This code is released under the WTFPL and is here by considered to be in the public domain.
*/
int OUT_PIN = 7;
int LED_PIN = 13;
int blip_us = 300; // Length of blip (in microseconds)
#define NUM_SOURCES 2 // Number of sources to combine (only two interrupts available on Arduino UNO)
#define CHANNELS_PER_SOURCE 4 // Number of channels to read from each source
#define MIN_LENGTH 500 // Full negative deflection on servo (0.5ms)
#define DEFAULT_LENGTH 1500 // Zero position on servo (1.5ms)
#define MAX_LENGTH 2500 // Full positive deflection on servo (2.5ms)
#define FRAME_LENGTH 22500; // Total length of entire frame (including all channels plus the frame separating gap), 22.5ms
int channels[CHANNELS_PER_SOURCE * NUM_SOURCES]; // Array containing the length used for watch channel
int PPM_1_in = 2; // Interrupt pin for first PPM input
int PPM_2_in = 3; // Interrupt pin for second PPM input
unsigned long last_pulse[2]; // Array used to 'remember' at what time the last 'blip' was read for each source
int current_channel[2]; // The channel currently being read for each source
void setup()
{
// Set mid-range value for all channels to begin with
for (int i=0 ; i<CHANNELS_PER_SOURCE*NUM_SOURCES ; i++)
channels[i] = DEFAULT_LENGTH;
// Initialize digital pin OUT_PIN which the combined PPM signal will be sent out of.
pinMode(OUT_PIN, OUTPUT);
// Set the default position of the 'read' pins to he 'HIGH' as the pulses are 'falling edge synchronised'.
pinMode(PPM_1_in, INPUT_PULLUP);
pinMode(PPM_2_in, INPUT_PULLUP);
// Assign interrupts for all the sources (only two available on Arduino UNO)
attachInterrupt(digitalPinToInterrupt(PPM_1_in), blipped_1, FALLING);
attachInterrupt(digitalPinToInterrupt(PPM_2_in), blipped_2, FALLING);
// Initialise with 'current time'.
last_pulse[1] = last_pulse[0] = micros();
}
// the loop function runs over and over again forever
void loop()
{
printFrame();
}
// Interrupt called for PPM input 1
void blipped_1()
{
blipped(0);
}
// Interrupt called for PPM input 2
void blipped_2()
{
blipped(1);
}
// Determine if current channel is in range (note we probably only actually need to check the 'upper-bound').
boolean chanelInRange(int source)
{
int lower_bound = source * CHANNELS_PER_SOURCE;
int upper_bound = (source + 1) * CHANNELS_PER_SOURCE;
return lower_bound <= current_channel[source] && current_channel[source] < upper_bound;
}
// Process received 'blip'
void blipped(int source)
{
unsigned long this_pulse = micros();
unsigned long pulse_width = this_pulse - last_pulse[source];
if (pulse_width < MIN_LENGTH)
{
// Probably just 'bouncing' noise
return;
}
else if (pulse_width < MAX_LENGTH)
{
// Record the channels length
if (chanelInRange(source))
channels[current_channel[source]] = pulse_width;
current_channel[source]++;
}
else // pulse_width > 2500
{
// End of frame
current_channel[source] = source * CHANNELS_PER_SOURCE;
}
last_pulse[source] = this_pulse;
}
// Print a blip to output pin
void blip()
{
digitalWrite(OUT_PIN, LOW);
delayMicroseconds(blip_us);
digitalWrite(OUT_PIN, HIGH);
}
void printFrame()
{
unsigned long remainingWindow = FRAME_LENGTH;
// Open the frame
blip();
remainingWindow -= blip_us;
// Print each of the channels
for (int i=0 ; i<CHANNELS_PER_SOURCE * NUM_SOURCES ; i++)
{
delayMicroseconds(channels[i] - blip_us);
blip();
remainingWindow -= channels[i];
}
// Add trailing space to deliniate the end of the frame.
// Max value that can be sent to 'delayMicroseconds(...)' is 16383 so we must use regular 'delay(...)' first then "finish off" with MicroSec.
delay(remainingWindow/1000);
delayMicroseconds(remainingWindow%1000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment