Monday, May 20, 2013

25. Had to remove the servo of one of the Ailerons




24. Update Switch-out from Auto-Pilot Mode

1. In order to receive indication physically on Dev Board that we have switched out from Auto-Pilot Mode  we use the Blue LED (declared in ConfigUDB4.h file) present on it.

So in servoMix.c file we made the following changes:

void startupfuntion(void)
{
if (startflag == 0)
{
startflag =1;
currentvalue = mychannelvalue;
}
}

void checkmode(void)
{
diff = mychannelvalue-currentvalue;
if((diff>100) || (diff<-100))
//if (diff==1)
{
currentvalue = mychannelvalue;
if(LED_BLUE == 0)
LED_BLUE = 1;
else
LED_BLUE = 0;
if (flags._.GPS_steering == 1 && flags._.pitch_feedback == 1 && udb_flags._.radio_on == 1)
            {
 next_waypoint();
              currentvalue = mychannelvalue;
}
}
}

2. Also we declared our int variable - diff in defines.h file so that it may be used for other purposes too, and removed its static declaration:

extern int diff; //extern helps to access a variable/function defined in a single file and makes it available for all the other files in our program

3. In order to check what difference in servoMix.c file (diff) is coming in the - diff = mychannelvalue-currentvalue;, so that we may check whether vale in our condition - if((diff>100) || (diff<-100)) is within range or not. So we opened telemetry.c file and did the following changes:


// Yaw
// Earth Frame of Reference
// Ardustation does not use yaw in degrees
// matrix_accum.x = rmat[4] ;
// matrix_accum.y = rmat[1] ;
// earth_yaw = rect_to_polar(&matrix_accum) ; // binary angle (0 - 256 = 360 degrees)
// earth_yaw = (earth_yaw * BYTECIR_TO_DEGREE) >> 16 ; // switch polarity, convert to -180 - 180 degrees
// The Ardupilot GroundStation protocol is mostly documented here:
//    http://diydrones.com/profiles/blogs/ardupilot-telemetry-protocol
if (udb_heartbeat_counter % 40 == 0)  // Every 8 runs (5 heartbeat counts per 8Hz)
{
serial_output("!!!LAT:%li,LON:%li,SPD:%.2f,CRT:%.2f,ALT:%li,ALH:%i,CRS:%.2f,BER:%i,WPN:%i,DST:%i,BTV:%.2f***\r\n"
 "+++THH:%i,RLL:%li,PCH:%li,STT:%i,***\r\n",
lat_gps.WW / 10 , long_gps.WW / 10 , (float)(sog_gps.BB / 100.0), (float)(climb_gps.BB / 100.0),
(alt_sl_gps.WW - alt_origin.WW) / 100, desiredHeight, (float)(cog_gps.BB / 100.0), desired_dir_deg,
waypointIndex, diff, (float)(voltage_milis.BB / 100.0), 
(int16_t)((udb_pwOut[THROTTLE_OUTPUT_CHANNEL] - udb_pwTrim[THROTTLE_OUTPUT_CHANNEL])/20),
earth_roll, earth_pitch,
mode
) ;
}
else if (udb_heartbeat_counter % 10 == 0)  // Every 2 runs (5 heartbeat counts per 8Hz)
{
serial_output("+++THH:%i,RLL:%li,PCH:%li,STT:%i,***\r\n",
(int16_t)((udb_pwOut[THROTTLE_OUTPUT_CHANNEL] - udb_pwTrim[THROTTLE_OUTPUT_CHANNEL])/20),
earth_roll, earth_pitch,
mode
) ;
}
return ;
}

We changed to diff from tofinish_line so that in Realterm Software we may see the diff value coming and set our condition accordingly.


4. And finally: What is the meaning of diff?

Diff is the decimal difference in milliseconds that comes between the up and down position of the switch we will use, on the transmitter, to switch-out from Auto-Pilot mode.

Saturday, May 18, 2013

23. Switch-out from Auto-Pilot Mode : Another function for #UAV

