diff --git a/quad/scripts/tests/test_safety_checks.rb b/quad/scripts/tests/test_safety_checks.rb index 922d6439f77b4c245ce1742dbd786f2fcbd81a06..9e7d693e6ee8459bedf24cc503a6265dcd8e6db0 100644 --- a/quad/scripts/tests/test_safety_checks.rb +++ b/quad/scripts/tests/test_safety_checks.rb @@ -34,34 +34,36 @@ Timeout::timeout(30) { puts("Beginning tests...") - # Set gravity + # Set gravity and gear File.write(I2C_MPU_ACCEL_Z, -1 * GRAVITY) + File.write(GEAR, GEAR_OFF) puts("Check that motors are off at startup") - check_motors_are_off + check_motors_are_off "Motors weren't off at startup! How dangerous!" puts("Check that LED is off at startup") - check_led(0) + check_led(0, "LED was on at startup! It should be off so that we can verify when the quad is ready.") puts("Check that increasing the throttle does nothing to motors") # (because gear is still off) - for i in (THROTTLE_MIN..THROTTLE_MAX).step(1000) + for i in (THROTTLE_MIN..THROTTLE_MAX).step(0.01) File.write(THROTTLE, i) - check_motors_are_off + check_motors_are_off "Was able to turn on motors with GEAR off! Yikes!" + check_led(0, "LED turned on while GEAR was off!") sleep 0.005 end puts("Check that flipping gear to 1 while throttle is high does nothing") # (motors should still be off, LED should still be off) File.write(GEAR, GEAR_ON) - sleep 0.015 - check_motors_are_off + sleep 0.5 + check_motors_are_off "Motors turned on by gear while rc throttle was high! How dangerous!" i = THROTTLE_MAX while i > THROTTLE_MID - i -= 1000 + i -= 0.01 File.write(THROTTLE, i) - check_motors_are_off - check_led 0 + check_motors_are_off "Motors turned on while GEAR was off. Yikes!" + check_led(0, "LED turned on while GEAR was off!") sleep 0.005 end @@ -73,8 +75,8 @@ Timeout::timeout(30) { # (motors should still be off because our throttle is low) File.write(GEAR, GEAR_ON) sleep 0.5 - check_motors_are_off - check_led 1 + check_motors_are_off "Motors turned on while throttle was low! Yikes!" + check_led(1, "LED didn't turn on when GEAR was switched on!") puts("Check that motors turn on") File.write(THROTTLE, THROTTLE_MID) @@ -87,7 +89,7 @@ Timeout::timeout(30) { # (and that light goes off) File.write(GEAR, GEAR_OFF) sleep 0.5 - check_motors_are_off + check_motors_are_off "Motors didn't turn off when GEAR was switched off! How dangerous!" #check_led 0 # (Bring the RC throttle back down) diff --git a/quad/scripts/tests/testing_library.rb b/quad/scripts/tests/testing_library.rb index 4deefed674f2cf205b4ad9b0bc6649a5dd882557..5324eacdd4dd8f9ad1d73aa79263a37f3b1a30e8 100644 --- a/quad/scripts/tests/testing_library.rb +++ b/quad/scripts/tests/testing_library.rb @@ -1,23 +1,23 @@ -THROTTLE_MIN = 110200 -THROTTLE_MAX = 191900 +THROTTLE_MIN = 0.10200 +THROTTLE_MAX = 0.91900 THROTTLE_MID = (THROTTLE_MAX + THROTTLE_MIN)/2 THROTTLE_3_4 = (THROTTLE_MAX + THROTTLE_MID)/2 THROTTLE_QUAR = (THROTTLE_MID + THROTTLE_MIN)/2 THROTTLE_EIGHTH = (THROTTLE_QUAR + THROTTLE_MIN)/2 THROTTLE_16 = (THROTTLE_EIGHTH + THROTTLE_MIN)/2 -MOTOR_MIN = 100000 -MOTOR_MAX = 200000 -GEAR_ON = 170800 -GEAR_OFF = 118300 +MOTOR_MIN = 0.0 +MOTOR_MAX = 1.0 +GEAR_ON = 0.70800 +GEAR_OFF = 0.18300 GRAVITY = 4096 -MOTOR1 = "virt-quad-fifos/pwm-output-motor1" -MOTOR2 = "virt-quad-fifos/pwm-output-motor2" -MOTOR3 = "virt-quad-fifos/pwm-output-motor3" -MOTOR4 = "virt-quad-fifos/pwm-output-motor4" +MOTOR1 = "virt-quad-fifos/motor1" +MOTOR2 = "virt-quad-fifos/motor2" +MOTOR3 = "virt-quad-fifos/motor3" +MOTOR4 = "virt-quad-fifos/motor4" -GEAR = "virt-quad-fifos/pwm-input-gear" -THROTTLE = "virt-quad-fifos/pwm-input-throttle" +GEAR = "virt-quad-fifos/rc-gear" +THROTTLE = "virt-quad-fifos/rc-throttle" LED = "virt-quad-fifos/mio7-led" @@ -43,15 +43,15 @@ def read_fifo_num(f) end # Utility functions -def check_motors_are_off +def check_motors_are_off(msg) motor1 = read_fifo_num(MOTOR1) motor2 = read_fifo_num(MOTOR2) motor3 = read_fifo_num(MOTOR3) motor4 = read_fifo_num(MOTOR4) - assert_operator motor1, :<=, THROTTLE_MIN - assert_operator motor2, :<=, THROTTLE_MIN - assert_operator motor3, :<=, THROTTLE_MIN - assert_operator motor4, :<=, THROTTLE_MIN + assert_operator(motor1, :<=, THROTTLE_MIN, msg) + assert_operator(motor2, :<=, THROTTLE_MIN, msg) + assert_operator(motor3, :<=, THROTTLE_MIN, msg) + assert_operator(motor4, :<=, THROTTLE_MIN, msg) end def get_motor_averages @@ -71,9 +71,9 @@ def get_motor_averages average end -def check_led(is_on) +def check_led(is_on, msg) led = read_fifo_num(LED) - assert_equal(is_on, led) + assert_equal(is_on, led, msg) end def delay_spin_cursor(delay) diff --git a/quad/src/graph_blocks/node_mixer.c b/quad/src/graph_blocks/node_mixer.c index 40972ad15521e1ce2d2755eac66afeaf18a0ae35..046f133eefde61de324f61d805f5dbc97616c664 100644 --- a/quad/src/graph_blocks/node_mixer.c +++ b/quad/src/graph_blocks/node_mixer.c @@ -1,30 +1,30 @@ #include "node_mixer.h" #include <stdlib.h> -static int pwm_min = 100000; -static int pwm_max = 200000; +static int motor_min = 0.00000; +static int motor_max = 1.00000; -static int pwm_clamp(int val) { - if (val < pwm_min) {val = pwm_min;} - if (val > pwm_max) {val = pwm_max;} +static double motor_clamp(double val) { + if (val < motor_min) {val = motor_min;} + if (val > motor_max) {val = motor_max;} return val; } static void mixer_computation(void *state, const double* params, const double *inputs, double *outputs) { - int pwm0 = inputs[MIXER_THROTTLE] - inputs[MIXER_PITCH] - inputs[MIXER_ROLL] - inputs[MIXER_YAW]; - int pwm1 = inputs[MIXER_THROTTLE] + inputs[MIXER_PITCH] - inputs[MIXER_ROLL] + inputs[MIXER_YAW]; - int pwm2 = inputs[MIXER_THROTTLE] - inputs[MIXER_PITCH] + inputs[MIXER_ROLL] + inputs[MIXER_YAW]; - int pwm3 = inputs[MIXER_THROTTLE] + inputs[MIXER_PITCH] + inputs[MIXER_ROLL] - inputs[MIXER_YAW]; - outputs[MIXER_PWM0] = pwm_clamp(pwm0); - outputs[MIXER_PWM1] = pwm_clamp(pwm1); - outputs[MIXER_PWM2] = pwm_clamp(pwm2); - outputs[MIXER_PWM3] = pwm_clamp(pwm3); + double motor0 = inputs[MIXER_THROTTLE] - inputs[MIXER_PITCH] - inputs[MIXER_ROLL] - inputs[MIXER_YAW]; + double motor1 = inputs[MIXER_THROTTLE] + inputs[MIXER_PITCH] - inputs[MIXER_ROLL] + inputs[MIXER_YAW]; + double motor2 = inputs[MIXER_THROTTLE] - inputs[MIXER_PITCH] + inputs[MIXER_ROLL] + inputs[MIXER_YAW]; + double motor3 = inputs[MIXER_THROTTLE] + inputs[MIXER_PITCH] + inputs[MIXER_ROLL] - inputs[MIXER_YAW]; + outputs[MIXER_MOTOR0] = motor_clamp(motor0); + outputs[MIXER_MOTOR1] = motor_clamp(motor1); + outputs[MIXER_MOTOR2] = motor_clamp(motor2); + outputs[MIXER_MOTOR3] = motor_clamp(motor3); } static void reset_mixer(void *state) {} static const char* const in_names[4] = {"Throttle", "Pitch", "Roll", "Yaw"}; -static const char* const out_names[4] = {"PWM 0", "PWM 1", "PWM 2", "PWM 3"}; +static const char* const out_names[4] = {"MOTOR 0", "MOTOR 1", "MOTOR 2", "MOTOR 3"}; static const char* const param_names[1] = {"You shouldnt see this"}; const struct graph_node_type node_mixer_type = { .input_names = in_names, diff --git a/quad/src/graph_blocks/node_mixer.h b/quad/src/graph_blocks/node_mixer.h index 374a88be39e409806c6c7a43d95cb5e5b35e7849..c2805fe8dc078c225b41dce8ef3be771be506e09 100644 --- a/quad/src/graph_blocks/node_mixer.h +++ b/quad/src/graph_blocks/node_mixer.h @@ -13,10 +13,10 @@ enum graph_node_mixer_inputs { }; enum graph_node_mixer_outputs { - MIXER_PWM0, - MIXER_PWM1, - MIXER_PWM2, - MIXER_PWM3, + MIXER_MOTOR0, + MIXER_MOTOR1, + MIXER_MOTOR2, + MIXER_MOTOR3, }; #endif // __NODE_MIXER_H__ diff --git a/quad/src/quad_app/PID.h b/quad/src/quad_app/PID.h index faf5579f090e7bfe424725ce65a762e7fa9a8e9b..9188e097192f6cf6a515482d8a235fdbae593ebb 100644 --- a/quad/src/quad_app/PID.h +++ b/quad/src/quad_app/PID.h @@ -15,7 +15,7 @@ // Yaw constants // when using units of radians -#define YAW_ANGULAR_VELOCITY_KP 29700//200.0f * 2292.0f +#define YAW_ANGULAR_VELOCITY_KP 0.297 #define YAW_ANGULAR_VELOCITY_KI 0.0f #define YAW_ANGULAR_VELOCITY_KD 0.0f #define YAW_ANGLE_KP 2.6f @@ -25,9 +25,9 @@ // when using units of radians -#define ROLL_ANGULAR_VELOCITY_KP 3000 +#define ROLL_ANGULAR_VELOCITY_KP 0.03 #define ROLL_ANGULAR_VELOCITY_KI 0.0f -#define ROLL_ANGULAR_VELOCITY_KD 500 +#define ROLL_ANGULAR_VELOCITY_KD 0.005 #define ROLL_ANGULAR_VELOCITY_ALPHA 0.88 #define ROLL_ANGLE_KP 35 #define ROLL_ANGLE_KI 0.0f @@ -44,9 +44,9 @@ //Pitch constants // when using units of radians -#define PITCH_ANGULAR_VELOCITY_KP 3000 +#define PITCH_ANGULAR_VELOCITY_KP 0.03 #define PITCH_ANGULAR_VELOCITY_KI 0.0f -#define PITCH_ANGULAR_VELOCITY_KD 500 +#define PITCH_ANGULAR_VELOCITY_KD 0.005 #define PITCH_ANGULAR_VELOCITY_ALPHA 0.88 #define PITCH_ANGLE_KP 35 #define PITCH_ANGLE_KI 0.0f @@ -62,9 +62,9 @@ //Throttle constants -#define ALT_ZPOS_KP -9804.0f -#define ALT_ZPOS_KI -817.0f -#define ALT_ZPOS_KD -7353.0f +#define ALT_ZPOS_KP -0.09804f +#define ALT_ZPOS_KI -0.00817f +#define ALT_ZPOS_KD -0.07353f #define ALT_ZPOS_ALPHA 0.88 #endif /* PID_H_ */ diff --git a/quad/src/quad_app/actuator_command_processing.c b/quad/src/quad_app/actuator_command_processing.c deleted file mode 100644 index e27dbf434d1aba16341a67fc3115f3ea2d88725f..0000000000000000000000000000000000000000 --- a/quad/src/quad_app/actuator_command_processing.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * actuator_command_processing.c - * - * Created on: Feb 20, 2016 - * Author: ucart - */ - -#include "actuator_command_processing.h" -#include "sensor_processing.h" -#include "controllers.h" - -int actuator_command_processing(log_t* log_struct, user_input_t * user_input_struct, raw_actuator_t* raw_actuator_struct, actuator_command_t* actuator_command_struct) -{ - - Aero_to_PWMS(actuator_command_struct->pwms, raw_actuator_struct->controller_corrected_motor_commands); -// old_Aero_to_PWMS(actuator_command_struct->pwms, raw_actuator_struct->controller_corrected_motor_commands); - - return 0; -} - -/** - * Converts Aero 4 channel signals to PWM signals - * Aero channels are defined above - */ -void Aero_to_PWMS(int* PWMs, int* aero) -{ - int motor0_bias = 0, motor1_bias = 0, motor2_bias = 0, motor3_bias = 0; - int pwm0 = 0, pwm1 = 0, pwm2 = 0, pwm3 = 0; - - pwm0 = aero[THROTTLE] - aero[PITCH] - aero[ROLL] - aero[YAW] + motor0_bias; - pwm1 = aero[THROTTLE] + aero[PITCH] - aero[ROLL] + aero[YAW] + motor1_bias; - pwm2 = aero[THROTTLE] - aero[PITCH] + aero[ROLL] + aero[YAW] + motor2_bias; - pwm3 = aero[THROTTLE] + aero[PITCH] + aero[ROLL] - aero[YAW] + motor3_bias; - -// printf("pwm0: %d\tpwm1: %d\tpwm2: %d\tpwm3: %d\n", pwm0, pwm1, pwm2, pwm3); - - /** - * Boundary checks: - * - * #define min 100000 - * #define max 200000 - */ - - if(pwm0 < min) - pwm0 = min; - else if(pwm0 > max) - pwm0 = max; - - if(pwm1 < min) - pwm1 = min; - else if(pwm1 > max) - pwm1 = max; - - if(pwm2 < min) - pwm2 = min; - else if(pwm2 > max) - pwm2 = max; - - if(pwm3 < min) - pwm3 = min; - else if(pwm3 > max) - pwm3 = max; - - PWMs[0] = pwm0; - PWMs[1] = pwm1; - PWMs[2] = pwm2; - PWMs[3] = pwm3; - - // the array PWMs is then written directly to the PWM hardware registers - // the PWMs are in units of clock cycles, not percentage duty cycle - // use pwm/222,222 to get the duty cycle. the freq is 450 Hz on a 100MHz clock -} - -/** - * Converts Aero 4 channel signals to PWM signals - * Aero channels are defined above - * - * *deprecated - */ -void old_Aero_to_PWMS(int* PWMs, int* aero) { - - int motor0_bias = -9900, motor1_bias = -200, motor2_bias = -10200, motor3_bias = 250; -// int motor0_bias = -5000, motor1_bias = 0, motor2_bias = -5000, motor3_bias = 0; - - // Throttle, pitch, roll, yaw as a percentage of their max - Range 0.0 - 100.0 - float throttle_100 = (aero[THROTTLE] - THROTTLE_MIN) / (THROTTLE_RANGE*1.0); - float pitch_100 = (aero[PITCH] - PITCH_MIN) / (PITCH_RANGE*1.0); - float roll_100 = (aero[ROLL] - ROLL_MIN) / (ROLL_RANGE*1.0); - float yaw_100 = (aero[YAW] - YAW_MIN) / (YAW_RANGE*1.0); - - // This adds a +/- 300 ms range bias for the throttle - int throttle_base = BASE + (int) 60000 * (throttle_100 - .5); - // This adds a +/- 200 ms range bias for the pitch - int pitch_base = (int) 60000 * (pitch_100 - .5); - // This adds a +/- 200 ms range bias for the roll - int roll_base = (int) 60000 * (roll_100 - .5); - // This adds a +/- 75 ms range bias for the yaw - int yaw_base = (int) 15000 * (yaw_100 - .5); - - int pwm0, pwm1, pwm2, pwm3; - - pwm1 = throttle_base + pitch_base/2 - roll_base/2 + yaw_base + motor1_bias; - pwm3 = throttle_base + pitch_base/2 + roll_base/2 - yaw_base + motor3_bias; - pwm0 = throttle_base - pitch_base/2 - roll_base/2 - yaw_base + motor0_bias; - pwm2 = throttle_base - pitch_base/2 + roll_base/2 + yaw_base + motor2_bias; - - /** - * Boundary checks: - * - * #define min 100000 - * #define max 200000 - */ - - if(pwm0 < min) - pwm0 = min; - else if(pwm0 > max) - pwm0 = max; - - if(pwm1 < min) - pwm1 = min; - else if(pwm1 > max) - pwm1 = max; - - if(pwm2 < min) - pwm2 = min; - else if(pwm2 > max) - pwm2 = max; - - if(pwm3 < min) - pwm3 = min; - else if(pwm3 > max) - pwm3 = max; - - PWMs[0] = pwm0; - PWMs[1] = pwm1; - PWMs[2] = pwm2; - PWMs[3] = pwm3; - - // the array PWMs is then written directly to the PWM hardware registers - // the PWMs are in units of clock cycles, not percentage duty cycle - // use pwm/222,222 to get the duty cycle. the freq is 450 Hz on a 100MHz clock - -} diff --git a/quad/src/quad_app/actuator_command_processing.h b/quad/src/quad_app/actuator_command_processing.h deleted file mode 100644 index 12110d5513130b90b4b60f30ffe555bcb370a07e..0000000000000000000000000000000000000000 --- a/quad/src/quad_app/actuator_command_processing.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * actuator_command_processing.h - * - * Created on: Feb 20, 2016 - * Author: ucart - */ - -#ifndef ACTUATOR_COMMAND_PROCESSING_H_ -#define ACTUATOR_COMMAND_PROCESSING_H_ - -#include <stdio.h> - -#include "log_data.h" -#include "control_algorithm.h" - -/** - * @brief - * Processes the commands to the actuators. - * - * @param log_struct - * structure of the data to be logged - * - * @param raw_actuator_struct - * structure of the commmands outputted to go to the actuators - * - * @param actuator_command_struct - * structure of the commmands to go to the actuators - * - * @return - * error message - * - */ -int actuator_command_processing(log_t* log_struct, user_input_t * user_input_struct, raw_actuator_t* raw_actuator_struct, actuator_command_t* actuator_command_struct); - -void old_Aero_to_PWMS(int* PWMs, int* aero); -void Aero_to_PWMS(int* PWMs, int* aero); - -#endif /* ACTUATOR_COMMAND_PROCESSING_H_ */ diff --git a/quad/src/quad_app/control_algorithm.c b/quad/src/quad_app/control_algorithm.c index 7d867cbfc2d498e769cccd1463f1d441710cc3e7..845c584334bdd8b83083ed1215398fb2ca7e0237 100644 --- a/quad/src/quad_app/control_algorithm.c +++ b/quad/src/quad_app/control_algorithm.c @@ -376,22 +376,22 @@ int control_algorithm_init(parameter_t * ps) // don't use the PID corrections if the throttle is less than about 10% of its range // unless we are in autonomous - if((user_input_struct->rc_commands[THROTTLE] > 118000) || + if((user_input_struct->rc_commands[THROTTLE] > 0.18000) || user_defined_struct->flight_mode == AUTO_FLIGHT_MODE) { //THROTTLE - actuator_struct->pwms[0] = graph_get_output(graph, ps->mixer, MIXER_PWM0); - actuator_struct->pwms[1] = graph_get_output(graph, ps->mixer, MIXER_PWM1); - actuator_struct->pwms[2] = graph_get_output(graph, ps->mixer, MIXER_PWM2); - actuator_struct->pwms[3] = graph_get_output(graph, ps->mixer, MIXER_PWM3); + actuator_struct->motor_magnitudes[0] = graph_get_output(graph, ps->mixer, MIXER_MOTOR0); + actuator_struct->motor_magnitudes[1] = graph_get_output(graph, ps->mixer, MIXER_MOTOR1); + actuator_struct->motor_magnitudes[2] = graph_get_output(graph, ps->mixer, MIXER_MOTOR2); + actuator_struct->motor_magnitudes[3] = graph_get_output(graph, ps->mixer, MIXER_MOTOR3); } else { - actuator_struct->pwms[0] = user_input_struct->rc_commands[THROTTLE]; - actuator_struct->pwms[1] = user_input_struct->rc_commands[THROTTLE]; - actuator_struct->pwms[2] = user_input_struct->rc_commands[THROTTLE]; - actuator_struct->pwms[3] = user_input_struct->rc_commands[THROTTLE]; + actuator_struct->motor_magnitudes[0] = user_input_struct->rc_commands[THROTTLE]; + actuator_struct->motor_magnitudes[1] = user_input_struct->rc_commands[THROTTLE]; + actuator_struct->motor_magnitudes[2] = user_input_struct->rc_commands[THROTTLE]; + actuator_struct->motor_magnitudes[3] = user_input_struct->rc_commands[THROTTLE]; } last_fm_switch = cur_fm_switch; diff --git a/quad/src/quad_app/controllers.h b/quad/src/quad_app/controllers.h index 1e12c7590e5fe661b81a1bca31b7398da3e457d3..40c7832601fd0509a002cb2f5c3c29fa80c304ff 100644 --- a/quad/src/quad_app/controllers.h +++ b/quad/src/quad_app/controllers.h @@ -71,39 +71,41 @@ /** * Signals from the Rx mins, maxes and ranges */ -#define THROTTLE_MAX 191900 -#define THROTTLE_MIN 110200 +#define THROTTLE_MAX 0.91900 +#define THROTTLE_MIN 0.10200 #define THROTTLE_RANGE THROTTLE_MAX - THROTTLE_MIN -#define ROLL_MAX 170200 -#define ROLL_MIN 129400 -#define ROLL_CENTER 149800 +#define ROLL_MAX 0.70200 +#define ROLL_MIN 0.29400 +#define ROLL_CENTER 0.49800 #define ROLL_RANGE ROLL_MAX - ROLL_MIN -#define PITCH_MAX 169900 -#define PITCH_MIN 129500 -#define PITCH_CENTER 149700 +#define PITCH_MAX 0.69900 +#define PITCH_MIN 0.29500 +#define PITCH_CENTER 0.49700 #define PITCH_RANGE PITCH_MAX - PITCH_MIN -#define YAW_MAX 169400 -#define YAW_MIN 129300 -#define YAW_CENTER 149800 +#define YAW_MAX 0.69400 +#define YAW_MIN 0.29300 +#define YAW_CENTER 0.49800 #define YAW_RANGE YAW_MAX - YAW_MIN -#define GEAR_1 170800 -#define GEAR_0 118300 +#define GEAR_1 0.70800 +#define GEAR_0 0.18300 +#define GEAR_MID (GEAR_0 + GEAR_1)/2.0 -#define FLAP_1 192000 -#define FLAP_0 107600 +#define FLAP_1 0.92000 +#define FLAP_0 0.07600 +#define FLAP_MID (FLAP_0 + FLAP_1)/2.0 #define GEAR_KILL GEAR_0 // The kill point for the program -#define BASE 150000 +#define BASE 0.50000 -#define min 100000 -#define max 200000 +#define min 0.00000 +#define max 1.00000 -#define MOTOR_MIN 100000 -#define MOTOR_MAX 200000 +#define MOTOR_MIN 0.00000 +#define MOTOR_MAX 1.00000 void filter_PWMs(int* mixer); void PWMS_to_Aero(int* PWMs, int* aero); // <= javey: unused diff --git a/quad/src/quad_app/hw_iface.h b/quad/src/quad_app/hw_iface.h index 48b3d0cf7f3cf26a0931c79e2b9c656dabc608ce..ca787b9fc6dde55ce2cddb69d8c77036aee41cd1 100644 --- a/quad/src/quad_app/hw_iface.h +++ b/quad/src/quad_app/hw_iface.h @@ -28,16 +28,16 @@ struct I2CDriver { unsigned int length); }; -struct PWMOutputDriver { +struct RCReceiverDriver { void *state; - int (*reset)(struct PWMOutputDriver *self); - int (*write)(struct PWMOutputDriver *self, unsigned int channel, unsigned long pulse_width_us); + int (*reset)(struct RCReceiverDriver *self); + int (*read)(struct RCReceiverDriver *self, unsigned int channel, float *magnitude); }; -struct PWMInputDriver { +struct MotorDriver { void *state; - int (*reset)(struct PWMInputDriver *self); - int (*read)(struct PWMInputDriver *self, unsigned int channel, unsigned long *pulse_width_us); + int (*reset)(struct MotorDriver *self); + int (*write)(struct MotorDriver *self, unsigned int channel, float magnitude); }; struct UARTDriver { diff --git a/quad/src/quad_app/initialize_components.c b/quad/src/quad_app/initialize_components.c index e476fd633eb9ecce40eb77af6570eac63462833a..5cd49342dcfffdaeb24649d18ca1555219200438 100644 --- a/quad/src/quad_app/initialize_components.c +++ b/quad/src/quad_app/initialize_components.c @@ -17,18 +17,18 @@ extern int Xil_AssertWait; int protection_loops(modular_structs_t *structs) { - u32 rc_commands[6]; // 6 "receiver_input" elements: Throttle, Pitch, Roll, Yaw, Gear, and Flap + float rc_commands[6]; // 6 "receiver_input" elements: Throttle, Pitch, Roll, Yaw, Gear, and Flap - struct PWMInputDriver *pwm_inputs = &structs->hardware_struct.pwm_inputs; - read_rec_all(pwm_inputs, rc_commands); + struct RCReceiverDriver *rc_receiver = &structs->hardware_struct.rc_receiver; + read_rec_all(rc_receiver, rc_commands); - while(rc_commands[THROTTLE] < 75000 || // wait for RC receiver to connect to transmitter - rc_commands[THROTTLE] > 125000 || // Wait until throttle is low + while(rc_commands[THROTTLE] < 0.075 || // wait for RC receiver to connect to transmitter + rc_commands[THROTTLE] > 0.125 || // Wait until throttle is low read_kill(rc_commands[GEAR]) || // Wait until gear switch is engaged (so you don't immediately break out of the main loop below) !read_flap(rc_commands[FLAP])) // Wait for the flight mode to be set to manual { process_received(structs); - read_rec_all(pwm_inputs, rc_commands); + read_rec_all(rc_receiver, rc_commands); } // let the pilot/observers know that the quad is now active @@ -77,15 +77,15 @@ int init_structs(modular_structs_t *structs) { iic_set_globals(i2c, sys); // Initialize PWM Recorders and Motor outputs - struct PWMInputDriver *pwm_inputs = &structs->hardware_struct.pwm_inputs; - if (pwm_inputs->reset(pwm_inputs)) return -1; - struct PWMOutputDriver *pwm_outputs = &structs->hardware_struct.pwm_outputs; - if (pwm_outputs->reset(pwm_outputs)) return -1; + struct RCReceiverDriver *rc_receiver = &structs->hardware_struct.rc_receiver; + if (rc_receiver->reset(rc_receiver)) return -1; + struct MotorDriver *motors = &structs->hardware_struct.motors; + if (motors->reset(motors)) return -1; // Set motor outputs to off int i; for (i = 0; i < 4; i += 1) { - pwm_outputs->write(pwm_outputs, i, MOTOR_MIN); + motors->write(motors, i, MOTOR_MIN); } // Initialize sensors diff --git a/quad/src/quad_app/log_data.c b/quad/src/quad_app/log_data.c index 5714d32a2e3c41e2ca1dbd7db5bf2217a190132a..bdc38f0eeb05714f73d334ea492ee8c6311abf21 100644 --- a/quad/src/quad_app/log_data.c +++ b/quad/src/quad_app/log_data.c @@ -117,10 +117,10 @@ void initialize_logging(log_t* log_struct, parameter_t* ps) { addOutputToLog(log_struct, ps->x_set, CONST_VAL, m); addOutputToLog(log_struct, ps->y_set, CONST_VAL, m); addOutputToLog(log_struct, ps->alt_set, CONST_VAL, m); - addOutputToLog(log_struct, ps->mixer, MIXER_PWM0, pwm_val); - addOutputToLog(log_struct, ps->mixer, MIXER_PWM1, pwm_val); - addOutputToLog(log_struct, ps->mixer, MIXER_PWM2, pwm_val); - addOutputToLog(log_struct, ps->mixer, MIXER_PWM3, pwm_val); + addOutputToLog(log_struct, ps->mixer, MIXER_MOTOR0, pwm_val); + addOutputToLog(log_struct, ps->mixer, MIXER_MOTOR1, pwm_val); + addOutputToLog(log_struct, ps->mixer, MIXER_MOTOR2, pwm_val); + addOutputToLog(log_struct, ps->mixer, MIXER_MOTOR3, pwm_val); addOutputToLog(log_struct, ps->rc_throttle, PID_CORRECTION, pwm_val); addOutputToLog(log_struct, ps->rc_pitch, PID_CORRECTION, pwm_val); addOutputToLog(log_struct, ps->rc_roll, PID_CORRECTION, pwm_val); diff --git a/quad/src/quad_app/quad_app.c b/quad/src/quad_app/quad_app.c index 01eabe9017f733685ae8f9737398099e657a0bf0..f83cc8698f58c41a42ae255808f1c749b442bdbb 100644 --- a/quad/src/quad_app/quad_app.c +++ b/quad/src/quad_app/quad_app.c @@ -12,7 +12,6 @@ #include "sensor.h" #include "sensor_processing.h" #include "control_algorithm.h" -#include "actuator_command_processing.h" #include "send_actuator_commands.h" #include "update_gui.h" #include "communication.h" @@ -67,10 +66,10 @@ int quad_main(int (*setup_hardware)(hardware_t *hardware_struct)) &(structs.parameter_struct), &(structs.user_defined_struct), &(structs.actuator_command_struct), &structs); // send the actuator commands - send_actuator_commands(&(structs.hardware_struct.pwm_outputs), &(structs.log_struct), &(structs.actuator_command_struct)); + send_actuator_commands(&(structs.hardware_struct.motors), &(structs.log_struct), &(structs.actuator_command_struct)); } else { - kill_motors(&(structs.hardware_struct.pwm_outputs)); + kill_motors(&(structs.hardware_struct.motors)); } // update the GUI update_GUI(&(structs.log_struct)); @@ -115,7 +114,7 @@ int quad_main(int (*setup_hardware)(hardware_t *hardware_struct)) timer_end_loop(&(structs.log_struct)); } - kill_motors(&(structs.hardware_struct.pwm_outputs)); + kill_motors(&(structs.hardware_struct.motors)); flash_MIO_7_led(10, 100); diff --git a/quad/src/quad_app/send_actuator_commands.c b/quad/src/quad_app/send_actuator_commands.c index c361e74db2146e44b80881fec18dde14efef44d3..8120224d0dd07f72cf0382ab5f11a86a352851c6 100644 --- a/quad/src/quad_app/send_actuator_commands.c +++ b/quad/src/quad_app/send_actuator_commands.c @@ -8,12 +8,12 @@ #include "send_actuator_commands.h" #include "util.h" -int send_actuator_commands(struct PWMOutputDriver *pwm_outputs, log_t* log_struct, actuator_command_t* actuator_command_struct) { +int send_actuator_commands(struct MotorDriver *motors, log_t* log_struct, actuator_command_t* actuator_command_struct) { int i; // write the PWMs to the motors for (i = 0; i < 4; i++) { - pwm_outputs->write(pwm_outputs, i, actuator_command_struct->pwms[i]); + motors->write(motors, i, actuator_command_struct->motor_magnitudes[i]); } return 0; diff --git a/quad/src/quad_app/send_actuator_commands.h b/quad/src/quad_app/send_actuator_commands.h index 3f6fb0fc833e3dc87d291ca6a357eed115d17e94..747ba0479ef15d08ed18e1a8c4f8c73694f893e6 100644 --- a/quad/src/quad_app/send_actuator_commands.h +++ b/quad/src/quad_app/send_actuator_commands.h @@ -11,7 +11,6 @@ #include <stdio.h> #include "log_data.h" -#include "actuator_command_processing.h" /** * @brief @@ -27,6 +26,6 @@ * error message * */ -int send_actuator_commands(struct PWMOutputDriver *pwm_outputs, log_t* log_struct, actuator_command_t* actuator_command_struct); +int send_actuator_commands(struct MotorDriver *motors, log_t* log_struct, actuator_command_t* actuator_command_struct); #endif /* SEND_ACTUATOR_COMMANDS_H_ */ diff --git a/quad/src/quad_app/sensor.c b/quad/src/quad_app/sensor.c index 2d9396de9cf254be598bd2d2cbea42bf47528c31..b2f7592c88f667ca9ed9f897ea65dd4b22293ecc 100644 --- a/quad/src/quad_app/sensor.c +++ b/quad/src/quad_app/sensor.c @@ -12,9 +12,9 @@ int sensor_init(raw_sensor_t * raw_sensor_struct, sensor_t * sensor_struct) { - if (iic0_lidarlite_init()) { // init LiDAR - return -1; - } +// if (iic0_lidarlite_init()) { // init LiDAR +// return -1; +// } if(iic0_mpu9150_start() == -1) { return -1; @@ -74,9 +74,9 @@ int get_sensors(log_t* log_struct, user_input_t* user_input_struct, raw_sensor_t log_struct->gam = raw_sensor_struct->gam; - static lidar_t lidar_val; - iic0_lidarlite_read_distance(&lidar_val); - raw_sensor_struct->lidar_distance_m = lidar_val.distance_m; +// static lidar_t lidar_val; +// iic0_lidarlite_read_distance(&lidar_val); +// raw_sensor_struct->lidar_distance_m = lidar_val.distance_m; return 0; } diff --git a/quad/src/quad_app/sensor_processing.h b/quad/src/quad_app/sensor_processing.h index 52b626eafa173ac5c806ad29d52ca03138017060..d340e34583c2a4e77fe7cad13e256c4f02eea955 100644 --- a/quad/src/quad_app/sensor_processing.h +++ b/quad/src/quad_app/sensor_processing.h @@ -19,45 +19,6 @@ #define GEAR 4 #define FLAP 5 -/** - * Signals from the Rx mins, maxes and ranges - */ -//#define THROTTLE_MAX 191900 -//#define THROTTLE_MIN 110200 -//#define THROTTLE_RANGE THROTTLE_MAX - THROTTLE_MIN -// -//#define ROLL_MAX 170200 -////#define ROLL_MAX 167664 -////#define ROLL_CENTER 148532 -//#define ROLL_MIN 129400 -//#define ROLL_CENTER 149800 -//#define ROLL_RANGE ROLL_MAX - ROLL_MIN -// -////#define PITCH_MAX 190800 -//#define PITCH_MAX 169900 -////#define PITCH_MIN 135760 -//#define PITCH_MIN 129500 -////#define PITCH_CENTER 152830 -//#define PITCH_CENTER 149700 -//#define PITCH_RANGE PITCH_MAX - PITCH_MIN -// -//#define YAW_MAX 169400 -//#define YAW_MIN 129300 -//#define YAW_CENTER 149800 -//#define YAW_RANGE YAW_MAX - YAW_MIN -// -//#define GEAR_1 170800 -//#define GEAR_0 118300 -// -//#define FLAP_1 192000 -//#define FLAP_0 107600 -// -//#define GEAR_KILL GEAR_0 // The kill point for the program -//#define BASE 150000 -// -//#define min 100000 -//#define max 200000 - /** * @brief * Processes the data from the sensors. diff --git a/quad/src/quad_app/type_def.h b/quad/src/quad_app/type_def.h index b7e398b6bb4cd2222f384c00b2fc05df9f6504a4..e2e40c1aac046af72fe499ef9b1f7f583bf27be5 100644 --- a/quad/src/quad_app/type_def.h +++ b/quad/src/quad_app/type_def.h @@ -148,7 +148,7 @@ typedef struct PID_values{ * */ typedef struct user_input_t { - u32 rc_commands[6]; // Commands from the RC transmitter + float rc_commands[6]; // Commands from the RC transmitter // float cam_x_pos; // Current x position from the camera system @@ -390,7 +390,7 @@ typedef struct user_defined_t { */ typedef struct raw_actuator_t { - int controller_corrected_motor_commands[6]; + float controller_corrected_motor_commands[6]; } raw_actuator_t; @@ -400,7 +400,7 @@ typedef struct raw_actuator_t { * */ typedef struct actuator_command_t { - int pwms[4]; + float motor_magnitudes[4]; } actuator_command_t; enum PWMChannels { @@ -418,8 +418,8 @@ enum PWMChannels { typedef struct hardware_t { struct I2CDriver i2c; - struct PWMInputDriver pwm_inputs; - struct PWMOutputDriver pwm_outputs; + struct RCReceiverDriver rc_receiver; + struct MotorDriver motors; struct UARTDriver uart; struct TimerDriver global_timer; struct TimerDriver axi_timer; diff --git a/quad/src/quad_app/user_input.c b/quad/src/quad_app/user_input.c index bcb7478bf3ce6b7d9b5e6457e82bdafdce02d915..824910a1b95842ff9947558ee86270e832abd100 100644 --- a/quad/src/quad_app/user_input.c +++ b/quad/src/quad_app/user_input.c @@ -10,8 +10,8 @@ int get_user_input(hardware_t *hardware_struct, log_t* log_struct, user_input_t* user_input_struct) { // Read in values from RC Receiver - struct PWMInputDriver *pwm_inputs = &hardware_struct->pwm_inputs; - read_rec_all(pwm_inputs, user_input_struct->rc_commands); + struct RCReceiverDriver *rc_receiver = &hardware_struct->rc_receiver; + read_rec_all(rc_receiver, user_input_struct->rc_commands); //create setpoints for manual flight // currently in units of radians @@ -44,10 +44,10 @@ int kill_condition(user_input_t* user_input_struct) * - * */ -float convert_from_receiver_cmd(int receiver_cmd, int max_receiver_cmd, int center_receiver_cmd, int min_receiver_cmd, float max_target, float min_target) +float convert_from_receiver_cmd(float receiver_cmd, float max_receiver_cmd, float center_receiver_cmd, float min_receiver_cmd, float max_target, float min_target) { // centers the receiver command by subtracting the given center value. This means that if receiver_cmd == center then receiver_cmd_centered should be 0. - int receiver_cmd_centered = receiver_cmd - center_receiver_cmd; + float receiver_cmd_centered = receiver_cmd - center_receiver_cmd; if(receiver_cmd_centered <= 0) { float ret = ((float)(receiver_cmd_centered * min_target)) / ((float) (min_receiver_cmd - center_receiver_cmd)); diff --git a/quad/src/quad_app/user_input.h b/quad/src/quad_app/user_input.h index c289e99c96e437dcfed2398a6711bcf9ecadb786..674f66e6ea2fdf820f7272ee520c4d84a34d0515 100644 --- a/quad/src/quad_app/user_input.h +++ b/quad/src/quad_app/user_input.h @@ -35,36 +35,6 @@ #define PITCH_DEG_TARGET 12.0f #define PITCH_RAD_TARGET ((float) ((PITCH_DEG_TARGET * 3.141592) / ((float) 180))) -/////// Signals from the Rx mins, maxes and ranges - -//#define THROTTLE_MAX 191900 -//#define THROTTLE_MIN 110200 -//#define THROTTLE_RANGE THROTTLE_MAX - THROTTLE_MIN -// -//#define ROLL_MAX 170200 -//#define ROLL_MIN 129400 -//#define ROLL_CENTER 149800 -//#define ROLL_RANGE ROLL_MAX - ROLL_MIN -// -//#define PITCH_MAX 169900 -//#define PITCH_MIN 129500 -//#define PITCH_CENTER 149700 -//#define PITCH_RANGE PITCH_MAX - PITCH_MIN -// -//#define YAW_MAX 169400 -//#define YAW_MIN 129300 -//#define YAW_CENTER (YAW_MIN + YAW_MAX)/2 //149800 -//#define YAW_RANGE YAW_MAX - YAW_MIN -// -//#define GEAR_1 170800 -//#define GEAR_0 118300 -// -//#define FLAP_1 192000 -//#define FLAP_0 107600 -// -//#define GEAR_KILL GEAR_0 // The kill point for the program -//#define BASE 150000 - /** * @brief * Receives user input to the system. @@ -81,7 +51,7 @@ */ int get_user_input(hardware_t *hardware_struct, log_t* log_struct, user_input_t* user_input_struct); int kill_condition(user_input_t* user_input_struct); -float convert_from_receiver_cmd(int receiver_cmd, int max_receiver_cmd, int center_receiver_cmd, int min_receiver_cmd, float max_target, float min_target); +float convert_from_receiver_cmd(float receiver_cmd, float max_receiver_cmd, float center_receiver_cmd, float min_receiver_cmd, float max_target, float min_target); #endif /* USER_INPUT_H_ */ diff --git a/quad/src/quad_app/util.c b/quad/src/quad_app/util.c index 2f1512a0e407385648f442083b2e5152b3fa8dac..e982432eafb4b624990b3da5b95846cc672abc50 100644 --- a/quad/src/quad_app/util.c +++ b/quad/src/quad_app/util.c @@ -13,10 +13,10 @@ extern int motor0_bias, motor1_bias, motor2_bias, motor3_bias; /** * Reads all 6 receiver channels at once */ -void read_rec_all(struct PWMInputDriver *pwm_input, u32 *mixer){ +void read_rec_all(struct RCReceiverDriver *rc_receiver, float *mixer){ int i; for(i = 0; i < 6; i++){ - pwm_input->read(pwm_input, i, &mixer[i]); + rc_receiver->read(rc_receiver, i, &mixer[i]); } } @@ -48,30 +48,37 @@ int hexStrToInt(char *buf, int startIdx, int endIdx) { * If the message from the receiver is 0 - gear, kill the system by sending a 1 * Otherwise, do nothing */ -int read_kill(int gear){ - if(gear > 115000 && gear < 125000) +int read_kill(float gear) { + if(gear < GEAR_MID) return 1; return 0; } -int read_flap(int flap) -{ - // flap '0' is 108,000 CC (Up) - // flap '1' is 192,000 CC (Down) - // here we say if the reading is greater than 150,000 than its '1'; '0' otherwise - if(flap > 150000) +int read_flap(float flap) { + if(flap > FLAP_MID) return 1; return 0; } +/** + * Return true if the transmitter is on. This is mostly a failsafe to be sure we don't + * drop out of the air if the receiver cuts out momentarily. If the receiver + * cuts out, we expect the rc values will flatline at 0. So if we get a float zero, + * then assume the transmitter is disconnected. + */ +int is_transmitter_on(float gear) { + if (gear < 0.00001) return 0; + else return 1; +} + /** * Turns off the motors */ -void kill_motors(struct PWMOutputDriver *pwm_outputs) { - pwm_outputs->write(pwm_outputs, 0, MOTOR_MIN); - pwm_outputs->write(pwm_outputs, 1, MOTOR_MIN); - pwm_outputs->write(pwm_outputs, 2, MOTOR_MIN); - pwm_outputs->write(pwm_outputs, 3, MOTOR_MIN); +void kill_motors(struct MotorDriver *motors) { + motors->write(motors, 0, MOTOR_MIN); + motors->write(motors, 1, MOTOR_MIN); + motors->write(motors, 2, MOTOR_MIN); + motors->write(motors, 3, MOTOR_MIN); } int build_int(u8 *buff) { diff --git a/quad/src/quad_app/util.h b/quad/src/quad_app/util.h index 643498afc53753720c8f4295fc88918ad5eae4db..390bafd9d5121af93ebef8e0a16c1340bea1fead 100644 --- a/quad/src/quad_app/util.h +++ b/quad/src/quad_app/util.h @@ -11,10 +11,10 @@ #include "controllers.h" #include "hw_iface.h" -void read_rec_all(struct PWMInputDriver *pwm_input, u32 *mixer); -int read_kill(int gear); -int read_flap(int flap); -void kill_motors(struct PWMOutputDriver *pwm_outputs); +void read_rec_all(struct RCReceiverDriver *rc_receiver, float *mixer); +int read_kill(float gear); +int read_flap(float flap); +void kill_motors(struct MotorDriver *motors); int build_int(u8 *buff); float build_float(u8 *buff); diff --git a/quad/src/virt_quad/hw_impl_unix.c b/quad/src/virt_quad/hw_impl_unix.c index fea231c35e963f5321b35665e4c3c2feac961383..bbd8e8775df179f41c36e3f96152f634bf1e0d97 100644 --- a/quad/src/virt_quad/hw_impl_unix.c +++ b/quad/src/virt_quad/hw_impl_unix.c @@ -9,20 +9,20 @@ struct UARTDriver create_unix_uart() { return uart; } -struct PWMOutputDriver create_unix_pwm_outputs() { - struct PWMOutputDriver pwm_outputs; - pwm_outputs.state = NULL; - pwm_outputs.reset = unix_pwm_output_reset; - pwm_outputs.write = unix_pwm_output_write; - return pwm_outputs; +struct MotorDriver create_unix_motors() { + struct MotorDriver motors; + motors.state = NULL; + motors.reset = unix_motor_reset; + motors.write = unix_motor_write; + return motors; } -struct PWMInputDriver create_unix_pwm_inputs() { - struct PWMInputDriver pwm_inputs; - pwm_inputs.state = NULL; - pwm_inputs.reset = unix_pwm_input_reset; - pwm_inputs.read = unix_pwm_input_read; - return pwm_inputs; +struct RCReceiverDriver create_unix_rc_receiver() { + struct RCReceiverDriver rc_receivers; + rc_receivers.state = NULL; + rc_receivers.reset = unix_rc_receiver_reset; + rc_receivers.read = unix_rc_receiver_read; + return rc_receivers; } struct I2CDriver create_unix_i2c() { diff --git a/quad/src/virt_quad/hw_impl_unix.h b/quad/src/virt_quad/hw_impl_unix.h index 38745899342bb3a8c81734bead570d1d876f4cff..85e223f2896a317fd5f1c1fa79f6fc60cb7a8772 100644 --- a/quad/src/virt_quad/hw_impl_unix.h +++ b/quad/src/virt_quad/hw_impl_unix.h @@ -16,11 +16,11 @@ int unix_uart_reset(struct UARTDriver *self); int unix_uart_write(struct UARTDriver *self, unsigned char c); int unix_uart_read(struct UARTDriver *self, unsigned char *c); -int unix_pwm_output_reset(struct PWMOutputDriver *self); -int unix_pwm_output_write(struct PWMOutputDriver *self, unsigned int channel, unsigned long pulse_width_us); +int unix_motor_reset(struct MotorDriver *self); +int unix_motor_write(struct MotorDriver *self, unsigned int channel, float magnitude); -int unix_pwm_input_reset(struct PWMInputDriver *self); -int unix_pwm_input_read(struct PWMInputDriver *self, unsigned int channel, unsigned long *pulse_width_us); +int unix_rc_receiver_reset(struct RCReceiverDriver *self); +int unix_rc_receiver_read(struct RCReceiverDriver *self, unsigned int channel, float *magnitude); int unix_i2c_reset(struct I2CDriver *self); int unix_i2c_write(struct I2CDriver *self, @@ -48,8 +48,8 @@ int unix_system_reset(struct SystemDriver *self); int unix_system_sleep(struct SystemDriver *self, unsigned long us); struct UARTDriver create_unix_uart(); -struct PWMOutputDriver create_unix_pwm_outputs(); -struct PWMInputDriver create_unix_pwm_inputs(); +struct MotorDriver create_unix_motors(); +struct RCReceiverDriver create_unix_rc_receiver(); struct I2CDriver create_unix_i2c(); struct TimerDriver create_unix_global_timer(); struct TimerDriver create_unix_axi_timer(); @@ -58,6 +58,6 @@ struct SystemDriver create_unix_system(); int test_unix_i2c(); int test_unix_mio7_led_and_system(); -int test_unix_pwm_inputs(); +int test_unix_rc_receivers(); #endif diff --git a/quad/src/virt_quad/hw_impl_unix_pwm_output.c b/quad/src/virt_quad/hw_impl_unix_motor.c similarity index 62% rename from quad/src/virt_quad/hw_impl_unix_pwm_output.c rename to quad/src/virt_quad/hw_impl_unix_motor.c index e58d5cf5ae496a5fb6d6d4d76332d78097f98a9f..3ad271b526aff0b45047988280157e1aa5e12b25 100644 --- a/quad/src/virt_quad/hw_impl_unix_pwm_output.c +++ b/quad/src/virt_quad/hw_impl_unix_motor.c @@ -9,19 +9,20 @@ void * output_cache(); static char *output_pwms[4]; -static unsigned long cache[4]; +static float cache[4]; pthread_t worker; +static void float_equals(float a, float b); static int zero = 0; static int one = 1; static int two = 2; static int three = 3; -int unix_pwm_output_reset(struct PWMOutputDriver *self) { - output_pwms[0] = VIRT_QUAD_FIFOS_DIR "/pwm-output-motor1"; - output_pwms[1] = VIRT_QUAD_FIFOS_DIR "/pwm-output-motor2"; - output_pwms[2] = VIRT_QUAD_FIFOS_DIR "/pwm-output-motor3"; - output_pwms[3] = VIRT_QUAD_FIFOS_DIR "/pwm-output-motor4"; +int unix_motor_reset(struct MotorDriver *self) { + output_pwms[0] = VIRT_QUAD_FIFOS_DIR "/motor1"; + output_pwms[1] = VIRT_QUAD_FIFOS_DIR "/motor2"; + output_pwms[2] = VIRT_QUAD_FIFOS_DIR "/motor3"; + output_pwms[3] = VIRT_QUAD_FIFOS_DIR "/motor4"; mkdir(VIRT_QUAD_FIFOS_DIR, 0777); @@ -34,13 +35,13 @@ int unix_pwm_output_reset(struct PWMOutputDriver *self) { return 0; } -int unix_pwm_output_write(struct PWMOutputDriver *self, +int unix_motor_write(struct MotorDriver *self, unsigned int channel, - unsigned long pulse_width_us) { - if (cache[channel] != pulse_width_us) { - printf("%s: %ld\n", output_pwms[channel], pulse_width_us); + float magnitude) { + if (cache[channel] != magnitude) { + printf("%s: %.2f\n", output_pwms[channel], magnitude); } - cache[channel] = pulse_width_us; + cache[channel] = magnitude; return 0; } @@ -56,10 +57,14 @@ void * output_cache(void *arg) { // Block while waiting for someone to listen while (1) { int fifo = open(output_pwms[i], O_WRONLY); - sprintf(buff, "%ld\n", cache[i]); + sprintf(buff, "%.2f\n", cache[i]); write(fifo, buff, strlen(buff)); close(fifo); pthread_yield(); } return NULL; } + +static void float_equals(float a, float b) { + return fabs(a - b) < 0.00001; +} diff --git a/quad/src/virt_quad/hw_impl_unix_pwm_input.c b/quad/src/virt_quad/hw_impl_unix_rc_receiver.c similarity index 65% rename from quad/src/virt_quad/hw_impl_unix_pwm_input.c rename to quad/src/virt_quad/hw_impl_unix_rc_receiver.c index df1aaf5f9b43811a4af9b5ed73aebe5e0ca24a86..229a019cd041d0aaed0636c3805121868eb68835 100644 --- a/quad/src/virt_quad/hw_impl_unix_pwm_input.c +++ b/quad/src/virt_quad/hw_impl_unix_rc_receiver.c @@ -9,17 +9,17 @@ void * update_input_cache(); static char *input_names[6]; static int fifos[6]; -static unsigned long cache[6]; +static float cache[6]; static pthread_t workers[6]; static int nums[] = {0, 1, 2, 3, 4, 5}; -int unix_pwm_input_reset(struct PWMInputDriver *self) { - input_names[0] = "pwm-input-throttle"; - input_names[1] = "pwm-input-roll"; - input_names[2] = "pwm-input-pitch"; - input_names[3] = "pwm-input-yaw"; - input_names[4] = "pwm-input-gear"; - input_names[5] = "pwm-input-flap"; +int unix_rc_receiver_reset(struct RCReceiverDriver *self) { + input_names[0] = "rc-throttle"; + input_names[1] = "rc-roll"; + input_names[2] = "rc-pitch"; + input_names[3] = "rc-yaw"; + input_names[4] = "rc-gear"; + input_names[5] = "rc-flap"; mkdir(VIRT_QUAD_FIFOS_DIR, 0777); @@ -38,17 +38,17 @@ int unix_pwm_input_reset(struct PWMInputDriver *self) { cache[5] = FLAP_1; for (i = 0; i < 6; i += 1) { - printf("%s: %lu\n", input_names[i], cache[i]); + printf("%s: %.2f\n", input_names[i], cache[i]); } return 0; } -int unix_pwm_input_read(struct PWMInputDriver *self, +int unix_rc_receiver_read(struct RCReceiverDriver *self, unsigned int channel, - unsigned long *pulse_width_us) { + float *magnitude) { - *pulse_width_us = cache[channel]; + *magnitude = cache[channel]; return 0; } @@ -69,13 +69,13 @@ void * update_input_cache(void *arg) { int bytes_read = read(fifos[i], buff, 15); if (bytes_read > 0) { buff[bytes_read] = '\0'; - unsigned long val = strtoll(buff, NULL, 10); - if (val < max && val > min) { + float val = strtof(buff, NULL); + if (val <= 1 && val >= 0) { cache[i] = val; - printf("%s: %lu\n", input_names[i], val); + printf("%s: %.2f\n", input_names[i], val); } else { - printf("%s: Bad value - input not received\n", input_names[i]); + printf("%s: Bad value (%f) - input not received\n", input_names[i], val); } } pthread_yield(); diff --git a/quad/src/virt_quad/main.c b/quad/src/virt_quad/main.c index f703f6ab77943a760ce7db7a1604ec672edb4e7b..5f6aaf8dbc9fda7e1adfc1c21fe0ecafa8065e5b 100644 --- a/quad/src/virt_quad/main.c +++ b/quad/src/virt_quad/main.c @@ -6,8 +6,8 @@ int setup_hardware(hardware_t *hardware) { hardware->i2c = create_unix_i2c(); - hardware->pwm_inputs = create_unix_pwm_inputs(); - hardware->pwm_outputs = create_unix_pwm_outputs(); + hardware->rc_receiver = create_unix_rc_receiver(); + hardware->motors = create_unix_motors(); hardware->uart = create_unix_uart(); hardware->global_timer = create_unix_global_timer(); hardware->axi_timer = create_unix_axi_timer(); diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.c b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.c index e8fceffa661ca92e0e1581d291a6f2b07d635819..3a6348f9b9a8f8090b2769f17201aeda88f36b93 100644 --- a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.c +++ b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.c @@ -9,20 +9,20 @@ struct UARTDriver create_zybo_uart() { return uart; } -struct PWMOutputDriver create_zybo_pwm_outputs() { - struct PWMOutputDriver pwm_outputs; - pwm_outputs.state = NULL; - pwm_outputs.reset = zybo_pwm_output_reset; - pwm_outputs.write = zybo_pwm_output_write; - return pwm_outputs; +struct MotorDriver create_zybo_motors() { + struct MotorDriver motors; + motors.state = NULL; + motors.reset = zybo_motor_reset; + motors.write = zybo_motor_write; + return motors; } -struct PWMInputDriver create_zybo_pwm_inputs() { - struct PWMInputDriver pwm_inputs; - pwm_inputs.state = NULL; - pwm_inputs.reset = zybo_pwm_input_reset; - pwm_inputs.read = zybo_pwm_input_read; - return pwm_inputs; +struct RCReceiverDriver create_zybo_rc_receiver() { + struct RCReceiverDriver rc_receiver; + rc_receiver.state = NULL; + rc_receiver.reset = zybo_rc_receiver_reset; + rc_receiver.read = zybo_rc_receiver_read; + return rc_receiver; } struct I2CDriver create_zybo_i2c() { diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.h b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.h index c721307bc08674e414683630564a2f7adf0dd2da..29d0ff8f388e0780f59aeefa63515ca0e8031522 100644 --- a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.h +++ b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo.h @@ -22,11 +22,11 @@ int zybo_uart_reset(struct UARTDriver *self); int zybo_uart_write(struct UARTDriver *self, unsigned char c); int zybo_uart_read(struct UARTDriver *self, unsigned char *c); -int zybo_pwm_output_reset(struct PWMOutputDriver *self); -int zybo_pwm_output_write(struct PWMOutputDriver *self, unsigned int channel, unsigned long pulse_width_us); +int zybo_motor_reset(struct MotorDriver *self); +int zybo_motor_write(struct MotorDriver *self, unsigned int channel, float magnitude); -int zybo_pwm_input_reset(struct PWMInputDriver *self); -int zybo_pwm_input_read(struct PWMInputDriver *self, unsigned int channel, unsigned long *pulse_width_us); +int zybo_rc_receiver_reset(struct RCReceiverDriver *self); +int zybo_rc_receiver_read(struct RCReceiverDriver *self, unsigned int channel, float *magnitude); int zybo_i2c_reset(struct I2CDriver *self); int zybo_i2c_write(struct I2CDriver *self, @@ -54,8 +54,8 @@ int zybo_system_reset(struct SystemDriver *self); int zybo_system_sleep(struct SystemDriver *self, unsigned long us); struct UARTDriver create_zybo_uart(); -struct PWMOutputDriver create_zybo_pwm_outputs(); -struct PWMInputDriver create_zybo_pwm_inputs(); +struct MotorDriver create_zybo_motors(); +struct RCReceiverDriver create_zybo_rc_receiver(); struct I2CDriver create_zybo_i2c(); struct TimerDriver create_zybo_global_timer(); struct TimerDriver create_zybo_axi_timer(); @@ -64,6 +64,6 @@ struct SystemDriver create_zybo_system(); int test_zybo_i2c(); int test_zybo_mio7_led_and_system(); -int test_zybo_pwm_inputs(); +int test_zybo_rc_receivers(); #endif diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_motor.c b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_motor.c new file mode 100644 index 0000000000000000000000000000000000000000..576c1ecaf353bf3caf7f0f63999ac500b8353a84 --- /dev/null +++ b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_motor.c @@ -0,0 +1,55 @@ +#include "hw_impl_zybo.h" + +#define SYS_CLOCK_RATE 100000000 // ticks per second +#define FREQUENCY 450 +#define PERIOD_WIDTH SYS_CLOCK_RATE/FREQUENCY +#define PULSE_WIDTH_LOW SYS_CLOCK_RATE/1000 // 1 ms +#define PULSE_WIDTH_HIGH SYS_CLOCK_RATE/500 // 2 ms +#define PULSE_WIDTH_ADDR_OFFSET 1 + +struct MotorDriverState { + int *outputs[4]; +}; + +int zybo_motor_reset(struct MotorDriver *self) { + if (self->state == NULL) { + self->state = malloc(sizeof(struct MotorDriverState)); + if (self->state == NULL) { + return -1; + } + } + struct MotorDriverState *state = self->state; + + state->outputs[0] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_0_BASEADDR; + state->outputs[1] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_1_BASEADDR; + state->outputs[2] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_2_BASEADDR; + state->outputs[3] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_3_BASEADDR; + + // Set period width of PWM pulse + *(state->outputs[0]) = PERIOD_WIDTH; + *(state->outputs[1]) = PERIOD_WIDTH; + *(state->outputs[2]) = PERIOD_WIDTH; + *(state->outputs[3]) = PERIOD_WIDTH; + + // Set a low pulse (1 ms) so that outputs are off + *(state->outputs[0] + PULSE_WIDTH_ADDR_OFFSET) = PULSE_WIDTH_LOW; + *(state->outputs[1] + PULSE_WIDTH_ADDR_OFFSET) = PULSE_WIDTH_LOW; + *(state->outputs[2] + PULSE_WIDTH_ADDR_OFFSET) = PULSE_WIDTH_LOW; + *(state->outputs[3] + PULSE_WIDTH_ADDR_OFFSET) = PULSE_WIDTH_LOW; + + usleep(1000000); + return 0; +} + +int zybo_motor_write(struct MotorDriver *self, + unsigned int channel, + float magnitude) { + if (magnitude > 1) + magnitude = 1; + if (magnitude < 0) + magnitude = 0; + struct MotorDriverState *state = self->state; + unsigned long pulse_width_ticks = (unsigned long) (magnitude * (float) (PULSE_WIDTH_HIGH - PULSE_WIDTH_LOW)) + PULSE_WIDTH_LOW; + *(state->outputs[channel] + PULSE_WIDTH_ADDR_OFFSET) = pulse_width_ticks; + return 0; +} diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_pwm_input.c b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_pwm_input.c deleted file mode 100644 index b0c3cd98ef90a33fc0a416f2f02a1ed6b92f57cf..0000000000000000000000000000000000000000 --- a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_pwm_input.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "hw_impl_zybo.h" - -struct PWMInputDriverState { - int *channels[6]; -}; - -int zybo_pwm_input_reset(struct PWMInputDriver *self) { - if (self->state == NULL) { - self->state = malloc(sizeof(struct PWMInputDriverState)); - if (self->state == NULL) { - return -1; - } - } - - // Save the addresses of the input PWM recorders - struct PWMInputDriverState *state = self->state; - state->channels[0] = (int *) XPAR_PWM_RECORDER_0_BASEADDR; - state->channels[1] = (int *) XPAR_PWM_RECORDER_1_BASEADDR; - state->channels[2] = (int *) XPAR_PWM_RECORDER_2_BASEADDR; - state->channels[3] = (int *) XPAR_PWM_RECORDER_3_BASEADDR; - state->channels[4] = (int *) XPAR_PWM_RECORDER_4_BASEADDR; - state->channels[5] = (int *) XPAR_PWM_RECORDER_5_BASEADDR; - return 0; -} - -int zybo_pwm_input_read(struct PWMInputDriver *self, - unsigned int channel, - unsigned long *pulse_width_us) { - struct PWMInputDriverState *state = self->state; - *pulse_width_us = (long) *((int *) state->channels[channel]); - return 0; -} diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_pwm_output.c b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_pwm_output.c deleted file mode 100644 index 3dd09e54379432529a3ce05614dedf648dffb3e2..0000000000000000000000000000000000000000 --- a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_pwm_output.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "hw_impl_zybo.h" - -#define SYS_CLOCK_RATE 100000000 // ticks per second -#define FREQUENCY 450 -#define PERIOD_WIDTH SYS_CLOCK_RATE/FREQUENCY -#define THROTTLE_PULSE_WIDTH_LOW SYS_CLOCK_RATE/1000 // 1 ms -#define THROTTLE_PULSE_WIDTH_HIGH SYS_CLOCK_RATE/500 // 2 ms -#define PULSE_WIDTH_ADDR_OFFSET 1 - -struct PWMOutputDriverState { - int *outputs[4]; -}; - -int zybo_pwm_output_reset(struct PWMOutputDriver *self) { - if (self->state == NULL) { - self->state = malloc(sizeof(struct PWMOutputDriverState)); - if (self->state == NULL) { - return -1; - } - } - struct PWMOutputDriverState *state = self->state; - - state->outputs[0] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_0_BASEADDR; - state->outputs[1] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_1_BASEADDR; - state->outputs[2] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_2_BASEADDR; - state->outputs[3] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_3_BASEADDR; - - // Set period width of PWM pulse - *(state->outputs[0]) = PERIOD_WIDTH; - *(state->outputs[1]) = PERIOD_WIDTH; - *(state->outputs[2]) = PERIOD_WIDTH; - *(state->outputs[3]) = PERIOD_WIDTH; - - // Set a low pulse (1 ms) so that outputs are off - *(state->outputs[0] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW; - *(state->outputs[1] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW; - *(state->outputs[2] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW; - *(state->outputs[3] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW; - - usleep(1000000); - return 0; -} - -int zybo_pwm_output_write(struct PWMOutputDriver *self, - unsigned int channel, - unsigned long pulse_width_us) { - if (pulse_width_us > THROTTLE_PULSE_WIDTH_HIGH) - pulse_width_us = THROTTLE_PULSE_WIDTH_HIGH; - if (pulse_width_us < THROTTLE_PULSE_WIDTH_LOW) - pulse_width_us = THROTTLE_PULSE_WIDTH_LOW; - struct PWMOutputDriverState *state = self->state; - *(state->outputs[channel] + PULSE_WIDTH_ADDR_OFFSET) = pulse_width_us; - return 0; -} diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_rc_receiver.c b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_rc_receiver.c new file mode 100644 index 0000000000000000000000000000000000000000..63d6ab525b330789670b251008bbcbc7d863b0ad --- /dev/null +++ b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_rc_receiver.c @@ -0,0 +1,40 @@ +#include "hw_impl_zybo.h" + +#define SYS_CLOCK_RATE 100000000 // ticks per second +#define FREQUENCY 450 +#define PERIOD_WIDTH SYS_CLOCK_RATE/FREQUENCY +#define PULSE_WIDTH_LOW SYS_CLOCK_RATE/1000 // 1 ms +#define PULSE_WIDTH_HIGH SYS_CLOCK_RATE/500 // 2 ms +#define PULSE_WIDTH_ADDR_OFFSET 1 + +struct RCReceiverDriverState { + int *channels[6]; +}; + +int zybo_rc_receiver_reset(struct RCReceiverDriver *self) { + if (self->state == NULL) { + self->state = malloc(sizeof(struct RCReceiverDriverState)); + if (self->state == NULL) { + return -1; + } + } + + // Save the addresses of the input PWM recorders + struct RCReceiverDriverState *state = self->state; + state->channels[0] = (int *) XPAR_PWM_RECORDER_0_BASEADDR; + state->channels[1] = (int *) XPAR_PWM_RECORDER_1_BASEADDR; + state->channels[2] = (int *) XPAR_PWM_RECORDER_2_BASEADDR; + state->channels[3] = (int *) XPAR_PWM_RECORDER_3_BASEADDR; + state->channels[4] = (int *) XPAR_PWM_RECORDER_4_BASEADDR; + state->channels[5] = (int *) XPAR_PWM_RECORDER_5_BASEADDR; + return 0; +} + +int zybo_rc_receiver_read(struct RCReceiverDriver *self, + unsigned int channel, + float *magnitude) { + struct RCReceiverDriverState *state = self->state; + unsigned long pulse_width_ticks = (long) *((int *) state->channels[channel]); + *magnitude = (float) (pulse_width_ticks - PULSE_WIDTH_LOW) / (float) (PULSE_WIDTH_HIGH - PULSE_WIDTH_LOW); + return 0; +} diff --git a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_tests.c b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_tests.c index 2a4a32c8063c34b5c4bf2f56651e7ee9de57b7d7..5971d023b9f4026040217b8368e6ee5d7967ce4a 100644 --- a/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_tests.c +++ b/quad/xsdk_workspace/real_quad/src/hw_impl_zybo_tests.c @@ -159,18 +159,18 @@ int test_zybo_i2c_all() { * 4) Set the RUN_TESTS macro in main.c * 5) Uncomment only this test in main.c * 6) Debug main. - * 7) Observe the values of pwm_inputs in debugger chaning as you use the + * 7) Observe the values of pwm_inputs in debugger changing as you use the * Spektrum RC controller. */ -int test_zybo_pwm_inputs() { - struct PWMInputDriver pwm_inputs = create_zybo_pwm_inputs(); - pwm_inputs.reset(&pwm_inputs); +int test_zybo_rc_receiver() { + struct RCReceiverDriver rc_receiver = create_zybo_rc_receiver(); + rc_receiver.reset(&rc_receiver); - unsigned long pwms[6]; + float pwms[6]; while (1) { int i; for (i = 0; i < 6; i += 1) { - pwm_inputs.read(&pwm_inputs, i, &pwms[i]); + rc_receiver.read(&rc_receiver, i, &pwms[i]); } continue; } @@ -188,22 +188,21 @@ int test_zybo_pwm_inputs() { * 6) Run main. * 7) Observe the PWM width of those PMOD pins changing with time */ -int test_zybo_pwm_outputs() { - struct PWMOutputDriver pwm_outputs = create_zybo_pwm_outputs(); - pwm_outputs.reset(&pwm_outputs); +int test_zybo_motors() { + struct MotorDriver motors = create_zybo_motors(); + motors.reset(&motors); struct SystemDriver sys = create_zybo_system(); sys.reset(&sys); + double j = 0; while (1) { - int j; - for (j = 100000; j < 200000; j += 1) { - int i; + for (j = 0; j < 1.0; j += 0.01) { + int i = 0; for (i = 0; i < 4; i += 1) { - pwm_outputs.write(&pwm_outputs, i, j); - sys.sleep(&sys, 50); + motors.write(&motors, i, j); + sys.sleep(&sys, 50000); } } - continue; } return 0; } diff --git a/quad/xsdk_workspace/real_quad/src/main.c b/quad/xsdk_workspace/real_quad/src/main.c index ef3971feb9c63c531073afa30651d7cb9f3e9959..5892393e53137ad97d0c735c77d768c8f3a70d23 100644 --- a/quad/xsdk_workspace/real_quad/src/main.c +++ b/quad/xsdk_workspace/real_quad/src/main.c @@ -8,8 +8,8 @@ int setup_hardware(hardware_t *hardware) { hardware->i2c = create_zybo_i2c(); - hardware->pwm_inputs = create_zybo_pwm_inputs(); - hardware->pwm_outputs = create_zybo_pwm_outputs(); + hardware->rc_receiver = create_zybo_rc_receiver(); + hardware->motors = create_zybo_motors(); hardware->uart = create_zybo_uart(); hardware->global_timer = create_zybo_global_timer(); hardware->axi_timer = create_zybo_axi_timer(); @@ -29,8 +29,8 @@ int main() //test_zybo_i2c_imu(); //test_zybo_i2c_px4flow(); //test_zybo_i2c_all(); - //test_zybo_pwm_inputs(); - //test_zybo_pwm_outputs(); + //test_zybo_rc_receiver(); + test_zybo_motors(); //test_zybo_uart(); //test_zybo_axi_timer(); //test_zybo_uart();