PulsePosition Library not working correctly

Kinsey

Member
For some context, i'm building a drone, to which i'm adding a collision detecting and avoidance system. And now i face problems with sending out the ppm signal from the receiver again, the reading part works flawlessly. I've tested the code with an Oscilloscope where it also shows that weird behaviour. It just randmoly sends completly weird signals witout me even touching the sender or anything.
Here is how that looks in betaflight:
1719046857954.png


Idk if its clear on the picure but on the botom left and right hand side i wasn't doing anything and you see the flactuation there, in the middle i was moving the throttle which suprisingly kinda worked but then the rest fucked it self back up again.
Hardware Setup:
Code Overview:
  • I am using the PulsePosition library to send PPM signals Pin 9. The reading i'm doing manualy bc it works better
  • The setup works intermittently but often sends erratic and incorrect PPM values even when no inputs are changing.
Observed Behavior:
  • The PPM signals appear noisy and unstable when monitored in Betaflight Configurator.
  • AUX channels fluctuate without any input changes.
  • The throttle value sometimes spikes or drops unexpectedly.
  • The pitch, yaw and rolle fluctuate aswell and are really noisy

So my question is, why is that happening and how can i fix this. Thanks for helping i really need this for my final project.

Here is my code that 'm using currently


C++:
#include <Arduino.h>
#include <Wire.h>
#include <PulsePosition.h>
// Define the pin connected to the PPM signal (on Teensy 4.1 must be 6, 9, 10, 20, 21, 22, or 23)
#define PPM_PIN 2
#define PPM_OUT_PIN 9  // Output pin for PPM signal
// Variables
volatile uint16_t channel1 = 1500; // uint16_t = int with 2^16 different values, initialize to 1500us
volatile uint16_t channel2 = 1500;
volatile uint16_t channel3 = 1500;
volatile uint16_t channel4 = 1000;
volatile uint16_t channel5 = 1500;
volatile uint16_t channel6 = 1500;
volatile uint16_t channel7 = 1500;
volatile uint16_t channel8 = 1500;
volatile uint8_t currentChannel = 0; // Volatile: value can change at any time without action being taken, uint8_T: stores values between 0 and 255 (only integers)
// PPM settings
#define NUM_CHANNELS 8  // Number of PPM channels
uint16_t channelValues[NUM_CHANNELS]; // Create an array that holds uint16_t with all the channel values
// PulsePosition object
PulsePositionOutput ppmOut;
// Define the functions
void readPPM();
void setup() {
  Serial.begin(9600);  // Start serial communication for debugging
  Serial.println("Start of program");
  pinMode(PPM_PIN, INPUT_PULLUP); // Enable internal pull-up resistor
  attachInterrupt(digitalPinToInterrupt(PPM_PIN), readPPM, FALLING);  // Set up an interrupt on PPM_PIN
  // Initialize the PulsePositionOutput object
  ppmOut.begin(PPM_OUT_PIN);
  // Initialize channelValues with default values
  for (int i = 0; i < NUM_CHANNELS; i++) {
    channelValues[i] = 1500; // Default value for each channel
  }
}
void loop() {
  // Print PPM values
  noInterrupts(); // Temporarily disable interrupts to safely read the volatile variables
  uint16_t ch1 = channel1;
  uint16_t ch2 = channel2;
  uint16_t ch3 = channel3;
  uint16_t ch4 = channel4;
  uint16_t ch5 = channel5;
  uint16_t ch6 = channel6;
  uint16_t ch7 = channel7;
  uint16_t ch8 = channel8;
  interrupts(); // Re-enable interrupts
  Serial.print("Channel 1: ");
  Serial.print(ch1);
  Serial.print(" us\t");
  Serial.print("Channel 2: ");
  Serial.print(ch2);
  Serial.print(" us\t");
  Serial.print("Channel 3: ");
  Serial.print(ch3);
  Serial.print(" us\t");
  Serial.print("Channel 4: ");
  Serial.print(ch4);
  Serial.print(" us\t");
  Serial.print("Channel 5: ");
  Serial.print(ch5);
  Serial.print(" us\t");
  Serial.print("Channel 6: ");
  Serial.print(ch6);
  Serial.print(" us\t");
  Serial.print("Channel 7: ");
  Serial.print(ch7);
  Serial.print(" us\t");
  Serial.print("Channel 8: ");
  Serial.print(ch8);
  Serial.print(" us\t");
  Serial.println();
  // Update channel values for PPM output
  channelValues[0] = ch1;
  channelValues[1] = ch2;
  channelValues[2] = ch3;
  channelValues[3] = ch4;
  channelValues[4] = ch5;
  channelValues[5] = ch6;
  channelValues[6] = ch7;
  channelValues[7] = ch8;
  // Set PulsePositionOutput with new values
  for (int i = 0; i < NUM_CHANNELS; i++) {
    ppmOut.write(i + 1, channelValues[i]);
  }
  delay(20);  // 50Hz refresh rate
}
void readPPM() {
  static uint32_t lastTime = 0;  // Variable to store the time of the previous pulse
  uint32_t currentTime = micros();  // Get the current time in microseconds
  uint32_t interval = currentTime - lastTime;  // Calculate the time interval since the last pulse
  lastTime = currentTime;  // Update lastTime to the current time for the next interval calculation
  if (interval >= 3000) { // Check if the interval is 3000 microseconds or more
    // A sync pulse is detected (interval longer than 3 milliseconds)
    // This sync pulse indicates the start of a new frame period
    currentChannel = 0;  // Reset to the first channel
  } else {
    // If the interval is less than 3000 microseconds, process the pulse for the current channel
    switch (currentChannel) {
      case 0:
        channel1 = interval;
        break;
      case 1:
        channel2 = interval;
        break;
      case 2:
        channel3 = interval;
        break;
      case 3:
        channel4 = interval;
        break;
      case 4:
        channel5 = interval;
        break;
      case 5:
        channel6 = interval;
        break;
      case 6:
        channel7 = interval;
        break;
      case 7:
        channel8 = interval;
        break;
    }
    currentChannel++;  // Move to the next channel
  }
}
 

Attachments

  • PulsePositionLibrary.ino
    4.2 KB · Views: 13
My first suggestion would be to comment out the print code and look at the oscilloscope output. Printing that much data 50 times per second not only puts out data faster than you can read it, but if the receiver can't process it, things may stall out. In addition, USB Serial.print generates interrupts of its own which may be interfering with your PPM output timing. I'm not familiar with the PPM library, but you may know whether you can set its interrupt priority to a higher level than the USB Serial interrupt.
 
Back
Top