diff --git a/src/modules/mc_att_control/mc_att_control_main.cpp b/src/modules/mc_att_control/mc_att_control_main.cpp
index 8e6365270fe89558531ff855cc50d3d44eb64973..89b69d8ce2f1991edf0f7d9fc655c3ee96356957 100644
--- a/src/modules/mc_att_control/mc_att_control_main.cpp
+++ b/src/modules/mc_att_control/mc_att_control_main.cpp
@@ -99,7 +99,6 @@ extern "C" __EXPORT int mc_att_control_main(int argc, char *argv[]);
 
 #define YAW_DEADZONE	0.05f
 #define MIN_TAKEOFF_THRUST    0.2f
-#define RATES_I_LIMIT	0.3f
 #define TPA_RATE_LOWER_LIMIT 0.05f
 #define MANUAL_THROTTLE_MAX_MULTICOPTER	0.9f
 #define ATTITUDE_TC_DEFAULT 0.2f
@@ -166,6 +165,22 @@ private:
 	struct mc_att_ctrl_status_s 		_controller_status; /**< controller status */
 	struct battery_status_s				_battery_status;	/**< battery status */
 
+	union {
+	    struct {
+		uint16_t motor_pos	: 1; // 0 - true when any motor has saturated in the positive direction
+		uint16_t motor_neg	: 1; // 1 - true when any motor has saturated in the negative direction
+		uint16_t roll_pos	: 1; // 2 - true when a positive roll demand change will increase saturation
+		uint16_t roll_neg	: 1; // 3 - true when a negative roll demand change will increase saturation
+		uint16_t pitch_pos	: 1; // 4 - true when a positive pitch demand change will increase saturation
+		uint16_t pitch_neg	: 1; // 5 - true when a negative pitch demand change will increase saturation
+		uint16_t yaw_pos	: 1; // 6 - true when a positive yaw demand change will increase saturation
+		uint16_t yaw_neg	: 1; // 7 - true when a negative yaw demand change will increase saturation
+		uint16_t thrust_pos	: 1; // 8 - true when a positive thrust demand change will increase saturation
+		uint16_t thrust_neg	: 1; // 9 - true when a negative thrust demand change will increase saturation
+	    } flags;
+	    uint16_t value;
+	} _saturation_status;
+
 	perf_counter_t	_loop_perf;			/**< loop performance counter */
 	perf_counter_t	_controller_latency_perf;
 
@@ -182,11 +197,13 @@ private:
 		param_t roll_p;
 		param_t roll_rate_p;
 		param_t roll_rate_i;
+		param_t roll_rate_integ_lim;
 		param_t roll_rate_d;
 		param_t roll_rate_ff;
 		param_t pitch_p;
 		param_t pitch_rate_p;
 		param_t pitch_rate_i;
+		param_t pitch_rate_integ_lim;
 		param_t pitch_rate_d;
 		param_t pitch_rate_ff;
 		param_t tpa_breakpoint_p;
@@ -198,6 +215,7 @@ private:
 		param_t yaw_p;
 		param_t yaw_rate_p;
 		param_t yaw_rate_i;
+		param_t yaw_rate_integ_lim;
 		param_t yaw_rate_d;
 		param_t yaw_rate_ff;
 		param_t yaw_ff;
@@ -225,6 +243,7 @@ private:
 		math::Vector<3> att_p;					/**< P gain for angular error */
 		math::Vector<3> rate_p;				/**< P gain for angular rate error */
 		math::Vector<3> rate_i;				/**< I gain for angular rate error */
+		math::Vector<3> rate_int_lim;			/**< integrator state limit for rate loop */
 		math::Vector<3> rate_d;				/**< D gain for angular rate error */
 		math::Vector<3>	rate_ff;			/**< Feedforward gain for desired rates */
 		float yaw_ff;						/**< yaw control feed-forward */
@@ -379,6 +398,7 @@ MulticopterAttitudeControl::MulticopterAttitudeControl() :
 	_params.att_p.zero();
 	_params.rate_p.zero();
 	_params.rate_i.zero();
+	_params.rate_int_lim.zero();
 	_params.rate_d.zero();
 	_params.rate_ff.zero();
 	_params.yaw_ff = 0.0f;
@@ -405,11 +425,13 @@ MulticopterAttitudeControl::MulticopterAttitudeControl() :
 	_params_handles.roll_p			= 	param_find("MC_ROLL_P");
 	_params_handles.roll_rate_p		= 	param_find("MC_ROLLRATE_P");
 	_params_handles.roll_rate_i		= 	param_find("MC_ROLLRATE_I");
