
jetzt muss es nur noch mit den reglern laufen.
dann biste der held !!
Würde ich die Finger von lassen.Schachti hat geschrieben:der soll in den nächsten quad
http://www.freakware.de/shop/artikeldet ... ikel=29601
Jetzt kamen mir doch tatsächlich Zweifel auf der Heimfahrt, ob das auch mit dem Summensignal funktioniert.Schachti hat geschrieben:Done compilling
jetzt muss es nur noch mit den reglern laufen.
Code: Alles auswählen
/* The type of multicopter */
//#define GIMBAL
//#define BI //experimental
//#define TRI
//#define QUADP
#define QUADX
//#define Y6
//#define HEX6
//#define FLYING_WING //experimental
#define SERIAL_COM_SPEED 57600
#define SERIAL_SUM_PPM ROLL,PITCH,THROTTLE,YAW,AUX1,AUX2,CAMPITCH,CAMROLL //For Robe/Hitec/Futaba
#define PPM_PIN_INTERRUPT attachInterrupt(0, rxInt, RISING); //PIN 0
//RX PIN assignment inside the port //for PORTD
#define THROTTLEPIN 2
#define ROLLPIN 4
#define PITCHPIN 5
#define YAWPIN 6
#define AUX1PIN 7
#define AUX2PIN 7 //unused just for compatibility with MEGA
#define CAM1PIN 7 //unused just for compatibility with MEGA
#define CAM2PIN 7 //unused just for compatibility with MEGA
/*********** RC alias *****************/
#define ROLL 0
#define PITCH 1
#define YAW 2
#define THROTTLE 3
#define AUX1 4
#define AUX2 5
#define CAMPITCH 6
#define CAMROLL 7
// ******************
// rc functions
// ******************
#define MINCHECK 1100
#define MAXCHECK 1900
static uint8_t pinRcChannel[8] = {ROLLPIN, PITCHPIN, YAWPIN, THROTTLEPIN, AUX1PIN,AUX2PIN,CAM1PIN,CAM2PIN};
volatile uint16_t rcPinValue[8] = {1500,1500,1500,1500,1500,1500,1500,1500}; // interval [1000;2000]
static int16_t rcData[8] ; // interval [1000;2000]
static int16_t rcCommand[4] ; // interval [1000;2000] for THROTTLE and [-500;+500] for ROLL/PITCH/YAW
static int16_t rcHysteresis[8] ;
static int16_t rcData4Values[8][4];
static uint8_t rcRate8;
static uint8_t rcExpo8;
static float rcFactor1;
static float rcFactor2;
// ***PPM SUM SIGNAL***
#ifdef SERIAL_SUM_PPM
static uint8_t rcChannel[8] = {SERIAL_SUM_PPM};
#endif
volatile uint16_t rcValue[8] = {1500,1500,1500,1500,1500,1500,1500,1500}; // interval [1000;2000]
// Configure each rc pin for PCINT
void configureReceiver() {
#ifndef SERIAL_SUM_PPM
for (uint8_t chan = 0; chan < 8; chan++)
for (uint8_t a = 0; a < 4; a++)
rcData4Values[chan][a] = 1500; //we initiate the default value of each channel. If there is no RC receiver connected, we will see those values
#if defined(PROMINI)
// PCINT activated only for specific pin inside [D0-D7] , [D2 D4 D5 D6 D7] for this multicopter
PORTD = (1<<2) | (1<<4) | (1<<5) | (1<<6) | (1<<7); //enable internal pull ups on the PINs of PORTD (no high impedence PINs)
PCMSK2 |= (1<<2) | (1<<4) | (1<<5) | (1<<6) | (1<<7);
PCICR = 1<<2; // PCINT activated only for the port dealing with [D0-D7] PINs
#endif
#if defined(MEGA)
// PCINT activated only for specific pin inside [A8-A15]
DDRK = 0; // defined PORTK as a digital port ([A8-A15] are consired as digital PINs and not analogical)
PORTK = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7); //enable internal pull ups on the PINs of PORTK
PCMSK2 |= (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7);
PCICR = 1<<2; // PCINT activated only for PORTK dealing with [A8-A15] PINs
#endif
#else
PPM_PIN_INTERRUPT
#endif
}
#ifndef SERIAL_SUM_PPM
ISR(PCINT2_vect) { //this ISR is common to every receiver channel, it is call everytime a change state occurs on a digital pin [D2-D7]
uint8_t mask;
uint8_t pin;
uint16_t cTime,dTime;
static uint16_t edgeTime[8];
static uint8_t PCintLast;
#if defined(PROMINI)
pin = PIND; // PIND indicates the state of each PIN for the arduino port dealing with [D0-D7] digital pins (8 bits variable)
#endif
#if defined(MEGA)
pin = PINK; // PINK indicates the state of each PIN for the arduino port dealing with [A8-A15] digital pins (8 bits variable)
#endif
mask = pin ^ PCintLast; // doing a ^ between the current interruption and the last one indicates wich pin changed
sei(); // re enable other interrupts at this point, the rest of this interrupt is not so time critical and can be interrupted safely
PCintLast = pin; // we memorize the current state of all PINs [D0-D7]
cTime = micros(); // micros() return a uint32_t, but it is not usefull to keep the whole bits => we keep only 16 bits
// mask is pins [D0-D7] that have changed // the principle is the same on the MEGA for PORTK and [A8-A15] PINs
// chan = pin sequence of the port. chan begins at D2 and ends at D7
if (mask & 1<<2) //indicates the bit 2 of the arduino port [D0-D7], that is to say digital pin 2, if 1 => this pin has just changed
if (!(pin & 1<<2)) { //indicates if the bit 2 of the arduino port [D0-D7] is not at a high state (so that we match here only descending PPM pulse)
dTime = cTime-edgeTime[2]; if (900<dTime && dTime<2200) rcPinValue[2] = dTime; // just a verification: the value must be in the range [1000;2000] + some margin
} else edgeTime[2] = cTime; // if the bit 2 of the arduino port [D0-D7] is at a high state (ascending PPM pulse), we memorize the time
if (mask & 1<<4) //same principle for other channels // avoiding a for() is more than twice faster, and it's important to minimize execution time in ISR
if (!(pin & 1<<4)) {
dTime = cTime-edgeTime[4]; if (900<dTime && dTime<2200) rcPinValue[4] = dTime;
} else edgeTime[4] = cTime;
if (mask & 1<<5)
if (!(pin & 1<<5)) {
dTime = cTime-edgeTime[5]; if (900<dTime && dTime<2200) rcPinValue[5] = dTime;
} else edgeTime[5] = cTime;
if (mask & 1<<6)
if (!(pin & 1<<6)) {
dTime = cTime-edgeTime[6]; if (900<dTime && dTime<2200) rcPinValue[6] = dTime;
} else edgeTime[6] = cTime;
if (mask & 1<<7)
if (!(pin & 1<<7)) {
dTime = cTime-edgeTime[7]; if (900<dTime && dTime<2200) rcPinValue[7] = dTime;
} else edgeTime[7] = cTime;
#if defined(MEGA)
if (mask & 1<<0)
if (!(pin & 1<<0)) {
dTime = cTime-edgeTime[0]; if (900<dTime && dTime<2200) rcPinValue[0] = dTime;
} else edgeTime[0] = cTime;
if (mask & 1<<1)
if (!(pin & 1<<1)) {
dTime = cTime-edgeTime[1]; if (900<dTime && dTime<2200) rcPinValue[1] = dTime;
} else edgeTime[1] = cTime;
if (mask & 1<<3)
if (!(pin & 1<<3)) {
dTime = cTime-edgeTime[3]; if (900<dTime && dTime<2200) rcPinValue[3] = dTime;
} else edgeTime[3] = cTime;
#endif
}
#else
void rxInt() {
uint16_t now,diff;
static uint16_t last = 0;
static uint8_t chan = 0;
now = micros();
diff = now - last;
last = now;
if(diff>5000) chan = 0;
else {
if(900<diff && diff<2200 && chan<8 ) rcValue[chan] = diff;
chan++;
}
}
#endif
uint16_t readRawRC(uint8_t chan) {
uint16_t data;
uint8_t oldSREG;
oldSREG = SREG;
cli(); // Let's disable interrupts
#ifndef SERIAL_SUM_PPM
data = rcPinValue[pinRcChannel[chan]]; // Let's copy the data Atomically
#else
data = rcValue[rcChannel[chan]];
#endif
SREG = oldSREG;
sei();// Let's enable the interrupts
return data; // We return the value correctly copied when the IRQ's where disabled
}
void computeRC() {
static uint8_t rc4ValuesIndex = 0;
uint8_t chan,a;
rc4ValuesIndex++;
for (chan = 0; chan < 8; chan++) {
rcData4Values[chan][rc4ValuesIndex%4] = readRawRC(chan);
rcData[chan] = 0;
for (a = 0; a < 4; a++)
rcData[chan] += rcData4Values[chan][a];
rcData[chan]= (rcData[chan]+2)/4;
if ( rcData[chan] < rcHysteresis[chan] -4) rcHysteresis[chan] = rcData[chan]+2;
if ( rcData[chan] > rcHysteresis[chan] +4) rcHysteresis[chan] = rcData[chan]-2;
}
#if defined(FORCE_LEVEL)
rcData[AUX1] = 2000;
#endif
}
#if defined(GIMBAL) || defined(FLYING_WING)
#define NUMBER_MOTOR 0
#elif defined(BI)
#define NUMBER_MOTOR 2
#elif defined(TRI)
#define NUMBER_MOTOR 3
#elif defined(QUADP) || defined(QUADX)
#define NUMBER_MOTOR 4
#elif defined(Y6) || defined(HEX6)
#define NUMBER_MOTOR 6
#endif
#define MOTOR_ORDER 9,10,11,3,6,5 //for a quad+: rear,right,left,front
// *************************
// motor and servo functions
// *************************
uint8_t PWM_PIN[6] = {MOTOR_ORDER};
static int16_t axisPID[3];
static int16_t motor[6];
static int16_t servo[4] = {1500,1500,1500,1500};
volatile int8_t atomicServo[4] = {250,250,250,250};
//for HEX Y6 and HEX6 flat
volatile uint8_t atomicPWM_PIN5_lowState;
volatile uint8_t atomicPWM_PIN5_highState;
volatile uint8_t atomicPWM_PIN6_lowState;
volatile uint8_t atomicPWM_PIN6_highState;
void writeMotors() { // [1000;2000] => [125;250]
for(uint8_t i=0;i<min(NUMBER_MOTOR,4);i++)
analogWrite(PWM_PIN[i], motor[i]>>3);
#if (NUMBER_MOTOR == 6) && defined(MEGA)
analogWrite(PWM_PIN[4], motor[4]>>3);
analogWrite(PWM_PIN[5], motor[5]>>3);
#endif
#if (NUMBER_MOTOR == 6) && defined(PROMINI)
atomicPWM_PIN5_highState = motor[5]/8;
atomicPWM_PIN5_lowState = 255-atomicPWM_PIN5_highState;
atomicPWM_PIN6_highState = motor[4]/8;
atomicPWM_PIN6_lowState = 255-atomicPWM_PIN6_highState;
#endif
}
void writeAllMotors(int16_t mc) { // Sends commands to all motors
for (uint8_t i =0;i<NUMBER_MOTOR;i++)
motor[i]=mc;
writeMotors();
}
#if (NUMBER_MOTOR == 6) && defined(PROMINI)
void initializeSoftPWM() {
TCCR0A = 0; // normal counting mode
TIMSK0 |= (1<<OCIE0A); // Enable CTC interrupt
TIMSK0 |= (1<<OCIE0B);
}
ISR(TIMER0_COMPA_vect) {
static uint8_t state = 0;
if (state == 0) {
PORTD |= 1<<5; //digital PIN 5 high
OCR0A+= atomicPWM_PIN5_highState; //250 x 4 microsecons = 1ms
state = 1;
} else if (state == 1) {
OCR0A+= atomicPWM_PIN5_highState;
state = 2;
} else if (state == 2) {
PORTD &= ~(1<<5); //digital PIN 5 low
OCR0A+= atomicPWM_PIN5_lowState;
state = 0;
}
}
ISR(TIMER0_COMPB_vect) { //the same with digital PIN 6 and OCR0B counter
static uint8_t state = 0;
if (state == 0) {
PORTD |= 1<<6;OCR0B+= atomicPWM_PIN6_highState;state = 1;
} else if (state == 1) {
OCR0B+= atomicPWM_PIN6_highState;state = 2;
} else if (state == 2) {
PORTD &= ~(1<<6);OCR0B+= atomicPWM_PIN6_lowState;state = 0;
}
}
#endif
void setup(){
Serial.begin(SERIAL_COM_SPEED);
configureReceiver();
delay(200);
#if (NUMBER_MOTOR == 6) && defined(PROMINI)
initializeSoftPWM();
#endif
}
void loop(){
computeRC();
writeAllMotors(rcData[THROTTLE]);
//Serial.print(rcData[THROTTLE]); //Print the value
//Serial.println(""); //Start a new line
}