In our previous programming segment (16. Auto Take-Off and Auto-Landing programming of the #UAV and 6. How are we going to build a more stable Loiter program? - The Idea.) we had made Auto-Pilot program and also an Auto-take off and Auto-landing program for our U.A.V.

Then we thought more. What if due to some reason we want our U.A.V to move out of the Auto-Pilot mode towards the next desired waypoint (like sometimes we may want a quick auto-landing or surveillance of some other area)?. Hence we came up with another addition to the whole program we had made so far.

We decided to use one of the 2 output channels left (rest 5 out total 7 are used for Aileron, Throttle, rudder, Elevator and Mode) of the UDB Devboard to receive a signal from our transmitter so that whenever we change the position of the switch from its initial position (at start-up) i.e. from up to down or down to up, our  DevBoard will switch out of the Auto-Pilot mode.

So in order form a logic, we first tried a simple C program in which if we press any letter different from the one we have put in the memory (through scanf function), then it will display a certain message and if we press the same letter as in the memory then another certain message will appear:


#include <stdio.h>
#include <conio.h>

int main()

{
char in, oc;
in = 'j';
printf("Testing code");
while(1)
{
          printf("input pls");
          oc=getch(); // so that we do not have to press enter every-time we enter something on screen
          //scanf("%c", &oc);
          //printf("yes wrkin");
          if (oc!=in)
             {
                     printf("Matched");
                    if ( (oc == 'j')||(oc == 'h'))
                       {
                                printf("moved to next waypoint");
                                in = oc;
                       }
             }
}
   getch();
   return 0;
}

To implement this idea we went into the servoMix.c file of our program and edited the following:

static int mychannelvalue =0;
static char startflag =0; // will be used to check position of switch at sart-up only once
void startupfuntion(void); //to store the current position of the switch
void checkmode (void); // to check the position of the switch, if changed then switch-out of Auto-Pilot mode
static int currentvalue =0;

// Helicopter airframe
// Mix half of roll_control and half of pitch_control into aileron channels
// Mix full pitch_control into elevator
// Ignore waggle for now
#if ( AIRFRAME_TYPE == AIRFRAME_HELI )
temp = pwManual[AILERON_INPUT_CHANNEL] +
REVERSE_IF_NEEDED(AILERON_CHANNEL_REVERSED, roll_control/2 +

pitch_control/2) ;
udb_pwOut[AILERON_OUTPUT_CHANNEL] = udb_servo_pulsesat( temp ) ;

temp = pwManual[ELEVATOR_INPUT_CHANNEL] +

REVERSE_IF_NEEDED(ELEVATOR_CHANNEL_REVERSED, pitch_control) ;
udb_pwOut[ELEVATOR_OUTPUT_CHANNEL] = udb_servo_pulsesat( temp ) ;

temp = pwManual[AILERON_SECONDARY_OUTPUT_CHANNEL] +
REVERSE_IF_NEEDED(AILERON_SECONDARY_CHANNEL_REVERSED,

-roll_control/2 + pitch_control/2) ;
udb_pwOut[AILERON_SECONDARY_OUTPUT_CHANNEL] = temp ;

temp = pwManual[RUDDER_INPUT_CHANNEL] /*+

REVERSE_IF_NEEDED(RUDDER_CHANNEL_REVERSED, yaw_control)*/ ;
udb_pwOut[RUDDER_OUTPUT_CHANNEL] = udb_servo_pulsesat( temp ) ;

if ( pwManual[THROTTLE_INPUT_CHANNEL] == 0 )
{
udb_pwOut[THROTTLE_OUTPUT_CHANNEL] = 0 ;
}
else
{
temp = pwManual[THROTTLE_INPUT_CHANNEL] +

REVERSE_IF_NEEDED(THROTTLE_CHANNEL_REVERSED, throttle_control) ;
udb_pwOut[THROTTLE_OUTPUT_CHANNEL] = udb_servo_pulsesat( temp ) ;
}
#endif
mychannelvalue = udb_servo_pulsesat( pwManual[PASSTHROUGH_A_INPUT_CHANNEL] )

;

startupfuntion();
checkmode();
// next_waypoint();      

udb_pwOut[PASSTHROUGH_A_OUTPUT_CHANNEL] = udb_servo_pulsesat(

pwManual[PASSTHROUGH_A_INPUT_CHANNEL] ) ;
udb_pwOut[PASSTHROUGH_B_OUTPUT_CHANNEL] = udb_servo_pulsesat(

pwManual[PASSTHROUGH_B_INPUT_CHANNEL] ) ;
udb_pwOut[PASSTHROUGH_C_OUTPUT_CHANNEL] = udb_servo_pulsesat(

pwManual[PASSTHROUGH_C_INPUT_CHANNEL] ) ;
udb_pwOut[PASSTHROUGH_D_OUTPUT_CHANNEL] = udb_servo_pulsesat(

pwManual[PASSTHROUGH_D_INPUT_CHANNEL] ) ;
}

void cameraServoMix( void )
{
int32_t temp ;
int16_t pwManual[NUM_INPUTS+1] ;

// If radio is off, use udb_pwTrim values instead of the udb_pwIn values
for (temp = 0; temp <= NUM_INPUTS; temp++)
if (udb_flags._.radio_on)
pwManual[temp] = udb_pwIn[temp];
else
pwManual[temp] = udb_pwTrim[temp];

temp = ( pwManual[CAMERA_PITCH_INPUT_CHANNEL] - 3000 ) +

REVERSE_IF_NEEDED(CAMERA_PITCH_CHANNEL_REVERSED,
cam_pitch_servo_pwm_delta ) ;
temp = cam_pitchServoLimit(temp) ;
udb_pwOut[CAMERA_PITCH_OUTPUT_CHANNEL] = udb_servo_pulsesat( temp + 3000 ) ;

temp = ( pwManual[CAMERA_YAW_INPUT_CHANNEL] - 3000 ) +

REVERSE_IF_NEEDED(CAMERA_YAW_CHANNEL_REVERSED,
cam_yaw_servo_pwm_delta ) ;
temp = cam_yawServoLimit(temp) ;
udb_pwOut[CAMERA_YAW_OUTPUT_CHANNEL] = udb_servo_pulsesat( temp + 3000 ) ;
}

void startupfuntion(void)
{
if (startflag == 0)
{
startflag =1;
currentvalue = mychannelvalue;
}
}

void checkmode(void)
{
int diff;
diff = mychannelvalue-currentvalue;
 if(diff>100 || diff<-100)
{
             if (flags._.GPS_steering == 1 && flags._.pitch_feedback == 1 && udb_flags._.radio_on == 1) //to check if in Auto-Pilot mode, else will never go for the function, make sure only Auto-Pilot switch-out
            {
 next_waypoint();
                           currentvalue = mychannelvalue;
}
}
}

22. Tip2 for #UAV

Always debug (i.e. check for values in a particular part of the program) your program in a PIC controller testing kit with MPLab 8.9, because UDB4 Devboard does not provide the facility to debug, i.e it can't be debugged with PICKit 2. This will help you as you will discover in the next post on this blog. (Wink! Wink!)
  1. You may double click on the left hand side of the line where you want to debug. A letter 'B' in red circle will appear at that point. Change the mode of the MPLab setup to Debug (originally its Release). 
  2. After the changes above you may build your program.
  3. Connect the PICKit 2 with the testing board and program it.
  4. Next go to View - Locals. A window will appear which will show you values at the breakpoints set by you every time you Run the debugging.



Wednesday, May 15, 2013

21. Tip1 for #UAV

Tip: After making all the changes to the hardware of the fuselage according to your requirements, do check the Center of Gravity of the whole plane.

Monday, May 13, 2013

19. Coordinating hardware with our program

We went into the options.h file of Matrix-Pilot UDB4 and did the following changes:

(Where left columns is from the receiver and the right column on the devboard)

// Configure Input and Output Channels
//
// For classic UDB boards:
// Use a single PPM input connection from the RC receiver to the UDB on RC input channel 4.
// This frees up RC inputs 3, 2, and 1 to act as RC outputs 4, 5, and 6.
// If PPM_ALT_OUTPUT_PINS is set to 0, the 9 available RC outputs will be sent to the
// following pins, in this order: Out1, Out2, Out3, In3, In2, In1, RE0, RE2, RE4.
// With it set to 1, the RC outputs will be in this alternate configuration:
// Out1, Out2, Out3, RE0, RE2, RE4, In3, In2, In1.
//
// For UDB4 boards:
// Use a single PPM input connection from the RC receiver to the UDB on RC input channel 1.
// The 8 standard output channels remain unaffected.  2 additional output channels are available
// on pins RA4 and RA1.
//
// For all boards:
// If you're not sure, leave USE_PPM_INPUT set to 0.
// PPM_NUMBER_OF_CHANNELS is the number of channels sent on the PWM signal.  This is
// often different from the NUM_INPUTS value below, and should usually be left at 8.
//
#define USE_PPM_INPUT 0
#define PPM_NUMBER_OF_CHANNELS 8
#define PPM_SIGNAL_INVERTED 0
#define PPM_ALT_OUTPUT_PINS 0

// NUM_INPUTS:
// For classic boards: Set to 1-5 (or 1-8 when using PPM input)
//   1-4 enables only the first 1-4 of the 4 standard input channels
//   5 also enables E8 as the 5th input channel
// For UDB4 boards: Set to 1-8
#define NUM_INPUTS 6

// Channel numbers for each input.
// Use as is, or edit to match your setup.
//   - If you're set up to use Rudder Navigation (like MatrixNav), then you may want to swap
//     the aileron and rudder channels so that rudder is CHANNEL_1, and aileron is 5.
#define THROTTLE_INPUT_CHANNEL CHANNEL_1
#define AILERON_INPUT_CHANNEL CHANNEL_2
#define ELEVATOR_INPUT_CHANNEL CHANNEL_3
#define RUDDER_INPUT_CHANNEL CHANNEL_4
#define MODE_SWITCH_INPUT_CHANNEL CHANNEL_6
#define CAMERA_PITCH_INPUT_CHANNEL CHANNEL_UNUSED
#define CAMERA_YAW_INPUT_CHANNEL CHANNEL_UNUSED
#define CAMERA_MODE_INPUT_CHANNEL CHANNEL_UNUSED
#define OSD_MODE_SWITCH_INPUT_CHANNEL        CHANNEL_UNUSED
#define PASSTHROUGH_A_INPUT_CHANNEL CHANNEL_5
#define PASSTHROUGH_B_INPUT_CHANNEL CHANNEL_UNUSED
#define PASSTHROUGH_C_INPUT_CHANNEL CHANNEL_UNUSED
#define PASSTHROUGH_D_INPUT_CHANNEL CHANNEL_UNUSED

// NUM_OUTPUTS:
// For classic boards: Set to 3, 4, 5, or 6
//   3 enables only the standard 3 output channels
//   4 also enables E0 as the 4th output channel
//   5 also enables E2 as the 5th output channel
//   6 also enables E4 as the 6th output channel
//   NOTE: If USE_PPM_INPUT is enabled above, up to 9 outputs are available.)
// For UDB4 boards: Set to 3-8 (or up to 10 using pins RA4 and RA1.)
#define NUM_OUTPUTS 5

// Channel numbers for each output
// Use as is, or edit to match your setup.
//   - Only assign each channel to one output purpose
//   - If you don't want to use an output channel, set it to CHANNEL_UNUSED
//   - If you're set up to use Rudder Navigation (like MatrixNav), then you may want to swap
//     the aileron and runner channels so that rudder is CHANNEL_1, and aileron is 5.
//
// NOTE: If your board is powered from your ESC through the throttle cable, make sure to
// connect THROTTLE_OUTPUT_CHANNEL to one of the built-in Outputs (1, 2, or 3) to make
// sure your board gets power.
//
#define THROTTLE_OUTPUT_CHANNEL CHANNEL_1
#define AILERON_OUTPUT_CHANNEL CHANNEL_2
#define ELEVATOR_OUTPUT_CHANNEL CHANNEL_3
#define RUDDER_OUTPUT_CHANNEL CHANNEL_5
#define AILERON_SECONDARY_OUTPUT_CHANNEL        CHANNEL_UNUSED
#define CAMERA_PITCH_OUTPUT_CHANNEL CHANNEL_UNUSED
#define CAMERA_YAW_OUTPUT_CHANNEL CHANNEL_UNUSED
#define TRIGGER_OUTPUT_CHANNEL CHANNEL_UNUSED
#define PASSTHROUGH_A_OUTPUT_CHANNEL CHANNEL_4
#define PASSTHROUGH_B_OUTPUT_CHANNEL CHANNEL_UNUSED
#define PASSTHROUGH_C_OUTPUT_CHANNEL CHANNEL_UNUSED
#define PASSTHROUGH_D_OUTPUT_CHANNEL CHANNEL_UNUSED

Next we soldered four channel cables with our DevBoard and by attaching each cable with a servo motor  ( while attaching another to a power supply) we checked whether our transmitter was working as we programmed or not. The four channels (Throttle, Aileron, Rudder and Elevator) were working just fine.