Hi everybody.
Maybe it could be an annoying question but really I searched in the forum before posting and I didnt find any answer
Ok, let s start: for a RC Plane I have developed a small autopilot with Arduino Nano 3.0 and one Spektrum RX.
The software runs very well and the values from the RX are correctly received, here an example:
throttle, aileron, elevator, rudder
936,1448,1444,1624
936,1448,1448,1628
936,1448,1448,1628
936,1448,1448,1628
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1464,1624
936,1444,1464,1624
936,1444,1448,1628
936,1444,1448,1628
936,1444,1444,1624
936,1444,1444,1624
936,1444,1444,1624
936,1444,1444,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1460,1624
936,1444,1460,1624
936,1444,1460,1624
936,1440,1444,1624
936,1440,1444,1624
936,1444,1444,1624
936,1444,1444,1624
936,1448,1448,1624
936,1448,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1448,1448,1624
936,1448,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
932,1448,1444,1624
932,1448,1444,1624
936,1444,1448,1608
936,1444,1448,1608
936,1444,1444,1624
936,1444,1444,1624
932,1448,1444,1624
932,1448,1444,1624
952,1444,1448,1624
952,1444,1448,1624
936,1448,1448,1624
936,1448,1448,1624
936,1448,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1444,1624
936,1444,1444,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1444,1624
936,1444,1444,1624
936,1448,1448,1624
936,1448,1448,1624
940,1440,1460,1624
940,1440,1460,1624
936,1444,1444,1628
936,1444,1444,1628
936,1444,1444,1628
936,1444,1444,1628
936,1444,1448,1624
936,1444,1448,1624
936,1448,1448,1624
936,1448,1448,1624
936,1448,1448,1624
940,1448,1444,1628
940,1448,1444,1628
936,1444,1448,1624
936,1444,1448,1624
936,1448,1444,1628
936,1448,1444,1628
936,1448,1448,1624
936,1448,1448,1624
936,1444,1448,1616
936,1444,1448,1616
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
944,1444,1448,1624
944,1444,1448,1624
952,1448,1448,1624
952,1448,1448,1624
936,1448,1444,1624
936,1448,1444,1624
936,1448,1444,1624
936,1448,1448,1624
936,1448,1448,1624
936,1444,1448,1624
936,1444,1448,1624
940,1444,1444,1624
940,1444,1444,1624
940,1444,1444,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1444,1624
936,1444,1444,1624
936,1444,1448,1624
936,1444,1448,1624
936,1444,1460,1624
936,1444,1460,1624
936,1436,1448,1624
936,1436,1448,1624
936,1436,1448,1624
936,1444,1444,1624
936,1444,1444,1624
936,1448,1448,1624
936,1448,1448,1624
936,1448,1448,1624
936,1448,1448,1624
so I get reasonable values.
But when I send those data to the servos I experience something like jitter or glitches with the servos. As you can see here is the routine and they are refreshed every 20 ms.
#include <avr/interrupt.h>
#include <avr/io.h>
#include <Servo.h>
#include <FreeRTOS_AVR.h>
#include "define_AP6.h"
/***************************************************************
* Variablen, die durch den ausgeführten Interrupt gelesen werden
***************************************************************/
volatile static unsigned long cnt;
volatile static byte PIND_SHADOW;
/****************************
* Data storage from the Radio
****************************/
struct fifoItem {
unsigned long throttlePulse;
unsigned long throttlePulseTemp;
unsigned long ailerPulse;
unsigned long ailerPulseTemp;
unsigned long elevPulse;
unsigned long elevPulseTemp;
unsigned long rudderPulse;
unsigned long rudderPulseTemp;
unsigned long ldgPulse;
unsigned long ldgPulseTemp;
bool thrFlag;
bool ailFlag;
bool elvFlag;
bool rudFlag;
bool ldgFlag;
};
// Array for the data incoming from the radio
fifoItem fifoArray[FIFO_SIZE];
/****************************
* Data storage from the Radio
****************************/
struct servoItem {
unsigned int throttle;
unsigned int aileron;
unsigned int elevator;
unsigned int rudder;
} dataServo;
/********************
* Data for the servos
********************/
Servo throttleServo, aileronServo, elevatorServo, rudderServo;
/*******************************
* Pin definitions for the servos
*******************************/
const int throttleServoPin = 8;
const int aileronServoPin = 9;
const int elevatorServoPin = 10;
const int rudderServoPin = 11;
/***************************************************************
* Semaphore definitions
***************************************************************/
xSemaphoreHandle interrupt; // semaphore from the interrupt routine
xSemaphoreHandle fifoData; // semaphore for counting data storage in the array
xSemaphoreHandle fifoSpace; // counter of free buffers in FIFO
//###########################################################################################
static void vTaskRadio( void *pvParameters );
static void vTaskSendData( void *pvParameters );
static void vTaskServo( void *pvParameters );
//###########################################################################################
/**************
*
* Initial Setup
*
**************/
void setup(){
Serial.begin( BAUDRATE );
Serial.flush();
#if DEBUGLEVEL
delay( 1000 );
Serial.println( F(" frAP6_Nano 3.0") );
delay( 1000 );
#endif
set_interrupt();
/******************
* Servo definition
******************/
throttleServo.attach( throttleServoPin );
aileronServo.attach( aileronServoPin );
elevatorServo.attach( elevatorServoPin );
rudderServo.attach( rudderServoPin );
/* Create the Semaphore and variable for tasks */
vSemaphoreCreateBinary( interrupt );
fifoData = xSemaphoreCreateCounting( FIFO_SIZE, 0 );
fifoSpace = xSemaphoreCreateCounting( FIFO_SIZE, FIFO_SIZE );
portBASE_TYPE s1, s2, s3;
/* Check if the semaphore has been created */
if( interrupt == NULL || fifoData == NULL || fifoSpace == NULL ) {
Serial.println( F("Cannot create the semaphore") );
}
s1 = xTaskCreate( vTaskRadio,
(signed char *)"T1",
configMINIMAL_STACK_SIZE + 210,
NULL,
3,
NULL );
s2 = xTaskCreate( vTaskSendData,
(signed char *)"T2",
configMINIMAL_STACK_SIZE + 20,
NULL,
1,
NULL );
s3 = xTaskCreate( vTaskServo,
(signed char *)"T3",
configMINIMAL_STACK_SIZE + 50,
NULL,
2,
NULL );
/* Check Tasks creations */
if( s1 != pdPASS || s2 != pdPASS || s3 != pdPASS ) {
Serial.println( F("Creation problem") );
Serial.print( s1 );
Serial.print( ',' );
Serial.print( s2 );
Serial.print( ',' );
Serial.print( s3 );
while(1);
}
Serial.print( F("Tasks created...") );
Serial.println( F("OK") );
/* Start activities... */
vTaskStartScheduler();
Serial.println( F("Insufficient RAM") );
while(1);
}
void loop(){
/* Nothing here */
}
void set_interrupt(void){
EICRA = 0x00;
DDRD &= ~((1 << PIND2)); // Input Pin - Es werden nur die ersten D2 und D3 als Interrupt verwendet
PORTB &= ~((1 << PIND2)); // Pull - up disabled
// Configure external interrupts on PCINT2 (from PD0 to PD7)
PCMSK2 = 0; // Disable interrupts on over a single port
PCICR |= (1 << PCIE2); // Enabled interrupts on PCINT23-16
PCMSK2 |= ((1 << PCINT21)); // At the moment only PD2 enabled
}
and here the ISR routine
ISR(PCINT2_vect){
cnt = micros();
PIND_SHADOW = PIND;
/* Give the semaphore to unblock the task */
xSemaphoreGiveFromISR( interrupt, NULL );
}
and here the tasks definition: