1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-01 09:24:10 +01:00

OP-237 I2C ESC support. This _will_ require you to reconfigure your

ActuatorSettings although for PWM aircrafts it should be done exactly as before

Actuator: Store the update times and maximum update time

OP-14 I2C: Start tracking short history of events and states in driver for
logging
OP-237 Flight/Actuator: Support for I2C based ESCs

OP-237 MK_ESC: Send all four motors as one atomic transfer

OP-237 Flight/Actuator: Allow channels to be mapped to MK I2C interface.  Currently
mixer channels are either PWM or MK but in the future this will change to
support more than 8 channels.

OP-16 PiOS/I2C: Further work to try and make I2C more stable, mstly special case
handline in IRQ

OP-237 I2C ESC: Support for Astect 4 channel ESCs

OP-237: When the I2C Actuator write update fails track this

OP-237 Actuator Settings: Change the way motor types are selected to keep that
information more appropriately within ActuatorSettings instead of MixerSettings

Also make motors stay at or above neutral when armed and throttle > 0

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2366 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
peabody124 2011-01-10 01:11:44 +00:00 committed by peabody124
parent ed11e64bb2
commit b173d74821
20 changed files with 512 additions and 38 deletions

View File

@ -235,6 +235,7 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c
SRC += $(PIOSCOMMON)/pios_sdcard.c SRC += $(PIOSCOMMON)/pios_sdcard.c
SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_com.c
SRC += $(PIOSCOMMON)/pios_bmp085.c SRC += $(PIOSCOMMON)/pios_bmp085.c
SRC += $(PIOSCOMMON)/pios_i2c_esc.c
SRC += $(PIOSCOMMON)/pios_iap.c SRC += $(PIOSCOMMON)/pios_iap.c
#SRC += $(PIOSCOMMON)/pios_opahrs.c #SRC += $(PIOSCOMMON)/pios_opahrs.c
#SRC += $(PIOSCOMMON)/pios_opahrs_proto.c #SRC += $(PIOSCOMMON)/pios_opahrs_proto.c

View File

@ -67,6 +67,8 @@ static void actuatorTask(void* parameters);
static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral); static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral);
static void setFailsafe(); static void setFailsafe();
static float MixerCurve(const float throttle, const float* curve); static float MixerCurve(const float throttle, const float* curve);
static bool set_channel(uint8_t mixer_channel, uint16_t value);
float ProcessMixer(const int index, const float curve1, const float curve2, float ProcessMixer(const int index, const float curve1, const float curve2,
MixerSettingsData* mixerSettings, ActuatorDesiredData* desired, MixerSettingsData* mixerSettings, ActuatorDesiredData* desired,
const float period); const float period);
@ -99,7 +101,6 @@ int32_t ActuatorInitialize()
} }
/** /**
* @brieft Main Actuator module task * @brieft Main Actuator module task
* *
@ -201,25 +202,42 @@ static void actuatorTask(void* parameters)
lastResult[ct] = 0; lastResult[ct] = 0;
}else }else
{ {
// For motors when armed keep above neutral
if((mixer[ct].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) && (status[ct] < 0))
status[ct] = 0;
command.Channel[ct] = scaleChannel(status[ct], command.Channel[ct] = scaleChannel(status[ct],
settings.ChannelMax[ct], settings.ChannelMax[ct],
settings.ChannelMin[ct], settings.ChannelNeutral[ct],
settings.ChannelNeutral[ct]); settings.ChannelNeutral[ct]);
} }
} }
} }
MixerStatusSet(&mixerStatus); MixerStatusSet(&mixerStatus);
// Store update time
command.UpdateTime = 10000*dT;
if(command.UpdateTime > command.MaxUpdateTime)
command.MaxUpdateTime = command.UpdateTime;
// Update output object // Update output object
ActuatorCommandSet(&command); ActuatorCommandSet(&command);
// Update in case read only (eg. during servo configuration) // Update in case read only (eg. during servo configuration)
ActuatorCommandGet(&command); ActuatorCommandGet(&command);
// Update servo outputs // Update servo outputs
bool success = true;
for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n) for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n)
{ {
PIOS_Servo_Set( n, command.Channel[n] ); success &= set_channel(n, command.Channel[n]);
} }
if(!success) {
command.NumFailedUpdates++;
ActuatorCommandSet(&command);
AlarmsSet(SYSTEMALARMS_ALARM_ACTUATOR, SYSTEMALARMS_ALARM_CRITICAL);
}
} }
} }
@ -385,13 +403,47 @@ static void setFailsafe()
// Update servo outputs // Update servo outputs
for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n) for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n)
{ {
PIOS_Servo_Set( n, command.Channel[n] ); set_channel(n, command.Channel[n]);
} }
// Update output object // Update output object
ActuatorCommandSet(&command); ActuatorCommandSet(&command);
} }
static bool set_channel(uint8_t mixer_channel, uint16_t value) {
ActuatorSettingsData settings;
ActuatorSettingsGet(&settings);
switch(settings.ChannelType[mixer_channel]) {
case ACTUATORSETTINGS_CHANNELTYPE_PWM:
PIOS_Servo_Set(settings.ChannelAddr[mixer_channel], value);
return true;
case ACTUATORSETTINGS_CHANNELTYPE_MK:
{
ManualControlCommandData manual;
ManualControlCommandGet(&manual);
/* Unfortunately MK controller take forever to start so keep */
/* them spinning when armed */
if(manual.Armed)
value = (value < 0) ? 1 : value;
else
value = 0;
return PIOS_SetMKSpeed(settings.ChannelAddr[mixer_channel],value);
break;
}
case ACTUATORSETTINGS_CHANNELTYPE_ASTEC4:
return PIOS_SetAstec4Speed(settings.ChannelAddr[mixer_channel],value);
break;
default:
return false;
}
return false;
}
/** /**
* @} * @}

View File

@ -58,7 +58,7 @@
#define PIOS_INCLUDE_GPIO #define PIOS_INCLUDE_GPIO
#define PIOS_INCLUDE_EXTI #define PIOS_INCLUDE_EXTI
#define PIOS_INCLUDE_WDG #define PIOS_INCLUDE_WDG
#define PIOS_INCLUDE_I2C_ESC
/* Defaults for Logging */ /* Defaults for Logging */
#define LOG_FILENAME "PIOS.LOG" #define LOG_FILENAME "PIOS.LOG"

