コード例 #1
0
ファイル: actuators_asctec.c プロジェクト: alex31/paparazzi
/** @file actuators_asctec.c
 *  Actuators driver for Asctec motor controllers.
 */

#include "firmwares/rotorcraft/actuators.h"
#include "firmwares/rotorcraft/actuators/actuators_asctec.h"

#ifdef ACTUATORS_ASCTEC_V2_PROTOCOL
#include "firmwares/rotorcraft/actuators/supervision.h"
#endif

#include "firmwares/rotorcraft/commands.h"
#include "mcu_periph/i2c.h"
#include "mcu_periph/sys_time.h"


struct ActuatorsAsctec actuators_asctec;

uint32_t actuators_delay_time;
bool_t   actuators_delay_done;

void actuators_init(void) {
  actuators_asctec.cmd = NONE;
  actuators_asctec.cur_addr = FRONT;
  actuators_asctec.new_addr = FRONT;
  actuators_asctec.i2c_trans.status = I2CTransSuccess;
  actuators_asctec.i2c_trans.type = I2CTransTx;
  actuators_asctec.i2c_trans.slave_addr = 0x02;
#ifdef ACTUATORS_ASCTEC_V2_PROTOCOL
  actuators_asctec.i2c_trans.len_w = 5;
#else
  actuators_asctec.i2c_trans.len_w = 4;
#endif
  actuators_asctec.nb_err = 0;

#if defined ACTUATORS_START_DELAY && ! defined SITL
  actuators_delay_done = FALSE;
  SysTimeTimerStart(actuators_delay_time);
#else
  actuators_delay_done = TRUE;
  actuators_delay_time = 0;
#endif

#ifdef ACTUATORS_ASCTEC_V2_PROTOCOL
  supervision_init();
#endif

}

#ifndef ACTUATORS_ASCTEC_V2_PROTOCOL
void actuators_set(bool_t motors_on) {
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) return;
    else actuators_delay_done = TRUE;
  }
#endif

  if (!actuators_asctec.i2c_trans.status == I2CTransSuccess)
    actuators_asctec.nb_err++;

#ifdef KILL_MOTORS
  actuators_asctec.cmds[PITCH]  = 0;
  actuators_asctec.cmds[ROLL]   = 0;
  actuators_asctec.cmds[YAW]    = 0;
  actuators_asctec.cmds[THRUST] = 0;
#else /* ! KILL_MOTORS */
  actuators_asctec.cmds[PITCH]  = commands[COMMAND_PITCH]  + SUPERVISION_TRIM_E;
  actuators_asctec.cmds[ROLL]   = commands[COMMAND_ROLL]   + SUPERVISION_TRIM_A;
  actuators_asctec.cmds[YAW]    = commands[COMMAND_YAW]    + SUPERVISION_TRIM_R;
  actuators_asctec.cmds[THRUST] = commands[COMMAND_THRUST];
  Bound(actuators_asctec.cmds[PITCH],-100, 100);
  Bound(actuators_asctec.cmds[ROLL], -100, 100);
  Bound(actuators_asctec.cmds[YAW],  -100, 100);
  if (motors_on) {
    Bound(actuators_asctec.cmds[THRUST],  1, 200);
  }
  else
    actuators_asctec.cmds[THRUST] = 0;
#endif /* KILL_MOTORS  */

  switch (actuators_asctec.cmd) {
  case TEST:
    actuators_asctec.i2c_trans.buf[0] = 251;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = 0;
    actuators_asctec.i2c_trans.buf[3] = 231 + actuators_asctec.cur_addr;
    break;
  case REVERSE:
    actuators_asctec.i2c_trans.buf[0] = 254;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = 0;
    actuators_asctec.i2c_trans.buf[3] = 234 + actuators_asctec.cur_addr;
    break;
  case SET_ADDR:
    actuators_asctec.i2c_trans.buf[0] = 250;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = actuators_asctec.new_addr;
    actuators_asctec.i2c_trans.buf[3] = 230 + actuators_asctec.cur_addr + actuators_asctec.new_addr;
    actuators_asctec.cur_addr = actuators_asctec.new_addr;
    break;
  case NONE:
    actuators_asctec.i2c_trans.buf[0] = 100 -  actuators_asctec.cmds[PITCH];
    actuators_asctec.i2c_trans.buf[1] = 100 + actuators_asctec.cmds[ROLL];
    actuators_asctec.i2c_trans.buf[2] = 100 - actuators_asctec.cmds[YAW];
    actuators_asctec.i2c_trans.buf[3] = actuators_asctec.cmds[THRUST];
    break;
  default:
    break;
  }
  actuators_asctec.cmd = NONE;

  i2c_submit(&ACTUATORS_ASCTEC_DEVICE, &actuators_asctec.i2c_trans);

}
#else /* ! ACTUATORS_ASCTEC_V2_PROTOCOL */
void actuators_set(bool_t motors_on) {
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) return;
    else actuators_delay_done = TRUE;
  }