+	_params_handles.roll_rate_integ_lim	= 	param_find("MC_RR_INT_LIM");
 	_params_handles.roll_rate_d		= 	param_find("MC_ROLLRATE_D");
 	_params_handles.roll_rate_ff	= 	param_find("MC_ROLLRATE_FF");
 	_params_handles.pitch_p			= 	param_find("MC_PITCH_P");
 	_params_handles.pitch_rate_p	= 	param_find("MC_PITCHRATE_P");
 	_params_handles.pitch_rate_i	= 	param_find("MC_PITCHRATE_I");
+	_params_handles.pitch_rate_integ_lim	= 	param_find("MC_PR_INT_LIM");
 	_params_handles.pitch_rate_d	= 	param_find("MC_PITCHRATE_D");
 	_params_handles.pitch_rate_ff 	= 	param_find("MC_PITCHRATE_FF");
 	_params_handles.tpa_breakpoint_p 	= 	param_find("MC_TPA_BREAK_P");
@@ -421,6 +443,7 @@ MulticopterAttitudeControl::MulticopterAttitudeControl() :
 	_params_handles.yaw_p			=	param_find("MC_YAW_P");
 	_params_handles.yaw_rate_p		= 	param_find("MC_YAWRATE_P");
 	_params_handles.yaw_rate_i		= 	param_find("MC_YAWRATE_I");
+	_params_handles.yaw_rate_integ_lim	= 	param_find("MC_YR_INT_LIM");
 	_params_handles.yaw_rate_d		= 	param_find("MC_YAWRATE_D");
 	_params_handles.yaw_rate_ff	 	= 	param_find("MC_YAWRATE_FF");
 	_params_handles.yaw_ff			= 	param_find("MC_YAW_FF");
@@ -497,6 +520,8 @@ MulticopterAttitudeControl::parameters_update()
 	_params.rate_p(0) = v * (ATTITUDE_TC_DEFAULT / roll_tc);
 	param_get(_params_handles.roll_rate_i, &v);
 	_params.rate_i(0) = v;
+	param_get(_params_handles.roll_rate_integ_lim, &v);
+	_params.rate_int_lim(0) = v;
 	param_get(_params_handles.roll_rate_d, &v);
 	_params.rate_d(0) = v * (ATTITUDE_TC_DEFAULT / roll_tc);
 	param_get(_params_handles.roll_rate_ff, &v);
@@ -509,6 +534,8 @@ MulticopterAttitudeControl::parameters_update()
 	_params.rate_p(1) = v * (ATTITUDE_TC_DEFAULT / pitch_tc);
 	param_get(_params_handles.pitch_rate_i, &v);
 	_params.rate_i(1) = v;
+	param_get(_params_handles.pitch_rate_integ_lim, &v);
+	_params.rate_int_lim(1) = v;
 	param_get(_params_handles.pitch_rate_d, &v);
 	_params.rate_d(1) = v * (ATTITUDE_TC_DEFAULT / pitch_tc);
 	param_get(_params_handles.pitch_rate_ff, &v);
@@ -528,6 +555,8 @@ MulticopterAttitudeControl::parameters_update()
 	_params.rate_p(2) = v;
 	param_get(_params_handles.yaw_rate_i, &v);
 	_params.rate_i(2) = v;
+	param_get(_params_handles.yaw_rate_integ_lim, &v);
+	_params.rate_int_lim(2) = v;
 	param_get(_params_handles.yaw_rate_d, &v);
 	_params.rate_d(2) = v;
 	param_get(_params_handles.yaw_rate_ff, &v);
@@ -687,6 +716,7 @@ MulticopterAttitudeControl::vehicle_motor_limits_poll()
 
 	if (updated) {
 		orb_copy(ORB_ID(multirotor_motor_limits), _motor_limits_sub, &_motor_limits);
+		_saturation_status.value = _motor_limits.saturation_status;
 	}
 }
 
@@ -865,21 +895,48 @@ MulticopterAttitudeControl::control_attitude_rates(float dt)
 	_rates_sp_prev = _rates_sp;
 	_rates_prev = rates;
 