View File

@ -120,6 +120,22 @@ static void setDefaults(UAVObjHandle obj, uint16_t instId)
data.ChannelMin[5] = 1000; data.ChannelMin[5] = 1000;
data.ChannelMin[6] = 1000; data.ChannelMin[6] = 1000;
data.ChannelMin[7] = 1000; data.ChannelMin[7] = 1000;
data.ChannelType[0] = 0;
data.ChannelType[1] = 0;
data.ChannelType[2] = 0;
data.ChannelType[3] = 0;
data.ChannelType[4] = 0;
data.ChannelType[5] = 0;
data.ChannelType[6] = 0;
data.ChannelType[7] = 0;
data.ChannelAddr[0] = 0;
data.ChannelAddr[1] = 1;
data.ChannelAddr[2] = 2;
data.ChannelAddr[3] = 3;
data.ChannelAddr[4] = 4;
data.ChannelAddr[5] = 5;
data.ChannelAddr[6] = 6;
data.ChannelAddr[7] = 7;
UAVObjSetInstanceData(obj, instId, &data); UAVObjSetInstanceData(obj, instId, &data);

View File

@ -41,7 +41,7 @@
#define ACTUATORCOMMAND_H #define ACTUATORCOMMAND_H
// Object constants // Object constants
#define ACTUATORCOMMAND_OBJID 3909877022U #define ACTUATORCOMMAND_OBJID 3907024856U
#define ACTUATORCOMMAND_NAME "ActuatorCommand" #define ACTUATORCOMMAND_NAME "ActuatorCommand"
#define ACTUATORCOMMAND_METANAME "ActuatorCommandMeta" #define ACTUATORCOMMAND_METANAME "ActuatorCommandMeta"
#define ACTUATORCOMMAND_ISSINGLEINST 1 #define ACTUATORCOMMAND_ISSINGLEINST 1
@ -72,6 +72,9 @@
// Object data // Object data
typedef struct { typedef struct {
int16_t Channel[8]; int16_t Channel[8];
uint8_t UpdateTime;
uint8_t MaxUpdateTime;
uint8_t NumFailedUpdates;
} __attribute__((packed)) ActuatorCommandData; } __attribute__((packed)) ActuatorCommandData;
@ -79,6 +82,9 @@ typedef struct {
// Field Channel information // Field Channel information
/* Number of elements for field Channel */ /* Number of elements for field Channel */
#define ACTUATORCOMMAND_CHANNEL_NUMELEM 8 #define ACTUATORCOMMAND_CHANNEL_NUMELEM 8
// Field UpdateTime information
// Field MaxUpdateTime information
// Field NumFailedUpdates information
// Generic interface functions // Generic interface functions

View File

@ -41,7 +41,7 @@
#define ACTUATORSETTINGS_H #define ACTUATORSETTINGS_H
// Object constants // Object constants
#define ACTUATORSETTINGS_OBJID 3054509114U #define ACTUATORSETTINGS_OBJID 844831578U
#define ACTUATORSETTINGS_NAME "ActuatorSettings" #define ACTUATORSETTINGS_NAME "ActuatorSettings"
#define ACTUATORSETTINGS_METANAME "ActuatorSettingsMeta" #define ACTUATORSETTINGS_METANAME "ActuatorSettingsMeta"
#define ACTUATORSETTINGS_ISSINGLEINST 1 #define ACTUATORSETTINGS_ISSINGLEINST 1
@ -89,6 +89,8 @@ typedef struct {
int16_t ChannelMax[8]; int16_t ChannelMax[8];
int16_t ChannelNeutral[8]; int16_t ChannelNeutral[8];
int16_t ChannelMin[8]; int16_t ChannelMin[8];
uint8_t ChannelType[8];
uint8_t ChannelAddr[8];
} __attribute__((packed)) ActuatorSettingsData; } __attribute__((packed)) ActuatorSettingsData;
@ -147,6 +149,14 @@ typedef enum { ACTUATORSETTINGS_VTOLMOTORNW_CHANNEL1=0, ACTUATORSETTINGS_VTOLMOT
// Field ChannelMin information // Field ChannelMin information
/* Number of elements for field ChannelMin */ /* Number of elements for field ChannelMin */
#define ACTUATORSETTINGS_CHANNELMIN_NUMELEM 8 #define ACTUATORSETTINGS_CHANNELMIN_NUMELEM 8
// Field ChannelType information
/* Enumeration options for field ChannelType */
typedef enum { ACTUATORSETTINGS_CHANNELTYPE_PWM=0, ACTUATORSETTINGS_CHANNELTYPE_MK=1, ACTUATORSETTINGS_CHANNELTYPE_ASTEC4=2 } ActuatorSettingsChannelTypeOptions;
/* Number of elements for field ChannelType */
#define ACTUATORSETTINGS_CHANNELTYPE_NUMELEM 8
// Field ChannelAddr information
/* Number of elements for field ChannelAddr */
#define ACTUATORSETTINGS_CHANNELADDR_NUMELEM 8
// Generic interface functions // Generic interface functions

View File

@ -0,0 +1,172 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_I2C_ESC Code for controlling I2C based ESCs
* @brief Deals with the hardware interface to the magnetometers
* @{
*
* @file pios_i2c_esc.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief HMC5843 Magnetic Sensor Functions from AHRS
* @see The GNU Public License (GPL) Version 3
*
******************************************************************************
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Project Includes */
#include "pios.h"
#if defined(PIOS_INCLUDE_I2C_ESC)
/* HMC5843 Addresses */
#define MK_I2C_ADDR 0x29
#define ASTEC4_I2C_ADDR 0x02
bool PIOS_SetMKSpeed(uint8_t motornum, uint8_t speed);
uint8_t base_address = MK_I2C_ADDR;
uint8_t valid_motors = 0;
bool PIOS_I2C_ESC_Config()
{
base_address = MK_I2C_ADDR;
valid_motors = 0;
for(uint8_t i = 0; i < 4; i ++)
if(PIOS_SetMKSpeed(i, 0))
valid_motors |= (1 << i);
return true;
}
bool PIOS_I2C_ESC_SetSpeed(uint8_t speed[4])
{
/*bool success = true;
for(uint8_t i = 0; i < 4; i++) {
//if(valid_motors & (1 << i))
success &= PIOS_SetMKSpeed(i, speed[i]);
}
return success; */
const struct pios_i2c_txn txn_list[] = {
{
.info = __func__,
.addr = MK_I2C_ADDR + 0,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(speed[0]),
.buf = &speed[0],
} ,
{
.info = __func__,
.addr = MK_I2C_ADDR + 1,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(speed[1]),
.buf = &speed[1],
},
{
.info = __func__,
.addr = MK_I2C_ADDR + 2,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(speed[2]),
.buf = &speed[2],
},
{
.info = __func__,
.addr = MK_I2C_ADDR + 3,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(speed[3]),
.buf = &speed[3],
}
};
return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list));
}
bool PIOS_SetMKSpeed(uint8_t motornum, uint8_t speed) {
static uint8_t speeds[4] = {0,0,0,0};
if(motornum >= 4)
return false;
if(speeds[motornum] == speed)
return true;
const struct pios_i2c_txn txn_list[] = {
{
.info = __func__,
.addr = MK_I2C_ADDR + motornum,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(speed),
.buf = &speed,
}
};
return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list));
}
bool PIOS_SetAstec4Address(uint8_t new_address) {
if((new_address < 0) || (new_address > 4))
return false;
uint8_t data[4] = {250, 0, new_address, 230+new_address};
const struct pios_i2c_txn txn_list[] = {
{
.info = __func__,
.addr = ASTEC4_I2C_ADDR,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(data),
.buf = &data[0],
}
};
return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list));
}
bool PIOS_SetAstec4Speed(uint8_t motornum, uint8_t speed) {
static uint8_t speeds[5] = {0,0,0,0};
if((motornum < 0) || (motornum >= 4))
return false;
speeds[motornum] = speed;
if(motornum != 3)
return true;
/* Write in chunks of four */
speeds[4] = 0xAA + speeds[0] + speeds[1] + speeds[2] + speeds[3];
const struct pios_i2c_txn txn_list[] = {
{
.info = __func__,
.addr = ASTEC4_I2C_ADDR,
.rw = PIOS_I2C_TXN_WRITE,
.len = sizeof(speeds),
.buf = &speeds[0],
}
};
return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list));
}
#endif
/**
* @}
* @}
*/