#endif

  supervision_run(motors_on, FALSE, commands);
#ifdef KILL_MOTORS
  actuators_asctec.i2c_trans.buf[0] = 0;
  actuators_asctec.i2c_trans.buf[1] = 0;
  actuators_asctec.i2c_trans.buf[2] = 0;
  actuators_asctec.i2c_trans.buf[3] = 0;
  actuators_asctec.i2c_trans.buf[4] = 0xAA;
#else
  actuators_asctec.i2c_trans.buf[0] = supervision.commands[SERVO_FRONT];
  actuators_asctec.i2c_trans.buf[1] = supervision.commands[SERVO_BACK];
  actuators_asctec.i2c_trans.buf[2] = supervision.commands[SERVO_LEFT];
  actuators_asctec.i2c_trans.buf[3] = supervision.commands[SERVO_RIGHT];
  actuators_asctec.i2c_trans.buf[4] = 0xAA + actuators_asctec.i2c_trans.buf[0] + actuators_asctec.i2c_trans.buf[1] +
                                             actuators_asctec.i2c_trans.buf[2] + actuators_asctec.i2c_trans.buf[3];
#endif

  i2c_submit(&ACTUATORS_ASCTEC_DEVICE, &actuators_asctec.i2c_trans);

}
コード例 #2
0
ファイル: actuators_mkk_v2.c プロジェクト: AULA-PPZ/paparazzi
void actuators_mkk_v2_set(void)
{
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) { return; }
    else { actuators_delay_done = TRUE; }
  }
