Page 1 of 1

quadcopter controlled via pc?

Posted: Sat Jul 30, 2011 3:59 pm
by n00b
Hi all
Will be a stupid question but I can not find a sure answer
you can replace the radiocontroller with a apc220 to completely control the quadcopter from pc?
thanks for any replies

Re: quadcopter controlled via pc?

Posted: Sun Jul 31, 2011 7:25 pm
by pixelseventy2
I wanted to ask a very similar question :) I'm a total RC newbie, working on building a quad to be controlled via PC and xbee link. It will either allow control manually from a joypad or as an autonomous drone. Unfortunately, I'm having some issues getting anything like stable flight, and I'm not sure if this is a hardware, software or both issue. I'm using Hobbywing Fentium (as Pentium are now called) 18A ESC, Emax CF2822 motors, 8x4 props, and a WMP and ADXL335 for the IMU, with an Arduino 328 for the main control. I would like to confirm where my issues lie by using known-good software, but I don't have an RC receiver.

I've got software running to send and receive commands, but I just can't achieve stability.

Any thoughts?

Many thanks.

Re: quadcopter controlled via pc?

Posted: Sun Jul 31, 2011 8:15 pm
by PatrikE
To be able to use a PC to control.
HeightControl must be fixed( Work in progress)
Stable mode must work Perfect.(Almost there..)
Gps-support need to be implemented. (PositionHold & WaypointNavigation)

The communication could be done with Serial comminication.(Z-Bee?)
Or Emulate a PPM-signal Via the soundcard or some other hardware.(Adiuno?)

It can be done.
But not quite yet.

/Patrik

Re: quadcopter controlled via pc?

Posted: Mon Aug 01, 2011 3:25 am
by cardboard
I built my own transmitter.
The Corona 2.4ghz diy module is what i used and could be a good starting point for you as well. It just takes a ppm single, I used an arduino to do all my processing.
You may also want to look into the frysky with telemetry, there are some people that have moded this unit to plug into usb and then have a dash with gps etc etc.
http://blog.flytron.com/simpleosd-telemetry-ground-station.html

P1050226.jpg

Re: quadcopter controlled via pc?

Posted: Mon Aug 01, 2011 8:32 am
by pixelseventy2
Hi Carboard. That module is just the transmitter, right? And you're using the arduino to control the TX? If so, presumably I could link use an arduino controlled by PC to connect to the TX, and just connect a compatible RX as normal? Would you be able to share your code, or point me in the right direction to find more information on interfacing with it? If I can interface it with a PC this might be a good alternative to using an XBee.

Thanks

Re: quadcopter controlled via pc?

Posted: Mon Aug 01, 2011 8:47 am
by cardboard
yup the box on the left hand side of the joystick is a 2.4ghz TX, there RX are only $8 or so each
http://www.hobbyking.com/hobbyking/store/__9770__Corona_2_4Ghz_DIY_Module_RX_DSSS_.html

I gutted the joystick and plugged the pots straight into the arduino so you may have to do some work to get serial output to the arduino. the hard work of converting pots to ppm is done for you tho. you can view my reference code from Ian Johnston, the link is in the code.

Note that when you use serial with an arduino it loads up the cycle time so you may need to adjust for that

Sorry the code is a little messy but should be commented enough to get you through it



//Standalone Joystick 2.4ghz TX
//Hadley Boks-Wilson 2/07/2011
//ver 1.0
//Many thanks to Ian Johnston for the origonal code i started from
//http://www.ianjohnston.com

#include <EEPROM.h>

int god = 0;
int jesus = 0;
int buzz=0;
int bob=1;
int interval=500;

long previous = 0;
unsigned long current;
long previous1 = 0;
unsigned long current1;

byte AEL_TRIM = 127;
byte ELE_TRIM = 127;
byte RUD_TRIM = 127;

int AEL_TRIMI = 127;
int ELE_TRIMI = 127;
int RUD_TRIMI = 127;

int TRIMC = 0;
int TRIMc = 0;

int AI_Pin_AEL = 4; // Ana In - Aeleron potentiometer
int AI_Pin_ELE = 1; // Ana In - Elevator potentiometer
int AI_Pin_THR = 2; // Ana In - Throttle potentiometer
int AI_Pin_RUD = 3; // Ana In - Rudder potentiometer

int AI_Raw_AEL; // Ana In raw var - 0->1023
int AI_Raw_ELE; // Ana In raw var - 0->1023
int AI_Raw_THR; // Ana In raw var - 0->1023
int AI_Raw_RUD; // Ana In raw var - 0->1023

int AI_AEL; // Ana In var - 0->1023 compensated
int AI_ELE; // Ana In var - 0->1023 compensated
int AI_THR; // Ana In var - 0->1023 compensated
int AI_RUD; // Ana In var - 0->1023 compensated