View File

@ -353,7 +353,6 @@ static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter)
#endif #endif
/* Note that this transfer has hit a bus error */ /* Note that this transfer has hit a bus error */
i2c_adapter->bus_error = true; i2c_adapter->bus_error = true;
// i2c_adapter->curr_state = I2C_STATE_STOPPED;
i2c_adapter_reset_bus(i2c_adapter); i2c_adapter_reset_bus(i2c_adapter);
@ -672,7 +671,7 @@ static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
/* Check SDA line to determine if slave is asserting bus and clock out if so, this may */ /* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
/* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */ /* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */
/* ESC */ /* ESC */
bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET; //bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
while(GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET) { while(GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET) {
/* Set clock high and wait for any clock stretching to finish. */ /* Set clock high and wait for any clock stretching to finish. */
@ -688,17 +687,14 @@ static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin); GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
PIOS_DELAY_WaituS(2); PIOS_DELAY_WaituS(2);
} }
if(sda_hung) {
/* Generate a start then stop condition */ /* Generate a start then stop condition */
GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin); GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
PIOS_DELAY_WaituS(2); PIOS_DELAY_WaituS(2);
GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin); GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
PIOS_DELAY_WaituS(2); PIOS_DELAY_WaituS(2);
GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin); GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
PIOS_DELAY_WaituS(2); PIOS_DELAY_WaituS(2);
}
/* Set data and clock high and wait for any clock stretching to finish. */ /* Set data and clock high and wait for any clock stretching to finish. */
GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin); GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
@ -914,6 +910,8 @@ void PIOS_I2C_EV_IRQ_Handler(uint8_t i2c)
i2c_adapter = find_i2c_adapter_by_id(i2c); i2c_adapter = find_i2c_adapter_by_id(i2c);
PIOS_DEBUG_Assert(i2c_adapter); PIOS_DEBUG_Assert(i2c_adapter);
PIOS_DELAY_WaituS(1);
uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs); uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
#if defined(PIOS_I2C_DIAGNOSTICS) #if defined(PIOS_I2C_DIAGNOSTICS)
@ -983,7 +981,7 @@ void PIOS_I2C_EV_IRQ_Handler(uint8_t i2c)
while (halt) ; while (halt) ;
} }
break; break;
case 0: /* Unexplained spurious event. Not sure what to do here. */ case 0: /* This triggers an FSM fault sometimes, but not having it stops things working */
case 0x40: /* RxNE only. MSL + BUSY have already been cleared by HW. */ case 0x40: /* RxNE only. MSL + BUSY have already been cleared by HW. */
case 0x44: /* RxNE + BTF. MSL + BUSY have already been cleared by HW. */ case 0x44: /* RxNE + BTF. MSL + BUSY have already been cleared by HW. */
case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */ case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
@ -1011,6 +1009,7 @@ void PIOS_I2C_EV_IRQ_Handler(uint8_t i2c)
break; break;
case 0x30084: /* Occurs between byte tranmistted and master mode selected */ case 0x30084: /* Occurs between byte tranmistted and master mode selected */
case 0x30000: /* Need to throw away this spurious event */ case 0x30000: /* Need to throw away this spurious event */
//case 0x0: /* Not sure why zeros are occurring */
goto skip_event; goto skip_event;
break; break;
default: default:
@ -1026,25 +1025,50 @@ skip_event:
; ;
} }
uint32_t i2c_interrupt_history[5];
uint8_t i2c_interrupt_history_pointer = 0;
void PIOS_I2C_ER_IRQ_Handler(uint8_t i2c) void PIOS_I2C_ER_IRQ_Handler(uint8_t i2c)
{ {
struct pios_i2c_adapter *i2c_adapter; struct pios_i2c_adapter *i2c_adapter;
i2c_adapter = find_i2c_adapter_by_id(i2c); i2c_adapter = find_i2c_adapter_by_id(i2c);
PIOS_DEBUG_Assert(i2c_adapter); PIOS_DEBUG_Assert(i2c_adapter);
PIOS_DELAY_WaituS(1);
#if defined(PIOS_I2C_DIAGNOSTICS) #if defined(PIOS_I2C_DIAGNOSTICS)
uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs); uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
/* Store event for diagnostics */ i2c_interrupt_history[i2c_interrupt_history_pointer] = event;
i2c_event_history[i2c_event_history_pointer] = event; i2c_interrupt_history_pointer = (i2c_interrupt_history_pointer + 1) % 5;
i2c_event_history_pointer = (i2c_event_history_pointer + 1) % I2C_LOG_DEPTH;
#endif
if(I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_AF)) { #endif
switch(event) {
case 0x70184: /* EV8_2, but system detects own stop byte as erroneous */
switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
case 0:
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0);
break;
case 1:
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1);
break;
case 2:
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2);
break;
default:
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_GT_2);
break;
}
return;
break;
}
if(event & I2C_FLAG_AF) {
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK); i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK);
} else { } else { /* Mostly bus errors here */
i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT); i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT);
/* Fail hard on any errors for now */ /* Fail hard on any errors for now */