#endif

  // Read result
  for (uint8_t i = 0; i < ACTUATORS_MKK_V2_NB; i++) {
    if (actuators_mkk_v2.trans[i].type != I2CTransTx) {
      actuators_mkk_v2.trans[i].type = I2CTransTx;

      actuators_mkk_v2.data[i].Current     = actuators_mkk_v2.trans[i].buf[0];
      actuators_mkk_v2.data[i].MaxPWM      = actuators_mkk_v2.trans[i].buf[1];
      actuators_mkk_v2.data[i].Temperature = actuators_mkk_v2.trans[i].buf[2];
    }
  }

  RunOnceEvery(10, actuators_mkk_v2_read());

  for (uint8_t i = 0; i < ACTUATORS_MKK_V2_NB; i++) {

#ifdef KILL_MOTORS
    actuators_mkk_v2.trans[i].buf[0] = 0;
    actuators_mkk_v2.trans[i].buf[1] = 0;
#else
    actuators_mkk_v2.trans[i].buf[0] = (actuators_mkk_v2.setpoint[i] >> 3);
    actuators_mkk_v2.trans[i].buf[1] = actuators_mkk_v2.setpoint[i] & 0x07;
#endif

    i2c_submit(&ACTUATORS_MKK_V2_DEVICE, &actuators_mkk_v2.trans[i]);
  }
}
コード例 #3
0
ファイル: baro_ets.c プロジェクト: 1bitsquared/paparazzi
void baro_ets_read_periodic( void ) {
  // Initiate next read
  if (!baro_ets_delay_done) {
    if (SysTimeTimer(baro_ets_delay_time) < USEC_OF_SEC(BARO_ETS_START_DELAY)) return;
    else baro_ets_delay_done = TRUE;
  }
  if (baro_ets_i2c_trans.status == I2CTransDone) {
    i2c_receive(&BARO_ETS_I2C_DEV, &baro_ets_i2c_trans, BARO_ETS_ADDR, 2);
  }
}
コード例 #4
0
ファイル: gps_sim_hitl.c プロジェクト: Merafour/paparazzi
void gps_sim_hitl_event(void)
{
  if (SysTimeTimer(gps_sim_hitl_timer) > 100000) {
    SysTimeTimerStart(gps_sim_hitl_timer);
    gps.last_msg_ticks = sys_time.nb_sec_rem;
    gps.last_msg_time = sys_time.nb_sec;
    if (state.ned_initialized_i) {
      if (!autopilot_in_flight) {
        struct Int32Vect2 zero_vector;
        INT_VECT2_ZERO(zero_vector);
        gh_set_ref(zero_vector, zero_vector, zero_vector);
        INT_VECT2_ZERO(guidance_h.ref.pos);
        INT_VECT2_ZERO(guidance_h.ref.speed);
        INT_VECT2_ZERO(guidance_h.ref.accel);
        gv_set_ref(0, 0, 0);
        guidance_v_z_ref = 0;
        guidance_v_zd_ref = 0;
        guidance_v_zdd_ref = 0;
      }
      struct NedCoor_i ned_c;
      ned_c.x = guidance_h.ref.pos.x * INT32_POS_OF_CM_DEN / INT32_POS_OF_CM_NUM;
      ned_c.y = guidance_h.ref.pos.y * INT32_POS_OF_CM_DEN / INT32_POS_OF_CM_NUM;
      ned_c.z = guidance_v_z_ref * INT32_POS_OF_CM_DEN / INT32_POS_OF_CM_NUM;
      ecef_of_ned_point_i(&gps.ecef_pos, &state.ned_origin_i, &ned_c);
      gps.lla_pos.alt = state.ned_origin_i.lla.alt - ned_c.z;
      gps.hmsl = state.ned_origin_i.hmsl - ned_c.z;
      ned_c.x = guidance_h.ref.speed.x * INT32_SPEED_OF_CM_S_DEN / INT32_SPEED_OF_CM_S_NUM;
      ned_c.y = guidance_h.ref.speed.y * INT32_SPEED_OF_CM_S_DEN / INT32_SPEED_OF_CM_S_NUM;
      ned_c.z = guidance_v_zd_ref * INT32_SPEED_OF_CM_S_DEN / INT32_SPEED_OF_CM_S_NUM;
      ecef_of_ned_vect_i(&gps.ecef_vel, &state.ned_origin_i, &ned_c);
      gps.fix = GPS_FIX_3D;
      gps.last_3dfix_ticks = sys_time.nb_sec_rem;
      gps.last_3dfix_time = sys_time.nb_sec;
      gps_available = true;
    }
    else {
      struct Int32Vect2 zero_vector;
      INT_VECT2_ZERO(zero_vector);
      gh_set_ref(zero_vector, zero_vector, zero_vector);
      gv_set_ref(0, 0, 0);
    }

    // publish gps data
    uint32_t now_ts = get_sys_time_usec();
    gps.last_msg_ticks = sys_time.nb_sec_rem;
    gps.last_msg_time = sys_time.nb_sec;
    if (gps.fix == GPS_FIX_3D) {
      gps.last_3dfix_ticks = sys_time.nb_sec_rem;
      gps.last_3dfix_time = sys_time.nb_sec;
    }
    AbiSendMsgGPS(GPS_SIM_ID, now_ts, &gps);
  }
}
コード例 #5
0
ファイル: airspeed_ets.c プロジェクト: Abhi0204/paparazzi
void airspeed_ets_read_periodic( void ) {
#ifndef SITL
  if (!airspeed_ets_delay_done) {
    if (SysTimeTimer(airspeed_ets_delay_time) < USEC_OF_SEC(AIRSPEED_ETS_START_DELAY)) return;
    else airspeed_ets_delay_done = TRUE;
  }
  if (airspeed_ets_i2c_trans.status == I2CTransDone)
    i2c_receive(&AIRSPEED_ETS_I2C_DEV, &airspeed_ets_i2c_trans, AIRSPEED_ETS_ADDR, 2);
#elif !defined USE_NPS
  extern float sim_air_speed;
  stateSetAirspeed_f(&sim_air_speed);
#endif //SITL
}
コード例 #6
0
ファイル: i2c_arch.c プロジェクト: 1bitsquared/paparazzi
void i2c_event(void) {
  static uint32_t i2c_wd_timer;

  if (SysTimeTimer(i2c_wd_timer) > 2000) { // 2ms (500Hz) periodic watchdog check
    SysTimeTimerStart(i2c_wd_timer);
#if USE_I2C1
    i2c_wd_check(&i2c1);
#endif

#if USE_I2C2
    i2c_wd_check(&i2c2);
#endif
#if USE_I2C3
    i2c_wd_check(&i2c3);
#endif
  }
}
コード例 #7
0
ファイル: actuators_mkk.c プロジェクト: AxSt/paparazzi
void actuators_set(bool_t motors_on) {
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) return;
    else actuators_delay_done = TRUE;
  }