-	/* update integral only if not saturated on low limit and if motor commands are not saturated */
-	if (_thrust_sp > MIN_TAKEOFF_THRUST && !_motor_limits.lower_limit && !_motor_limits.upper_limit) {
+	/* update integral only if motors are providing enough thrust to be effective */
+	if (_thrust_sp > MIN_TAKEOFF_THRUST) {
 		for (int i = AXIS_INDEX_ROLL; i < AXIS_COUNT; i++) {
-			if (fabsf(_att_control(i)) < _thrust_sp) {
-				float rate_i = _rates_int(i) + rates_i_scaled(i) * rates_err(i) * dt;
-
-				if (PX4_ISFINITE(rate_i) && rate_i > -RATES_I_LIMIT && rate_i < RATES_I_LIMIT &&
-				    _att_control(i) > -RATES_I_LIMIT && _att_control(i) < RATES_I_LIMIT &&
-				    /* if the axis is the yaw axis, do not update the integral if the limit is hit */
-				    !((i == AXIS_INDEX_YAW) && _motor_limits.yaw)) {
-					_rates_int(i) = rate_i;
-				}
+			// Check for positive control saturation
+			bool positive_saturation =
+					((i == AXIS_INDEX_ROLL) && _saturation_status.flags.roll_pos) ||
+					((i == AXIS_INDEX_PITCH) && _saturation_status.flags.pitch_pos) ||
+					((i == AXIS_INDEX_YAW) && _saturation_status.flags.yaw_pos);
+
+			// Check for negative control saturation
+			bool negative_saturation =
+					((i == AXIS_INDEX_ROLL) && _saturation_status.flags.roll_neg) ||
+					((i == AXIS_INDEX_PITCH) && _saturation_status.flags.pitch_neg) ||
+					((i == AXIS_INDEX_YAW) && _saturation_status.flags.yaw_neg);
+
+			// prevent further positive control saturation
+			if (positive_saturation) {
+				rates_err(i) = math::min(rates_err(i), 0.0f);
+
+			}
+
+			// prevent further negative control saturation
+			if (negative_saturation) {
+				rates_err(i) = math::max(rates_err(i), 0.0f);
+
+			}
+
+			// Perform the integration using a first order method and do not propaate the result if out of range or invalid
+			float rate_i = _rates_int(i) + _params.rate_i(i) * rates_err(i) * dt;
+
+			if (PX4_ISFINITE(rate_i) && rate_i > -_params.rate_int_lim(i) && rate_i < _params.rate_int_lim(i)) {
+				_rates_int(i) = rate_i;
+
 			}
 		}
 	}
+
+	/* explicitly limit the integrator state */
+	for (int i = AXIS_INDEX_ROLL; i < AXIS_COUNT; i++) {
+		_rates_int(i) = math::constrain(_rates_int(i), -_params.rate_int_lim(i), _params.rate_int_lim(i));
+
+	}
 }
 
 void
diff --git a/src/modules/mc_att_control/mc_att_control_params.c b/src/modules/mc_att_control/mc_att_control_params.c
index 9f6722833ac4ae752a3f5a0feff56fd4c8a16316..e3ecaa9e319415f968ae130211d5cb997a7ff7cf 100644
--- a/src/modules/mc_att_control/mc_att_control_params.c
+++ b/src/modules/mc_att_control/mc_att_control_params.c
@@ -106,6 +106,18 @@ PARAM_DEFINE_FLOAT(MC_ROLLRATE_P, 0.15f);
  */
 PARAM_DEFINE_FLOAT(MC_ROLLRATE_I, 0.05f);
 
+/**
+ * Roll rate integrator limit
+ *
+ * Roll rate integrator limit. Can be set to increase the amount of integrator available to counteract disturbances or reduced to improve settling time after large roll moment trim changes.
+ *
+ * @min 0.0
+ * @decimal 2
+ * @increment 0.01
+ * @group Multicopter Attitude Control
+ */
+PARAM_DEFINE_FLOAT(MC_RR_INT_LIM, 0.30f);
+
 /**
  * Roll rate D gain
  *
@@ -169,6 +181,18 @@ PARAM_DEFINE_FLOAT(MC_PITCHRATE_P, 0.15f);
  */
 PARAM_DEFINE_FLOAT(MC_PITCHRATE_I, 0.05f);
 
+/**
+ * Pitch rate integrator limit
+ *
+ * Pitch rate integrator limit. Can be set to increase the amount of integrator available to counteract disturbances or reduced to improve settling time after large pitch moment trim changes.
+ *
+ * @min 0.0
+ * @decimal 2
+ * @increment 0.01
+ * @group Multicopter Attitude Control
+ */
+PARAM_DEFINE_FLOAT(MC_PR_INT_LIM, 0.30f);
+
 /**
  * Pitch rate D gain
  *
@@ -231,6 +255,18 @@ PARAM_DEFINE_FLOAT(MC_YAWRATE_P, 0.2f);
  */
 PARAM_DEFINE_FLOAT(MC_YAWRATE_I, 0.1f);
 
+/**
+ * Yaw rate integrator limit
+ *
+ * Yaw rate integrator limit. Can be set to increase the amount of integrator available to counteract disturbances or reduced to improve settling time after large yaw moment trim changes.
+ *
+ * @min 0.0
+ * @decimal 2
+ * @increment 0.01
+ * @group Multicopter Attitude Control
+ */
+PARAM_DEFINE_FLOAT(MC_YR_INT_LIM, 0.30f);
+
 /**
  * Yaw rate D gain
  *