View File

@ -0,0 +1,49 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_I2C_ESC Code for controlling I2C based ESCs
* @brief Deals with the hardware interface to the magnetometers
* @{
*
* @file pios_i2c_esc.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief HMC5843 Magnetic Sensor Functions from AHRS
* @see The GNU Public License (GPL) Version 3
*
******************************************************************************
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PIOS_I2C_ESC_H
#define PIOS_I2C_ESC_H
/* Public Functions */
#include <stdbool.h>
#include <stdint.h>
bool PIOS_I2C_ESC_Config();
bool PIOS_I2C_ESC_SetSpeed(uint8_t speed[4]);
bool PIOS_SetMKSpeed(uint8_t motornum, uint8_t speed);
bool PIOS_SetAstec4Speed(uint8_t motornum, uint8_t speed);
#endif /* PIOS_I2C_ESC_H */
/**
* @}
* @}
*/

View File

@ -92,6 +92,9 @@
#if defined(PIOS_INCLUDE_HMC5843) #if defined(PIOS_INCLUDE_HMC5843)
#include <pios_hmc5843.h> #include <pios_hmc5843.h>
#endif #endif
#if defined(PIOS_INCLUDE_I2C_ESC)
#include <pios_i2c_esc.h>
#endif
#include <pios_iap.h> #include <pios_iap.h>
#if defined(PIOS_INCLUDE_BL_HELPER) #if defined(PIOS_INCLUDE_BL_HELPER)

View File

@ -41,9 +41,6 @@
6549E0D21279B3C800C5476F /* fifo_buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fifo_buffer.c; sourceTree = "<group>"; }; 6549E0D21279B3C800C5476F /* fifo_buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fifo_buffer.c; sourceTree = "<group>"; };
6549E0D31279B3CF00C5476F /* fifo_buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fifo_buffer.h; sourceTree = "<group>"; }; 6549E0D31279B3CF00C5476F /* fifo_buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fifo_buffer.h; sourceTree = "<group>"; };
655268BC121FBD2900410C6E /* ahrscalibration.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = ahrscalibration.xml; sourceTree = "<group>"; }; 655268BC121FBD2900410C6E /* ahrscalibration.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = ahrscalibration.xml; sourceTree = "<group>"; };
655DBA5212DA5B6A00341B9A /* pios_iap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_iap.h; sourceTree = "<group>"; };
655DBA5312DA5E9900341B9A /* watchdogstatus.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = watchdogstatus.xml; sourceTree = "<group>"; };
655DBA8A12DA644300341B9A /* taskmonitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = taskmonitor.c; sourceTree = "<group>"; };
65632CBF124E09D900469B77 /* guidance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guidance.c; sourceTree = "<group>"; }; 65632CBF124E09D900469B77 /* guidance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guidance.c; sourceTree = "<group>"; };
65632CC1124E09D900469B77 /* guidance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guidance.h; sourceTree = "<group>"; }; 65632CC1124E09D900469B77 /* guidance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guidance.h; sourceTree = "<group>"; };
65632DF51251650300469B77 /* pios_board.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_board.h; sourceTree = "<group>"; }; 65632DF51251650300469B77 /* pios_board.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_board.h; sourceTree = "<group>"; };
@ -6786,7 +6783,6 @@
65B367FD121C2620003EAD18 /* systemstats.xml */, 65B367FD121C2620003EAD18 /* systemstats.xml */,
65B367FE121C2620003EAD18 /* telemetrysettings.xml */, 65B367FE121C2620003EAD18 /* telemetrysettings.xml */,
65408AA812BB1648004DACC5 /* i2cstats.xml */, 65408AA812BB1648004DACC5 /* i2cstats.xml */,
655DBA5312DA5E9900341B9A /* watchdogstatus.xml */,
); );
path = uavobjectdefinition; path = uavobjectdefinition;
sourceTree = "<group>"; sourceTree = "<group>";
@ -7113,7 +7109,6 @@
65E8EF5B11EEA61E00BBF654 /* System */ = { 65E8EF5B11EEA61E00BBF654 /* System */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
655DBA8A12DA644300341B9A /* taskmonitor.c */,
65E8EF5C11EEA61E00BBF654 /* alarms.c */, 65E8EF5C11EEA61E00BBF654 /* alarms.c */,
65E8EF5D11EEA61E00BBF654 /* inc */, 65E8EF5D11EEA61E00BBF654 /* inc */,
65E8EF6511EEA61E00BBF654 /* openpilot.c */, 65E8EF6511EEA61E00BBF654 /* openpilot.c */,
@ -7298,7 +7293,6 @@
65E8F03811EFF25C00BBF654 /* inc */ = { 65E8F03811EFF25C00BBF654 /* inc */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
655DBA5212DA5B6A00341B9A /* pios_iap.h */,
6526645A122DF972006F9A3C /* pios_i2c_priv.h */, 6526645A122DF972006F9A3C /* pios_i2c_priv.h */,
6526645B122DF972006F9A3C /* pios_wdg.h */, 6526645B122DF972006F9A3C /* pios_wdg.h */,
651CF9EF120B700D00EEFD70 /* pios_usb_hid_desc.h */, 651CF9EF120B700D00EEFD70 /* pios_usb_hid_desc.h */,

View File

@ -4,6 +4,9 @@ function [] = OPLogConvert()
actuatorcommandIdx = 1; actuatorcommandIdx = 1;
ActuatorCommand.timestamp = 0; ActuatorCommand.timestamp = 0;
ActuatorCommand(1).Channel = zeros(1,8); ActuatorCommand(1).Channel = zeros(1,8);
ActuatorCommand(1).UpdateTime = 0;
ActuatorCommand(1).MaxUpdateTime = 0;
ActuatorCommand(1).NumFailedUpdates = 0;
actuatordesiredIdx = 1; actuatordesiredIdx = 1;
ActuatorDesired.timestamp = 0; ActuatorDesired.timestamp = 0;
@ -34,6 +37,8 @@ function [] = OPLogConvert()
ActuatorSettings(1).ChannelMax = zeros(1,8); ActuatorSettings(1).ChannelMax = zeros(1,8);
ActuatorSettings(1).ChannelNeutral = zeros(1,8); ActuatorSettings(1).ChannelNeutral = zeros(1,8);
ActuatorSettings(1).ChannelMin = zeros(1,8); ActuatorSettings(1).ChannelMin = zeros(1,8);
ActuatorSettings(1).ChannelType = zeros(1,8);
ActuatorSettings(1).ChannelAddr = zeros(1,8);
ahrscalibrationIdx = 1; ahrscalibrationIdx = 1;
AHRSCalibration.timestamp = 0; AHRSCalibration.timestamp = 0;
@ -453,13 +458,13 @@ function [] = OPLogConvert()
%% Read object %% Read object
switch objID switch objID
case 3909877022 case 3907024856
ActuatorCommand(actuatorcommandIdx) = ReadActuatorCommandObject(fid, timestamp); ActuatorCommand(actuatorcommandIdx) = ReadActuatorCommandObject(fid, timestamp);
actuatorcommandIdx = actuatorcommandIdx + 1; actuatorcommandIdx = actuatorcommandIdx + 1;
case 3562104706 case 3562104706
ActuatorDesired(actuatordesiredIdx) = ReadActuatorDesiredObject(fid, timestamp); ActuatorDesired(actuatordesiredIdx) = ReadActuatorDesiredObject(fid, timestamp);
actuatordesiredIdx = actuatordesiredIdx + 1; actuatordesiredIdx = actuatordesiredIdx + 1;
case 3054509114 case 844831578
ActuatorSettings(actuatorsettingsIdx) = ReadActuatorSettingsObject(fid, timestamp); ActuatorSettings(actuatorsettingsIdx) = ReadActuatorSettingsObject(fid, timestamp);
actuatorsettingsIdx = actuatorsettingsIdx + 1; actuatorsettingsIdx = actuatorsettingsIdx + 1;
case 806362034 case 806362034
@ -611,6 +616,9 @@ function [ActuatorCommand] = ReadActuatorCommandObject(fid, timestamp)
ActuatorCommand.timestamp = timestamp; ActuatorCommand.timestamp = timestamp;
ActuatorCommand.Channel = double(fread(fid, 8, 'int16')); ActuatorCommand.Channel = double(fread(fid, 8, 'int16'));
ActuatorCommand.UpdateTime = double(fread(fid, 1, 'uint8'));
ActuatorCommand.MaxUpdateTime = double(fread(fid, 1, 'uint8'));
ActuatorCommand.NumFailedUpdates = double(fread(fid, 1, 'uint8'));
% read CRC % read CRC
fread(fid, 1, 'uint8'); fread(fid, 1, 'uint8');
end end
@ -661,6 +669,8 @@ function [ActuatorSettings] = ReadActuatorSettingsObject(fid, timestamp)
ActuatorSettings.ChannelMax = double(fread(fid, 8, 'int16')); ActuatorSettings.ChannelMax = double(fread(fid, 8, 'int16'));
ActuatorSettings.ChannelNeutral = double(fread(fid, 8, 'int16')); ActuatorSettings.ChannelNeutral = double(fread(fid, 8, 'int16'));
ActuatorSettings.ChannelMin = double(fread(fid, 8, 'int16')); ActuatorSettings.ChannelMin = double(fread(fid, 8, 'int16'));
ActuatorSettings.ChannelType = double(fread(fid, 8, 'uint8'));
ActuatorSettings.ChannelAddr = double(fread(fid, 8, 'uint8'));
% read CRC % read CRC
fread(fid, 1, 'uint8'); fread(fid, 1, 'uint8');
end end

View File

@ -53,6 +53,15 @@ ActuatorCommand::ActuatorCommand(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTING
ChannelElemNames.append("6"); ChannelElemNames.append("6");
ChannelElemNames.append("7"); ChannelElemNames.append("7");
fields.append( new UAVObjectField(QString("Channel"), QString("us"), UAVObjectField::INT16, ChannelElemNames, QStringList()) ); fields.append( new UAVObjectField(QString("Channel"), QString("us"), UAVObjectField::INT16, ChannelElemNames, QStringList()) );
QStringList UpdateTimeElemNames;
UpdateTimeElemNames.append("0");
fields.append( new UAVObjectField(QString("UpdateTime"), QString("ms x 10"), UAVObjectField::UINT8, UpdateTimeElemNames, QStringList()) );
QStringList MaxUpdateTimeElemNames;
MaxUpdateTimeElemNames.append("0");
fields.append( new UAVObjectField(QString("MaxUpdateTime"), QString("ms x 10"), UAVObjectField::UINT8, MaxUpdateTimeElemNames, QStringList()) );
QStringList NumFailedUpdatesElemNames;
NumFailedUpdatesElemNames.append("0");
fields.append( new UAVObjectField(QString("NumFailedUpdates"), QString(""), UAVObjectField::UINT8, NumFailedUpdatesElemNames, QStringList()) );
// Initialize object // Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES); initializeFields(fields, (quint8*)&data, NUMBYTES);

View File

@ -44,6 +44,9 @@ public:
// Field structure // Field structure
typedef struct { typedef struct {
qint16 Channel[8]; qint16 Channel[8];
quint8 UpdateTime;
quint8 MaxUpdateTime;
quint8 NumFailedUpdates;
} __attribute__((packed)) DataFields; } __attribute__((packed)) DataFields;
@ -51,10 +54,13 @@ public:
// Field Channel information // Field Channel information
/* Number of elements for field Channel */ /* Number of elements for field Channel */
static const quint32 CHANNEL_NUMELEM = 8; static const quint32 CHANNEL_NUMELEM = 8;
// Field UpdateTime information
// Field MaxUpdateTime information
// Field NumFailedUpdates information
// Constants // Constants
static const quint32 OBJID = 3909877022U; static const quint32 OBJID = 3907024856U;
static const QString NAME; static const QString NAME;
static const QString DESCRIPTION; static const QString DESCRIPTION;
static const bool ISSINGLEINST = 1; static const bool ISSINGLEINST = 1;

View File

@ -54,12 +54,42 @@ _fields = [ \
{ {
} }
), ),
uavobject.UAVObjectField(
'UpdateTime',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'MaxUpdateTime',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'NumFailedUpdates',
'B',
1,
[
'0',
],
{
}
),
] ]
class ActuatorCommand(uavobject.UAVObject): class ActuatorCommand(uavobject.UAVObject):
## Object constants ## Object constants
OBJID = 3909877022 OBJID = 3907024856
NAME = "ActuatorCommand" NAME = "ActuatorCommand"
METANAME = "ActuatorCommandMeta" METANAME = "ActuatorCommandMeta"
ISSINGLEINST = 1 ISSINGLEINST = 1