#endif

  supervision_run(motors_on, FALSE, commands);
  for (uint8_t i=0; i<ACTUATORS_MKK_NB; i++) {
#ifdef KILL_MOTORS
    actuators_mkk.trans[i].buf[0] = 0;
#else
    actuators_mkk.trans[i].buf[0] = supervision.commands[i];
#endif
    i2c_submit(&ACTUATORS_MKK_DEVICE, &actuators_mkk.trans[i]);
  }
}
コード例 #8
0
ファイル: actuators_mkk.c プロジェクト: jornanke/paparazzi
void actuators_mkk_set(void) {
  const uint8_t actuators_addr[ACTUATORS_MKK_NB] = ACTUATORS_MKK_ADDR;

#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) return;
    else actuators_delay_done = TRUE;
  }
#endif

  for (uint8_t i=0; i<ACTUATORS_MKK_NB; i++) {

#ifdef KILL_MOTORS
    actuators_mkk.trans[i].buf[0] = 0;
#endif

    i2c_transmit(&ACTUATORS_MKK_DEVICE, &actuators_mkk.trans[i], actuators_addr[i], 1);
  }
}
コード例 #9
0
void actuators_asctec_set(bool_t motors_on) {
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) return;
    else actuators_delay_done = TRUE;
  }
#endif

  switch (actuators_asctec.i2c_trans.status) {
    case I2CTransFailed:
      actuators_asctec.nb_err++;
      actuators_asctec.i2c_trans.status = I2CTransDone;
      break;
    case I2CTransSuccess:
    case I2CTransDone:
      actuators_asctec.i2c_trans.status = I2CTransDone;
      break;
    default:
      actuators_asctec.nb_err++;
      return;
  }

#ifdef KILL_MOTORS
  actuators_asctec.cmds[PITCH]  = 0;
  actuators_asctec.cmds[ROLL]   = 0;
  actuators_asctec.cmds[YAW]    = 0;
  actuators_asctec.cmds[THRUST] = 0;
#else /* ! KILL_MOTORS */
  Bound(actuators_asctec.cmds[PITCH],ASCTEC_MIN_CMD, ASCTEC_MAX_CMD);
  Bound(actuators_asctec.cmds[ROLL], ASCTEC_MIN_CMD, ASCTEC_MAX_CMD);
  Bound(actuators_asctec.cmds[YAW],  ASCTEC_MIN_CMD, ASCTEC_MAX_CMD);
  if (motors_on) {
    Bound(actuators_asctec.cmds[THRUST], ASCTEC_MIN_THROTTLE + 1, ASCTEC_MAX_THROTTLE);
  }
  else
    actuators_asctec.cmds[THRUST] = 0;