int AI_TIpot; // Ana In var - 0->1023 compensated
int Aeleron_uS = 750; // Ana In Ch.0 uS var - Aeleron
int Elevator_uS = 750; // Ana In Ch.1 uS var - Elevator
int Throttle_uS = 750; // Ana In Ch.2 uS var - Throttle
int Rudder_uS = 750; // Ana In Ch.3 uS var - Rudder

int Fixed_uS = 300; // PPM frame fixed LOW phase
int pulseMin = 750; // pulse minimum width minus start in uS
int pulseMax = 1700; // pulse maximum width in uS

float DualrateMultAel = 0.9; // Dual rate mult
float DualrateMultEle = 0.9; // Dual rate mult
float DualrateMultThr = 0.9; // Dual rate mult
float DualrateMultRud = 0.9; // Dual rate mult

int DualrateAdjAel = 0; // Dual rate mid adjustment
int DualrateAdjEle = 0; // Dual rate mid adjustment
int DualrateAdjThr = 0; // Dual rate mid adjustment
int DualrateAdjRud = 0; // Dual rate mid adjustment

int outPinPPM = 10; // digital pin 11

ISR(TIMER1_COMPA_vect) {
ppmoutput(); // Jump to ppmoutput subroutine
}

void setup() {

//Serial.begin(9600) ; // Test

pinMode(2,INPUT);
pinMode(3,INPUT);
pinMode(4,INPUT);
pinMode(5,INPUT);
pinMode(6,INPUT);
pinMode(7,INPUT);
pinMode(8,OUTPUT);
pinMode(9,OUTPUT);

digitalWrite(2,HIGH);
digitalWrite(3,HIGH);
digitalWrite(4,HIGH);
digitalWrite(5,HIGH);
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);

pinMode(outPinPPM, OUTPUT); // sets the digital pin as output

// Setup timer
TCCR1A = B00110001; // Compare register B used in mode '3'
TCCR1B = B00010010; // WGM13 and CS11 set to 1
TCCR1C = B00000000; // All set to 0
TIMSK1 = B00000010; // Interrupt on compare B
TIFR1 = B00000010; // Interrupt on compare B
OCR1A = 22000; // 22mS PPM output refresh
OCR1B = 1000;

AEL_TRIM = EEPROM.read(1);
ELE_TRIM = EEPROM.read(2);
RUD_TRIM = EEPROM.read(3);


digitalWrite(9, HIGH); // Turn on buzzer
delay (10);
digitalWrite(9, LOW); // Turn off buzzer
delay (100);
digitalWrite(9, HIGH); // Turn on buzzer
delay (10);
digitalWrite(9, LOW); // Turn off buzzer
delay (100);
digitalWrite(9, HIGH); // Turn on buzzer
delay (10);
digitalWrite(9, LOW); // Turn off buzzer*/
}


void ppmoutput() { // PPM output sub

// test pulse - used to trigger scope
// digitalWrite(outPinTEST, LOW);
// delayMicroseconds(100); // Hold
// digitalWrite(outPinTEST, HIGH);

// Channel 1 - Aeleron
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Aeleron_uS); // Hold for Aeleron_uS microseconds

// Channel 2 - Elevator
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Elevator_uS); // Hold for Elevator_uS microseconds

// Channel 3 - Throttle
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Throttle_uS); // Hold for Throttle_uS microseconds

// Channel 4 - Rudder
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Rudder_uS); // Hold for Rudder_uS microseconds

// Synchro pulse
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH); // Start Synchro pulse

}