View File

@ -259,6 +259,30 @@ ActuatorSettings::ActuatorSettings(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTI
ChannelMinElemNames.append("6"); ChannelMinElemNames.append("6");
ChannelMinElemNames.append("7"); ChannelMinElemNames.append("7");
fields.append( new UAVObjectField(QString("ChannelMin"), QString("us"), UAVObjectField::INT16, ChannelMinElemNames, QStringList()) ); fields.append( new UAVObjectField(QString("ChannelMin"), QString("us"), UAVObjectField::INT16, ChannelMinElemNames, QStringList()) );
QStringList ChannelTypeElemNames;
ChannelTypeElemNames.append("0");
ChannelTypeElemNames.append("1");
ChannelTypeElemNames.append("2");
ChannelTypeElemNames.append("3");
ChannelTypeElemNames.append("4");
ChannelTypeElemNames.append("5");
ChannelTypeElemNames.append("6");
ChannelTypeElemNames.append("7");
QStringList ChannelTypeEnumOptions;
ChannelTypeEnumOptions.append("PWM");
ChannelTypeEnumOptions.append("MK");
ChannelTypeEnumOptions.append("ASTEC4");
fields.append( new UAVObjectField(QString("ChannelType"), QString(""), UAVObjectField::ENUM, ChannelTypeElemNames, ChannelTypeEnumOptions) );
QStringList ChannelAddrElemNames;
ChannelAddrElemNames.append("0");
ChannelAddrElemNames.append("1");
ChannelAddrElemNames.append("2");
ChannelAddrElemNames.append("3");
ChannelAddrElemNames.append("4");
ChannelAddrElemNames.append("5");
ChannelAddrElemNames.append("6");
ChannelAddrElemNames.append("7");
fields.append( new UAVObjectField(QString("ChannelAddr"), QString(""), UAVObjectField::UINT8, ChannelAddrElemNames, QStringList()) );
// Initialize object // Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES); initializeFields(fields, (quint8*)&data, NUMBYTES);
@ -334,6 +358,22 @@ void ActuatorSettings::setDefaultFieldValues()
data.ChannelMin[5] = 1000; data.ChannelMin[5] = 1000;
data.ChannelMin[6] = 1000; data.ChannelMin[6] = 1000;
data.ChannelMin[7] = 1000; data.ChannelMin[7] = 1000;
data.ChannelType[0] = 0;
data.ChannelType[1] = 0;
data.ChannelType[2] = 0;
data.ChannelType[3] = 0;
data.ChannelType[4] = 0;
data.ChannelType[5] = 0;
data.ChannelType[6] = 0;
data.ChannelType[7] = 0;
data.ChannelAddr[0] = 0;
data.ChannelAddr[1] = 1;
data.ChannelAddr[2] = 2;
data.ChannelAddr[3] = 3;
data.ChannelAddr[4] = 4;
data.ChannelAddr[5] = 5;
data.ChannelAddr[6] = 6;
data.ChannelAddr[7] = 7;
} }