#endif /* KILL_MOTORS  */

  switch (actuators_asctec.cmd) {
  case TEST:
    actuators_asctec.i2c_trans.buf[0] = 251;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = 0;
    actuators_asctec.i2c_trans.buf[3] = 231 + actuators_asctec.cur_addr;
    break;
  case REVERSE:
    actuators_asctec.i2c_trans.buf[0] = 254;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = 0;
    actuators_asctec.i2c_trans.buf[3] = 234 + actuators_asctec.cur_addr;
    break;
  case SET_ADDR:
    actuators_asctec.i2c_trans.buf[0] = 250;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = actuators_asctec.new_addr;
    actuators_asctec.i2c_trans.buf[3] = 230 + actuators_asctec.cur_addr +
                                        actuators_asctec.new_addr;
    actuators_asctec.cur_addr = actuators_asctec.new_addr;
    break;
  case NONE:
    actuators_asctec.i2c_trans.buf[0] = 100 - actuators_asctec.cmds[PITCH];
    actuators_asctec.i2c_trans.buf[1] = 100 + actuators_asctec.cmds[ROLL];
    actuators_asctec.i2c_trans.buf[2] = 100 - actuators_asctec.cmds[YAW];
    actuators_asctec.i2c_trans.buf[3] = actuators_asctec.cmds[THRUST];
    break;
  default:
    break;
  }
  actuators_asctec.cmd = NONE;

  i2c_transmit(&ACTUATORS_ASCTEC_I2C_DEV, &actuators_asctec.i2c_trans,
              ACTUATORS_ASCTEC_SLAVE_ADDR, 4);

}
コード例 #10
0
void actuators_asctec_v2_set(void) {
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) {
#ifdef USE_I2C_ACTUATORS_REBOOT_HACK
      //Lisa-L with Asctech v2 motors only start after reflashing when a bus error was sensed on stm32-i2c.
      //multiple re-init solves the problem.
      i2c1_init();
#endif
      return;
    }
    else actuators_delay_done = TRUE;
  }
#endif

  switch (actuators_asctec_v2.i2c_trans.status) {
    case I2CTransFailed:
      actuators_asctec_v2.nb_err++;
      actuators_asctec_v2.i2c_trans.status = I2CTransDone;
      break;
    case I2CTransSuccess:
    case I2CTransDone:
      actuators_asctec_v2.i2c_trans.status = I2CTransDone;
      break;
    default:
      actuators_asctec_v2.nb_err++;
      return;
  }

#ifdef KILL_MOTORS
  actuators_asctec_v2.i2c_trans.buf[0] = 0;
  actuators_asctec_v2.i2c_trans.buf[1] = 0;
  actuators_asctec_v2.i2c_trans.buf[2] = 0;
  actuators_asctec_v2.i2c_trans.buf[3] = 0;
  actuators_asctec_v2.i2c_trans.buf[4] = 0xAA;
#else
  switch (actuators_asctec_v2.cmd) {
    case TEST:
      actuators_asctec_v2.i2c_trans.buf[0] = 251;
      actuators_asctec_v2.i2c_trans.buf[1] = actuators_asctec_v2.cur_addr;
      actuators_asctec_v2.i2c_trans.buf[2] = 0;
      actuators_asctec_v2.i2c_trans.buf[3] = 231 + actuators_asctec_v2.cur_addr;
      actuators_asctec_v2.i2c_trans.len_w = 4;
      break;
    case REVERSE:
      actuators_asctec_v2.i2c_trans.buf[0] = 254;
      actuators_asctec_v2.i2c_trans.buf[1] = actuators_asctec_v2.cur_addr;
      actuators_asctec_v2.i2c_trans.buf[2] = 0;
      actuators_asctec_v2.i2c_trans.buf[3] = 234 + actuators_asctec_v2.cur_addr;
      actuators_asctec_v2.i2c_trans.len_w = 4;
      break;
    case SET_ADDR:
      actuators_asctec_v2.i2c_trans.buf[0] = 250;
      actuators_asctec_v2.i2c_trans.buf[1] = actuators_asctec_v2.cur_addr;
      actuators_asctec_v2.i2c_trans.buf[2] = actuators_asctec_v2.new_addr;
      actuators_asctec_v2.i2c_trans.buf[3] = 230 + actuators_asctec_v2.cur_addr +
                                             actuators_asctec_v2.new_addr;
      actuators_asctec_v2.cur_addr = actuators_asctec_v2.new_addr;
      actuators_asctec_v2.i2c_trans.len_w = 4;
      break;
    case NONE:
      actuators_asctec_v2.i2c_trans.buf[0] = actuators_asctec_v2.cmds[SERVO_FRONT];
      actuators_asctec_v2.i2c_trans.buf[1] = actuators_asctec_v2.cmds[SERVO_BACK];
      actuators_asctec_v2.i2c_trans.buf[2] = actuators_asctec_v2.cmds[SERVO_LEFT];
      actuators_asctec_v2.i2c_trans.buf[3] = actuators_asctec_v2.cmds[SERVO_RIGHT];
      actuators_asctec_v2.i2c_trans.buf[4] = 0xAA + actuators_asctec_v2.i2c_trans.buf[0] +
                                             actuators_asctec_v2.i2c_trans.buf[1] +
                                             actuators_asctec_v2.i2c_trans.buf[2] +
                                             actuators_asctec_v2.i2c_trans.buf[3];
      actuators_asctec_v2.i2c_trans.len_w = 5;
      break;
    default:
      break;
  }
  actuators_asctec_v2.cmd = NONE;
