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:
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:
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
Here is how that looks in betaflight:
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:
- Microcontroller: Teensy 4.1
- PPM Input Pin: Pin 2 (comes directly from the Rc Receiver)
- PPM Output Pin: Pin 9 (goes to the Flightcontrolelr)
- Library Used: PulsePosition
https://www.pjrc.com/teensy/td_libs_PulsePosition.html
- 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.
- 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
}
}