void loop() { // Main loop

// Read analogue ports
AI_Raw_AEL = analogRead(AI_Pin_AEL);
AI_Raw_ELE = analogRead(AI_Pin_ELE);
AI_Raw_THR = analogRead(AI_Pin_THR);
AI_Raw_RUD = analogRead(AI_Pin_RUD);

// Compensate for discrepancy in pot inputs including centering offset.
// Also use this to invert inputs if necessary (swap x1 & y1)
// y=mx+c, x to y scales to x1 to y1
AI_AEL = map(AI_Raw_AEL, 0, 1023, 1200, 0) - 75 -(127-AEL_TRIM); // Invert Aeleron pot and slight centre offset
AI_ELE = map(AI_Raw_ELE, 0, 1023, 1200, 0) - 75 -(127-ELE_TRIM); // Invert Elevator pot and slight centre offset
AI_THR = map(AI_Raw_THR, 0, 1023, 0, 1023) - (127-RUD_TRIM); // Throttle
AI_RUD = map(AI_Raw_RUD, 0, 1023, 1023, 0) + 0; // Rudder

god=AEL_TRIM+ELE_TRIM+RUD_TRIM;

// Map analogue inputs to PPM rates for each of the channels
Aeleron_uS = (AI_AEL * 1.1) + pulseMin - 100;
Elevator_uS = (AI_ELE * 1.1) + pulseMin - 100;
Throttle_uS = (AI_THR * 1.1) + pulseMin - 100;
Rudder_uS = (AI_RUD * 1.1) + pulseMin - 100;

// Check limits
if (Aeleron_uS <= 750) Aeleron_uS = 750; // Min
if (Aeleron_uS >= 1700) Aeleron_uS = 1700; // Max
if (Elevator_uS <= 750) Elevator_uS = 750; // Min
if (Elevator_uS >= 1700) Elevator_uS = 1700; // Max
if (Throttle_uS <= 750) Throttle_uS = 750; // Min
if (Throttle_uS >= 1700) Throttle_uS = 1700; // Max
if (Rudder_uS <= 750) Rudder_uS = 750; // Min
if (Rudder_uS >= 1700) Rudder_uS = 1700; // Max
if (AEL_TRIM <= 1)AEL_TRIM =1;
if (AEL_TRIM >= 254)AEL_TRIM =254;
if (ELE_TRIM <= 1)ELE_TRIM =1;
if (ELE_TRIM >= 254)ELE_TRIM =254;
if (RUD_TRIM <= 1)RUD_TRIM =1;
if (RUD_TRIM >= 254)RUD_TRIM =254;

TRIMC=AEL_TRIM+ELE_TRIM+RUD_TRIM;

AEL_TRIMI = (int)AEL_TRIM;
ELE_TRIMI = (int)ELE_TRIM;
RUD_TRIMI = (int)RUD_TRIM;

if (digitalRead(7)==LOW&&jesus==0){
AEL_TRIM++;
interval=200;}

if (digitalRead(3)==LOW&&jesus==0){
ELE_TRIM++;
interval=200;}

if (digitalRead(2)==LOW&&jesus==0){
RUD_TRIM++;
interval=200;}

if (digitalRead(5)==LOW&&jesus==0){
RUD_TRIM--;
interval=200;}

if (digitalRead(6)==LOW&&jesus==0){
ELE_TRIM--;
interval=200;}

if (digitalRead(4)==LOW&&jesus==0){
AEL_TRIM--;
interval=200;}

jesus=god-(AEL_TRIM+ELE_TRIM+RUD_TRIM);

/*Serial.print(Aeleron_uS);
Serial.print(" Aeleron_uS "); //for debug
Serial.print(Elevator_uS);
Serial.print(" Elevator_uS ");
Serial.print(Throttle_uS);
Serial.print(" Throttle_uS ");
Serial.print(Rudder_uS);
Serial.println(" Rudder_uS ");
Serial.print(jesus);
Serial.print(" jesus ");
Serial.print(buzz);
Serial.print(" buzz ");
Serial.print(AEL_TRIMI-127);
Serial.print(" Alerion trim "); //for debug
Serial.print(ELE_TRIMI-127);
Serial.print(" Elevater trim ");
Serial.print(RUD_TRIMI-127);
Serial.print(" Rudder trim ");
Serial.print(AEL_TRIMc);
Serial.print(" Alerion "); //for debug
Serial.print(ELE_TRIMc);
Serial.print(" Elevater ");
Serial.print(RUD_TRIMc);
Serial.print(" Rudder ");
Serial.println(millis()); */


if(jesus != 0){
buzz=1;
}

if(buzz == 1){
digitalWrite(9, HIGH);
current=millis();
if(current-previous >interval){
previous = current;
buzz=0;
digitalWrite(9, LOW);

}
}

current1=millis();
if(current1-previous1 >10000){
previous1 = current1;
if(TRIMC!=TRIMc){
//Serial.println(" save ");
EEPROM.write(1,AEL_TRIM);
EEPROM.write(2,ELE_TRIM);
EEPROM.write(3,RUD_TRIM);
TRIMc=TRIMC;
}
}
}

Re: quadcopter controlled via pc?

Posted: Mon Aug 01, 2011 10:00 am
by pixelseventy2
that's great, thanks. Might be perfect for what I'm looking to do, means I can use the known-good multiwii software but still control it how I want. What sort of a range do those transmitters have?

Re: quadcopter controlled via pc?

Posted: Mon Aug 01, 2011 1:02 pm
by cardboard
its standard 2.4qhz gear so i assume it'd be on par with any other radio gear. you could try upgrading the antenna. they do it with fpv why not the tx/rx?

Re: quadcopter controlled via pc?

Posted: Sat Apr 14, 2012 5:08 am
by dfidalgo
I have done also the Ian Johnston Joystick solution, and works great (http://www.youtube.com/watch?feature=pl ... IUw7Lfdme4).
But if you don't want canabalise your joystick, I think that this is what you are looking for:

https://www.insecure.ws/2010/03/19/cont ... se-windows

A cheap solution and open source, maybe you can improve the source code

Cheers