#endif

  actuators_asctec_v2.i2c_trans.type = I2CTransTx;   // Can be reset I2C driver
  i2c_submit(&ACTUATORS_ASCTEC_V2_DEVICE, &actuators_asctec_v2.i2c_trans);

}
コード例 #11
0
ファイル: actuators_asctec.c プロジェクト: alex31/paparazzi
void actuators_set(bool_t motors_on) {
#if defined ACTUATORS_START_DELAY && ! defined SITL
  if (!actuators_delay_done) {
    if (SysTimeTimer(actuators_delay_time) < USEC_OF_SEC(ACTUATORS_START_DELAY)) return;
    else actuators_delay_done = TRUE;
  }
#endif

  if (!actuators_asctec.i2c_trans.status == I2CTransSuccess)
    actuators_asctec.nb_err++;

#ifdef KILL_MOTORS
  actuators_asctec.cmds[PITCH]  = 0;
  actuators_asctec.cmds[ROLL]   = 0;
  actuators_asctec.cmds[YAW]    = 0;
  actuators_asctec.cmds[THRUST] = 0;
#else /* ! KILL_MOTORS */
  actuators_asctec.cmds[PITCH]  = commands[COMMAND_PITCH]  + SUPERVISION_TRIM_E;
  actuators_asctec.cmds[ROLL]   = commands[COMMAND_ROLL]   + SUPERVISION_TRIM_A;
  actuators_asctec.cmds[YAW]    = commands[COMMAND_YAW]    + SUPERVISION_TRIM_R;
  actuators_asctec.cmds[THRUST] = commands[COMMAND_THRUST];
  Bound(actuators_asctec.cmds[PITCH],-100, 100);
  Bound(actuators_asctec.cmds[ROLL], -100, 100);
  Bound(actuators_asctec.cmds[YAW],  -100, 100);
  if (motors_on) {
    Bound(actuators_asctec.cmds[THRUST],  1, 200);
  }
  else
    actuators_asctec.cmds[THRUST] = 0;
#endif /* KILL_MOTORS  */

  switch (actuators_asctec.cmd) {
  case TEST:
    actuators_asctec.i2c_trans.buf[0] = 251;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = 0;
    actuators_asctec.i2c_trans.buf[3] = 231 + actuators_asctec.cur_addr;
    break;
  case REVERSE:
    actuators_asctec.i2c_trans.buf[0] = 254;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = 0;
    actuators_asctec.i2c_trans.buf[3] = 234 + actuators_asctec.cur_addr;
    break;
  case SET_ADDR:
    actuators_asctec.i2c_trans.buf[0] = 250;
    actuators_asctec.i2c_trans.buf[1] = actuators_asctec.cur_addr;
    actuators_asctec.i2c_trans.buf[2] = actuators_asctec.new_addr;
    actuators_asctec.i2c_trans.buf[3] = 230 + actuators_asctec.cur_addr + actuators_asctec.new_addr;
    actuators_asctec.cur_addr = actuators_asctec.new_addr;
    break;
  case NONE:
    actuators_asctec.i2c_trans.buf[0] = 100 -  actuators_asctec.cmds[PITCH];
    actuators_asctec.i2c_trans.buf[1] = 100 + actuators_asctec.cmds[ROLL];
    actuators_asctec.i2c_trans.buf[2] = 100 - actuators_asctec.cmds[YAW];
    actuators_asctec.i2c_trans.buf[3] = actuators_asctec.cmds[THRUST];
    break;
  default:
    break;
  }
  actuators_asctec.cmd = NONE;

  i2c_submit(&ACTUATORS_ASCTEC_DEVICE, &actuators_asctec.i2c_trans);

}