I want to use Arduino to read the ppm value from RC receiver FS-iA6B, print the ppm value and output it back in ppm format. The connection between Arduino and the RC receiver is fairly simple, the ppm signal from the Rc receiver is connected to pin 2 Arduino (Uno), and pin 3 will be connected to the drone flight controller. 5v and ground for RC receiver can either be connected to 5v/ground Arduino or directly to 5v/ground flight controller. The purpose of this project is so I can modify and rewrite the output ppm value to the drone flight controller if my lidar sensor detects obstacles during flight.
This is my current code so far, but the problem I faced now is
- in void loop(), on TCNT1 = 0; line, if I comment the line drone is able to be armed, but no response from the Serial monitor.
- If I didn't put a comment on the line (void loop(), on TCNT1 = 0;), the serial monitor able to show 8 channel ppm value, but the drone is unable to be armed.
Please help me with how I can read, print, and output the ppm value to the flight controller and able to arm the drone. Thank you.
this is the code
volatile uint16_t ppm_buffer[8]; // buffer array to store PPM signal
volatile uint8_t ppm_channel = 0; // current channel
volatile uint32_t ppm_last_time; // last time PPM signal updated
const int PPM_PIN = 3; //19 for mega, 3 for uno
unsigned long previousMillis = 0;
const unsigned long interval = 1000;
void setup() {
pinMode(2, INPUT); // 18 for mega, 2 for uno
pinMode(PPM_PIN, OUTPUT);
Serial.begin(115200);
// configure timer1 to trigger every 20ms for PPM signal output
attachInterrupt(digitalPinToInterrupt(2), ppm_isr, CHANGE);
//timer1 setup configuration
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 39999; // 20ms = 40000 / 16MHz
TCCR1B |= (1<< WGM12);
TCCR1B |= (1<< CS11);
TIMSK1 |= (1<< OCIE1A);}
void ppm_isr() { //function to read signal from rc receiver
uint32_t now = micros(); // current time
int32_t duration = now - ppm_last_time;
ppm_last_time = now;
if (duration > 5000) {
ppm_channel = 0;
} else {
ppm_buffer[ppm_channel]= duration;
ppm_channel++;
}
}
ISR(TIMER1_COMPA_vect) { //function to output signal from rc receiver
static uint8_t ppm_index = 0;
static uint32_t last_micros = 0;
uint16_t pulse_width = ppm_buffer[ppm_index];
uint32_t now_micros = micros();
uint32_t elapsed_micros = now_micros - last_micros;
if (elapsed_micros >= pulse_width) {
digitalWrite(PPM_PIN, LOW);
}
if (elapsed_micros >=20000) {
digitalWrite(PPM_PIN, HIGH);
last_micros = now_micros;
ppm_index++;
if (ppm_index >= 8) {
ppm_index = 0;
}
}
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
if (ppm_channel == 8) {
previousMillis = currentMillis;
Serial.print("PPM:");
for (int i = 0; i < 8; i++) {
Serial.print(" ");
Serial.print(ppm_buffer[i]);
}
Serial.println();
ppm_channel = 0;
}
}
TCNT1 = 0; //if comment this, drone able to armed,but no response on serial monitor
// reset timer1 counter
OCR1A = 39999;
// set timer1 output compare register
TIFR1 |= (1<< OCF1A);
// clear timer1 output compare match flag
//TCNT1 = 0;
}