View File

@ -61,6 +61,8 @@ public:
qint16 ChannelMax[8]; qint16 ChannelMax[8];
qint16 ChannelNeutral[8]; qint16 ChannelNeutral[8];
qint16 ChannelMin[8]; qint16 ChannelMin[8];
quint8 ChannelType[8];
quint8 ChannelAddr[8];
} __attribute__((packed)) DataFields; } __attribute__((packed)) DataFields;
@ -119,10 +121,18 @@ public:
// Field ChannelMin information // Field ChannelMin information
/* Number of elements for field ChannelMin */ /* Number of elements for field ChannelMin */
static const quint32 CHANNELMIN_NUMELEM = 8; static const quint32 CHANNELMIN_NUMELEM = 8;
// Field ChannelType information
/* Enumeration options for field ChannelType */
typedef enum { CHANNELTYPE_PWM=0, CHANNELTYPE_MK=1, CHANNELTYPE_ASTEC4=2 } ChannelTypeOptions;
/* Number of elements for field ChannelType */
static const quint32 CHANNELTYPE_NUMELEM = 8;
// Field ChannelAddr information
/* Number of elements for field ChannelAddr */
static const quint32 CHANNELADDR_NUMELEM = 8;
// Constants // Constants
static const quint32 OBJID = 3054509114U; static const quint32 OBJID = 844831578U;
static const QString NAME; static const QString NAME;
static const QString DESCRIPTION; static const QString DESCRIPTION;
static const bool ISSINGLEINST = 1; static const bool ISSINGLEINST = 1;

View File

@ -365,12 +365,49 @@ _fields = [ \
{ {
} }
), ),
uavobject.UAVObjectField(
'ChannelType',
'b',
8,
[
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
],
{
'0' : 'PWM',
'1' : 'MK',
'2' : 'ASTEC4',
}
),
uavobject.UAVObjectField(
'ChannelAddr',
'B',
8,
[
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
],
{
}
),
] ]
class ActuatorSettings(uavobject.UAVObject): class ActuatorSettings(uavobject.UAVObject):
## Object constants ## Object constants
OBJID = 3054509114 OBJID = 844831578
NAME = "ActuatorSettings" NAME = "ActuatorSettings"
METANAME = "ActuatorSettingsMeta" METANAME = "ActuatorSettingsMeta"
ISSINGLEINST = 1 ISSINGLEINST = 1

View File

@ -2,6 +2,9 @@
<object name="ActuatorCommand" singleinstance="true" settings="false"> <object name="ActuatorCommand" singleinstance="true" settings="false">
<description>Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule</description> <description>Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule</description>
<field name="Channel" units="us" type="int16" elements="8"/> <field name="Channel" units="us" type="int16" elements="8"/>
<field name="UpdateTime" units="ms x 10" type="uint8" elements="1"/>
<field name="MaxUpdateTime" units="ms x 10" type="uint8" elements="1"/>
<field name="NumFailedUpdates" units="" type="uint8" elements="1"/>
<access gcs="readwrite" flight="readwrite"/> <access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/> <telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="periodic" period="1000"/> <telemetryflight acked="false" updatemode="periodic" period="1000"/>

View File

@ -19,6 +19,8 @@
<field name="ChannelMax" units="us" type="int16" elements="8" defaultvalue="1000"/> <field name="ChannelMax" units="us" type="int16" elements="8" defaultvalue="1000"/>
<field name="ChannelNeutral" units="us" type="int16" elements="8" defaultvalue="1000"/> <field name="ChannelNeutral" units="us" type="int16" elements="8" defaultvalue="1000"/>
<field name="ChannelMin" units="us" type="int16" elements="8" defaultvalue="1000"/> <field name="ChannelMin" units="us" type="int16" elements="8" defaultvalue="1000"/>
<field name="ChannelType" units="" type="enum" elements="8" options="PWM,MK,ASTEC4" defaultvalue="PWM"/>
<field name="ChannelAddr" units="" type="uint8" elements="8" defaultvalue="0,1,2,3,4,5,6,7"/>
<access gcs="readwrite" flight="readwrite"/> <access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/> <telemetrygcs acked="true" updatemode="onchange" period="0"/>
<telemetryflight acked="true" updatemode="onchange" period="0"/> <telemetryflight acked="true" updatemode="onchange" period="0"/>