mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-25 16:56:25 +08:00
Merge branch 'master' of https://github.com/PX4/Firmware into fmuv2_bringup
Fix px4iov2 build issue by selecting the correct NuttX config.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
@@ -95,9 +95,14 @@ all: $(STAGED_FIRMWARES)
|
||||
#
|
||||
# Copy FIRMWARES into the image directory.
|
||||
#
|
||||
# XXX copying the .bin files is a hack to work around the PX4IO uploader
|
||||
# not supporting .px4 files, and it should be deprecated onced that
|
||||
# is taken care of.
|
||||
#
|
||||
$(STAGED_FIRMWARES): $(IMAGE_DIR)%.px4: $(BUILD_DIR)%.build/firmware.px4
|
||||
@echo %% Copying $@
|
||||
$(Q) $(COPY) $< $@
|
||||
$(Q) $(COPY) $(patsubst %.px4,%.bin,$<) $(patsubst %.px4,%.bin,$@)
|
||||
|
||||
#
|
||||
# Generate FIRMWARES.
|
||||
@@ -159,11 +164,11 @@ $(NUTTX_ARCHIVES): $(ARCHIVE_DIR)%.export: $(NUTTX_SRC) $(NUTTX_APPS)
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(Q) $(RMDIR) $(BUILD_DIR)*.build
|
||||
$(Q) $(REMOVE) -f $(IMAGE_DIR)*.px4
|
||||
$(Q) $(REMOVE) $(IMAGE_DIR)*.px4
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
$(Q) $(REMOVE) -f $(ARCHIVE_DIR)*.export
|
||||
$(Q) $(REMOVE) $(ARCHIVE_DIR)*.export
|
||||
$(Q) make -C $(NUTTX_SRC) -r $(MQUIET) distclean
|
||||
|
||||
#
|
||||
@@ -196,6 +201,11 @@ help:
|
||||
@echo " distclean"
|
||||
@echo " Remove all compilation products, including NuttX RTOS archives."
|
||||
@echo ""
|
||||
@echo " upload"
|
||||
@echo " When exactly one config is being built, add this target to upload the"
|
||||
@echo " firmware to the board when the build is complete. Not supported for"
|
||||
@echo " all configurations."
|
||||
@echo ""
|
||||
@echo " Common options:"
|
||||
@echo " ---------------"
|
||||
@echo ""
|
||||
|
||||
@@ -20,10 +20,10 @@ uorb start
|
||||
# Load microSD params
|
||||
#
|
||||
echo "[init] loading microSD params"
|
||||
param select /fs/microsd/parameters
|
||||
if [ -f /fs/microsd/parameters ]
|
||||
param select /fs/microsd/params
|
||||
if [ -f /fs/microsd/params ]
|
||||
then
|
||||
param load /fs/microsd/parameters
|
||||
param load /fs/microsd/params
|
||||
fi
|
||||
|
||||
#
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#!nsh
|
||||
|
||||
# Disable USB and autostart
|
||||
set USB no
|
||||
set MODE quad
|
||||
|
||||
#
|
||||
# Start the ORB (first app to start)
|
||||
#
|
||||
uorb start
|
||||
|
||||
#
|
||||
# Load microSD params
|
||||
#
|
||||
echo "[init] loading microSD params"
|
||||
param select /fs/microsd/params
|
||||
if [ -f /fs/microsd/params ]
|
||||
then
|
||||
param load /fs/microsd/params
|
||||
fi
|
||||
|
||||
#
|
||||
# Force some key parameters to sane values
|
||||
# MAV_TYPE 1 = fixed wing, 2 = quadrotor, 13 = hexarotor
|
||||
# see https://pixhawk.ethz.ch/mavlink/
|
||||
#
|
||||
param set MAV_TYPE 2
|
||||
|
||||
#
|
||||
# Check if PX4IO Firmware should be upgraded (from Andrew Tridgell)
|
||||
#
|
||||
if [ -f /fs/microsd/px4io.bin ]
|
||||
then
|
||||
echo "PX4IO Firmware found. Checking Upgrade.."
|
||||
if cmp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
|
||||
then
|
||||
echo "No newer version, skipping upgrade."
|
||||
else
|
||||
echo "Loading /fs/microsd/px4io.bin"
|
||||
if px4io update /fs/microsd/px4io.bin > /fs/microsd/px4io_update.log
|
||||
then
|
||||
cp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
|
||||
echo "Flashed /fs/microsd/px4io.bin OK" >> /fs/microsd/px4io_update.log
|
||||
else
|
||||
echo "Failed flashing /fs/microsd/px4io.bin" >> /fs/microsd/px4io_update.log
|
||||
echo "Failed to upgrade PX4IO firmware - check if PX4IO is in bootloader mode"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Start MAVLink (depends on orb)
|
||||
#
|
||||
mavlink start -d /dev/ttyS1 -b 57600
|
||||
usleep 5000
|
||||
|
||||
#
|
||||
# Start the commander (depends on orb, mavlink)
|
||||
#
|
||||
commander start
|
||||
|
||||
#
|
||||
# Start PX4IO interface (depends on orb, commander)
|
||||
#
|
||||
px4io start
|
||||
|
||||
#
|
||||
# Allow PX4IO to recover from midair restarts.
|
||||
# this is very unlikely, but quite safe and robust.
|
||||
px4io recovery
|
||||
|
||||
#
|
||||
# Start the sensors (depends on orb, px4io)
|
||||
#
|
||||
sh /etc/init.d/rc.sensors
|
||||
|
||||
#
|
||||
# Start GPS interface (depends on orb)
|
||||
#
|
||||
gps start
|
||||
|
||||
#
|
||||
# Start the attitude estimator (depends on orb)
|
||||
#
|
||||
attitude_estimator_ekf start
|
||||
|
||||
#
|
||||
# Load mixer and start controllers (depends on px4io)
|
||||
#
|
||||
mixer load /dev/pwm_output /etc/mixers/FMU_quad_+.mix
|
||||
multirotor_att_control start
|
||||
|
||||
#
|
||||
# Start logging
|
||||
#
|
||||
#sdlog start -s 4
|
||||
|
||||
#
|
||||
# Start system state
|
||||
#
|
||||
if blinkm start
|
||||
then
|
||||
echo "using BlinkM for state indication"
|
||||
blinkm systemstate
|
||||
else
|
||||
echo "no BlinkM found, OK."
|
||||
fi
|
||||
@@ -13,10 +13,10 @@ uorb start
|
||||
# Load microSD params
|
||||
#
|
||||
echo "[init] loading microSD params"
|
||||
param select /fs/microsd/parameters
|
||||
if [ -f /fs/microsd/parameters ]
|
||||
param select /fs/microsd/params
|
||||
if [ -f /fs/microsd/params ]
|
||||
then
|
||||
param load /fs/microsd/parameters
|
||||
param load /fs/microsd/params
|
||||
fi
|
||||
|
||||
#
|
||||
|
||||
@@ -17,13 +17,13 @@ echo "[init] doing PX4IOAR startup..."
|
||||
uorb start
|
||||
|
||||
#
|
||||
# Init the parameter storage
|
||||
# Load microSD params
|
||||
#
|
||||
echo "[init] loading microSD params"
|
||||
param select /fs/microsd/parameters
|
||||
if [ -f /fs/microsd/parameters ]
|
||||
param select /fs/microsd/params
|
||||
if [ -f /fs/microsd/params ]
|
||||
then
|
||||
param load /fs/microsd/parameters
|
||||
param load /fs/microsd/params
|
||||
fi
|
||||
|
||||
#
|
||||
|
||||
@@ -17,10 +17,10 @@ hil mode_pwm
|
||||
# Load microSD params
|
||||
#
|
||||
echo "[init] loading microSD params"
|
||||
param select /fs/microsd/parameters
|
||||
if [ -f /fs/microsd/parameters ]
|
||||
param select /fs/microsd/params
|
||||
if [ -f /fs/microsd/params ]
|
||||
then
|
||||
param load /fs/microsd/parameters
|
||||
param load /fs/microsd/params
|
||||
fi
|
||||
|
||||
#
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
# Start sensor drivers here.
|
||||
#
|
||||
|
||||
#
|
||||
# Check for UORB
|
||||
#
|
||||
if uorb start
|
||||
then
|
||||
echo "uORB started"
|
||||
fi
|
||||
|
||||
ms5611 start
|
||||
adc start
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Multirotor mixer for PX4FMU
|
||||
===========================
|
||||
|
||||
This file defines a single mixer for a quadrotor with a wide configuration. All controls are mixed 100%.
|
||||
|
||||
R: 4w 10000 10000 10000 0
|
||||
@@ -0,0 +1,71 @@
|
||||
PX4 Build System
|
||||
================
|
||||
|
||||
The files in this directory implement the PX4 runtime firmware build system
|
||||
and configuration for the standard PX4 boards and software, in conjunction
|
||||
with Makefile in the parent directory.
|
||||
|
||||
../Makefile
|
||||
|
||||
Top-level makefile for the PX4 build system. This makefile supports
|
||||
building NuttX archives, as well as supervising the building of all
|
||||
of the defined PX4 firmware configurations.
|
||||
|
||||
Try 'make help' in the parent directory for documentation.
|
||||
|
||||
firmware.mk
|
||||
|
||||
Manages the build for one specific firmware configuration.
|
||||
See the comments at the top of this file for detailed documentation.
|
||||
|
||||
Builds modules, builtin command lists and the ROMFS (if configured).
|
||||
|
||||
This is the makefile directly used by external build systems; it can
|
||||
be configured to compile modules both inside and outside the PX4
|
||||
source tree. When used in this mode, at least BOARD, MODULES and
|
||||
CONFIG_FILE must be set.
|
||||
|
||||
module.mk
|
||||
|
||||
Called by firmware.mk to build individual modules.
|
||||
See the comments at the top of this file for detailed documentation.
|
||||
|
||||
Not normally used other than by firmware.mk.
|
||||
|
||||
nuttx.mk
|
||||
|
||||
Called by ../Makefile to build or download the NuttX archives.
|
||||
|
||||
upload.mk
|
||||
|
||||
Called by ../Makefile to upload files to a target board. Can be used
|
||||
by external build systems as well.
|
||||
|
||||
setup.mk
|
||||
|
||||
Provides common path and tool definitions. Implements host system-specific
|
||||
compatibility hacks.
|
||||
|
||||
board_<boardname>.mk
|
||||
|
||||
Board-specific configuration for <boardname>. Typically sets CONFIG_ARCH
|
||||
and then includes the toolchain definition for the board.
|
||||
|
||||
config_<boardname>_<configname>.mk
|
||||
|
||||
Parameters for a specific configuration on a specific board.
|
||||
The board name is derived from the filename. Sets MODULES to select
|
||||
source modules to be included in the configuration, may also set
|
||||
ROMFS_ROOT to build a ROMFS and BUILTIN_COMMANDS to include non-module
|
||||
commands (e.g. from NuttX)
|
||||
|
||||
toolchain_<toolchainname>.mk
|
||||
|
||||
Provides macros used to compile and link source files.
|
||||
Accepts EXTRADEFINES to add additional pre-processor symbol definitions,
|
||||
EXTRACFLAGS, EXTRACXXFLAGS, EXTRAAFLAGS and EXTRALDFLAGS to pass
|
||||
additional flags to the C compiler, C++ compiler, assembler and linker
|
||||
respectively.
|
||||
|
||||
Defines the COMPILE, COMPILEXX, ASSEMBLE, PRELINK, ARCHIVE and LINK
|
||||
macros that are used elsewhere in the build system.
|
||||
@@ -14,6 +14,7 @@ MODULES += drivers/device
|
||||
MODULES += drivers/stm32
|
||||
MODULES += drivers/stm32/adc
|
||||
MODULES += drivers/stm32/tone_alarm
|
||||
MODULES += drivers/led
|
||||
MODULES += drivers/px4io
|
||||
MODULES += drivers/px4fmu
|
||||
MODULES += drivers/boards/px4fmu
|
||||
@@ -29,6 +30,9 @@ MODULES += drivers/gps
|
||||
MODULES += drivers/hil
|
||||
MODULES += drivers/hott_telemetry
|
||||
MODULES += drivers/blinkm
|
||||
MODULES += drivers/mkblctrl
|
||||
MODULES += drivers/md25
|
||||
MODULES += drivers/ets_airspeed
|
||||
MODULES += modules/sensors
|
||||
|
||||
#
|
||||
@@ -102,6 +106,10 @@ MODULES += modules/uORB
|
||||
# https://pixhawk.ethz.ch/px4/dev/debug_values
|
||||
#MODULES += examples/px4_mavlink_debug
|
||||
|
||||
# Tutorial code from
|
||||
# https://pixhawk.ethz.ch/px4/dev/example_fixedwing_control
|
||||
MODULES += examples/fixedwing_control
|
||||
|
||||
#
|
||||
# Transitional support - add commands from the NuttX export archive.
|
||||
#
|
||||
|
||||
+21
-14
@@ -193,7 +193,7 @@ EXTRA_CLEANS =
|
||||
# for GMSL).
|
||||
|
||||
# where to look for modules
|
||||
MODULE_SEARCH_DIRS += $(WORK_DIR) $(MODULE_SRC) $(PX4_MODULE_SRC)
|
||||
MODULE_SEARCH_DIRS += $(WORK_DIR) $(MODULE_SRC) $(PX4_MODULE_SRC)
|
||||
|
||||
# sort and unique the modules list
|
||||
MODULES := $(sort $(MODULES))
|
||||
@@ -201,9 +201,9 @@ MODULES := $(sort $(MODULES))
|
||||
# locate the first instance of a module by full path or by looking on the
|
||||
# module search path
|
||||
define MODULE_SEARCH
|
||||
$(abspath $(firstword $(wildcard $(1)/module.mk) \
|
||||
$(foreach search_dir,$(MODULE_SEARCH_DIRS),$(wildcard $(search_dir)/$(1)/module.mk)) \
|
||||
MISSING_$1))
|
||||
$(firstword $(abspath $(wildcard $(1)/module.mk)) \
|
||||
$(abspath $(foreach search_dir,$(MODULE_SEARCH_DIRS),$(wildcard $(search_dir)/$(1)/module.mk))) \
|
||||
MISSING_$1)
|
||||
endef
|
||||
|
||||
# make a list of module makefiles and check that we found them all
|
||||
@@ -223,12 +223,15 @@ MODULE_OBJS := $(foreach path,$(dir $(MODULE_MKFILES)),$(WORK_DIR)$(path)module
|
||||
.PHONY: $(MODULE_OBJS)
|
||||
$(MODULE_OBJS): relpath = $(patsubst $(WORK_DIR)%,%,$@)
|
||||
$(MODULE_OBJS): mkfile = $(patsubst %module.pre.o,%module.mk,$(relpath))
|
||||
$(MODULE_OBJS): workdir = $(@D)
|
||||
$(MODULE_OBJS): $(GLOBAL_DEPS) $(NUTTX_CONFIG_HEADER)
|
||||
$(Q) $(MKDIR) -p $(workdir)
|
||||
$(Q) $(MAKE) -r -f $(PX4_MK_DIR)module.mk \
|
||||
MODULE_WORK_DIR=$(dir $@) \
|
||||
-C $(workdir) \
|
||||
MODULE_WORK_DIR=$(workdir) \
|
||||
MODULE_OBJ=$@ \
|
||||
MODULE_MK=$(mkfile) \
|
||||
MODULE_NAME=$(lastword $(subst /, ,$(@D))) \
|
||||
MODULE_NAME=$(lastword $(subst /, ,$(workdir))) \
|
||||
module
|
||||
|
||||
# make a list of phony clean targets for modules
|
||||
@@ -266,14 +269,18 @@ endif
|
||||
#
|
||||
|
||||
# Add dependencies on anything in the ROMFS root
|
||||
ROMFS_DEPS += $(wildcard \
|
||||
(ROMFS_ROOT)/* \
|
||||
(ROMFS_ROOT)/*/* \
|
||||
(ROMFS_ROOT)/*/*/* \
|
||||
(ROMFS_ROOT)/*/*/*/* \
|
||||
(ROMFS_ROOT)/*/*/*/*/* \
|
||||
(ROMFS_ROOT)/*/*/*/*/*/*)
|
||||
ROMFS_IMG = $(WORK_DIR)romfs.img
|
||||
ROMFS_FILES += $(wildcard \
|
||||
$(ROMFS_ROOT)/* \
|
||||
$(ROMFS_ROOT)/*/* \
|
||||
$(ROMFS_ROOT)/*/*/* \
|
||||
$(ROMFS_ROOT)/*/*/*/* \
|
||||
$(ROMFS_ROOT)/*/*/*/*/* \
|
||||
$(ROMFS_ROOT)/*/*/*/*/*/*)
|
||||
ifeq ($(ROMFS_FILES),)
|
||||
$(error ROMFS_ROOT $(ROMFS_ROOT) specifies a directory containing no files)
|
||||
endif
|
||||
ROMFS_DEPS += $(ROMFS_FILES)
|
||||
ROMFS_IMG = romfs.img
|
||||
ROMFS_CSRC = $(ROMFS_IMG:.img=.c)
|
||||
ROMFS_OBJ = $(ROMFS_CSRC:.c=.o)
|
||||
LIBS += $(ROMFS_OBJ)
|
||||
|
||||
+31
-20
@@ -39,6 +39,10 @@
|
||||
# symbols, as the global namespace is shared between all modules. Normally an
|
||||
# module will just export one or more <command>_main functions.
|
||||
#
|
||||
# IMPORTANT NOTE:
|
||||
#
|
||||
# This makefile assumes it is being invoked in the module's output directory.
|
||||
#
|
||||
|
||||
#
|
||||
# Variables that can be set by the module's module.mk:
|
||||
@@ -179,26 +183,30 @@ CXXFLAGS += -fvisibility=$(DEFAULT_VISIBILITY) -include $(PX4_INCLUDE_DIR)visibi
|
||||
#
|
||||
module: $(MODULE_OBJ) $(MODULE_COMMAND_FILES)
|
||||
|
||||
##
|
||||
## Locate sources (allows relative source paths in module.mk)
|
||||
##
|
||||
#define SRC_SEARCH
|
||||
# $(abspath $(firstword $(wildcard $1) $(wildcard $(MODULE_SRC)/$1) MISSING_$1))
|
||||
#endef
|
||||
#
|
||||
# Locate sources (allows relative source paths in module.mk)
|
||||
#ABS_SRCS ?= $(foreach src,$(SRCS),$(call SRC_SEARCH,$(src)))
|
||||
#MISSING_SRCS := $(subst MISSING_,,$(filter MISSING_%,$(ABS_SRCS)))
|
||||
#ifneq ($(MISSING_SRCS),)
|
||||
#$(error $(MODULE_MK): missing in SRCS: $(MISSING_SRCS))
|
||||
#endif
|
||||
#ifeq ($(ABS_SRCS),)
|
||||
#$(error $(MODULE_MK): nothing to compile in SRCS)
|
||||
#endif
|
||||
#
|
||||
define SRC_SEARCH
|
||||
$(abspath $(firstword $(wildcard $(MODULE_SRC)/$1) MISSING_$1))
|
||||
endef
|
||||
##
|
||||
## Object files we will generate from sources
|
||||
##
|
||||
#OBJS := $(foreach src,$(ABS_SRCS),$(MODULE_WORK_DIR)$(src).o)
|
||||
|
||||
ABS_SRCS ?= $(foreach src,$(SRCS),$(call SRC_SEARCH,$(src)))
|
||||
MISSING_SRCS := $(subst MISSING_,,$(filter MISSING_%,$(ABS_SRCS)))
|
||||
ifneq ($(MISSING_SRCS),)
|
||||
$(error $(MODULE_MK): missing in SRCS: $(MISSING_SRCS))
|
||||
endif
|
||||
ifeq ($(ABS_SRCS),)
|
||||
$(error $(MODULE_MK): nothing to compile in SRCS)
|
||||
endif
|
||||
|
||||
#
|
||||
# Object files we will generate from sources
|
||||
#
|
||||
OBJS := $(foreach src,$(ABS_SRCS),$(MODULE_WORK_DIR)$(src).o)
|
||||
OBJS = $(addsuffix .o,$(SRCS))
|
||||
$(info SRCS $(SRCS))
|
||||
$(info OBJS $(OBJS))
|
||||
|
||||
#
|
||||
# SRCS -> OBJS rules
|
||||
@@ -206,13 +214,16 @@ OBJS := $(foreach src,$(ABS_SRCS),$(MODULE_WORK_DIR)$(src).o)
|
||||
|
||||
$(OBJS): $(GLOBAL_DEPS)
|
||||
|
||||
$(filter %.c.o,$(OBJS)): $(MODULE_WORK_DIR)%.c.o: %.c $(GLOBAL_DEPS)
|
||||
vpath %.c $(MODULE_SRC)
|
||||
$(filter %.c.o,$(OBJS)): %.c.o: %.c $(GLOBAL_DEPS)
|
||||
$(call COMPILE,$<,$@)
|
||||
|
||||
$(filter %.cpp.o,$(OBJS)): $(MODULE_WORK_DIR)%.cpp.o: %.cpp $(GLOBAL_DEPS)
|
||||
vpath %.cpp $(MODULE_SRC)
|
||||
$(filter %.cpp.o,$(OBJS)): %.cpp.o: %.cpp $(GLOBAL_DEPS)
|
||||
$(call COMPILEXX,$<,$@)
|
||||
|
||||
$(filter %.S.o,$(OBJS)): $(MODULE_WORK_DIR)%.S.o: %.S $(GLOBAL_DEPS)
|
||||
vpath %.S $(MODULE_SRC)
|
||||
$(filter %.S.o,$(OBJS)): %.S.o: %.S $(GLOBAL_DEPS)
|
||||
$(call ASSEMBLE,$<,$@)
|
||||
|
||||
#
|
||||
|
||||
@@ -144,6 +144,7 @@ CFLAGS = $(ARCHCFLAGS) \
|
||||
$(INSTRUMENTATIONDEFINES) \
|
||||
$(ARCHDEFINES) \
|
||||
$(EXTRADEFINES) \
|
||||
$(EXTRACFLAGS) \
|
||||
-fno-common \
|
||||
$(addprefix -I,$(INCLUDE_DIRS))
|
||||
|
||||
@@ -156,18 +157,22 @@ CXXFLAGS = $(ARCHCXXFLAGS) \
|
||||
$(ARCHXXINCLUDES) \
|
||||
$(INSTRUMENTATIONDEFINES) \
|
||||
$(ARCHDEFINES) \
|
||||
$(EXTRADEFINES) \
|
||||
-DCONFIG_WCHAR_BUILTIN \
|
||||
$(EXTRADEFINES) \
|
||||
$(EXTRACXXFLAGS) \
|
||||
$(addprefix -I,$(INCLUDE_DIRS))
|
||||
|
||||
# Flags we pass to the assembler
|
||||
#
|
||||
AFLAGS = $(CFLAGS) -D__ASSEMBLY__
|
||||
AFLAGS = $(CFLAGS) -D__ASSEMBLY__ \
|
||||
$(EXTRADEFINES) \
|
||||
$(EXTRAAFLAGS)
|
||||
|
||||
# Flags we pass to the linker
|
||||
#
|
||||
LDFLAGS += --warn-common \
|
||||
--gc-sections \
|
||||
$(EXTRALDFLAGS) \
|
||||
$(addprefix -T,$(LDSCRIPT)) \
|
||||
$(addprefix -L,$(LIB_DIRS))
|
||||
|
||||
@@ -249,6 +254,20 @@ endef
|
||||
# - relink the object and insert the binary file
|
||||
# - edit symbol names to suit
|
||||
#
|
||||
# NOTE: exercise caution using this with absolute pathnames; it looks
|
||||
# like the MinGW tools insert an extra _ in the binary symbol name; e.g.
|
||||
# the path:
|
||||
#
|
||||
# /d/px4/firmware/Build/px4fmu_default.build/romfs.img
|
||||
#
|
||||
# is assigned symbols like:
|
||||
#
|
||||
# _binary_d__px4_firmware_Build_px4fmu_default_build_romfs_img_size
|
||||
#
|
||||
# when we would expect
|
||||
#
|
||||
# _binary__d_px4_firmware_Build_px4fmu_default_build_romfs_img_size
|
||||
#
|
||||
define BIN_SYM_PREFIX
|
||||
_binary_$(subst /,_,$(subst .,_,$1))
|
||||
endef
|
||||
@@ -262,4 +281,5 @@ define BIN_TO_OBJ
|
||||
--redefine-sym $(call BIN_SYM_PREFIX,$1)_start=$3 \
|
||||
--redefine-sym $(call BIN_SYM_PREFIX,$1)_size=$3_len \
|
||||
--strip-symbol $(call BIN_SYM_PREFIX,$1)_end
|
||||
$(Q) $(REMOVE) $2.c $2.c.o
|
||||
endef
|
||||
|
||||
@@ -30,9 +30,6 @@ upload-serial-px4fmu: $(BUNDLE) $(UPLOADER)
|
||||
upload-serial-px4fmuv2: $(BUNDLE) $(UPLOADER)
|
||||
$(Q) $(PYTHON) -u $(UPLOADER) --port $(SERIAL_PORTS) $(BUNDLE)
|
||||
|
||||
upload-serial-px4fmuv2: $(BUNDLE) $(UPLOADER)
|
||||
@python -u $(UPLOADER) --port $(SERIAL_PORTS) $(BUNDLE)
|
||||
|
||||
#
|
||||
# JTAG firmware uploading with OpenOCD
|
||||
#
|
||||
|
||||
@@ -1512,7 +1512,6 @@ static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt)
|
||||
|
||||
DEBUGASSERT(privep && privep->ep.priv);
|
||||
priv = (FAR struct stm32_usbdev_s *)privep->ep.priv;
|
||||
DEBUGASSERT(priv->ep0state == EP0STATE_SETUP_OUT);
|
||||
|
||||
ullvdbg("EP0: bcnt=%d\n", bcnt);
|
||||
usbtrace(TRACE_READ(EP0), bcnt);
|
||||
|
||||
@@ -647,10 +647,14 @@ CONFIG_DISABLE_POLL=n
|
||||
# CONFIG_LIBC_FIXEDPRECISION - Sets 7 digits after dot for printing:
|
||||
# 5.1234567
|
||||
# CONFIG_HAVE_LONG_LONG - Enabled printf("%llu)
|
||||
# CONFIG_LIBC_STRERR - allow printing of error text
|
||||
# CONFIG_LIBC_STRERR_SHORT - allow printing of short error text
|
||||
#
|
||||
CONFIG_NOPRINTF_FIELDWIDTH=n
|
||||
CONFIG_LIBC_FLOATINGPOINT=y
|
||||
CONFIG_HAVE_LONG_LONG=y
|
||||
CONFIG_LIBC_STRERROR=n
|
||||
CONFIG_LIBC_STRERROR_SHORT=n
|
||||
|
||||
#
|
||||
# Allow for architecture optimized implementations
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
#include <math.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@@ -104,6 +105,13 @@ static void zeroes(FAR struct lib_outstream_s *obj, int nzeroes)
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void lib_dtoa_string(FAR struct lib_outstream_s *obj, const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
obj->put(obj, *str++);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_dtoa
|
||||
*
|
||||
@@ -137,9 +145,23 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
||||
int nchars; /* Number of characters to print */
|
||||
int dsgn; /* Unused sign indicator */
|
||||
int i;
|
||||
bool done_decimal_point = false;
|
||||
|
||||
/* special handling for NaN and Infinity */
|
||||
if (isnan(value)) {
|
||||
lib_dtoa_string(obj, "NaN");
|
||||
return;
|
||||
}
|
||||
if (isinf(value)) {
|
||||
if (value < 0.0d) {
|
||||
obj->put(obj, '-');
|
||||
}
|
||||
lib_dtoa_string(obj, "Infinity");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Non-zero... positive or negative */
|
||||
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
value = -value;
|
||||
@@ -178,6 +200,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
||||
if (prec > 0 || IS_ALTFORM(flags))
|
||||
{
|
||||
obj->put(obj, '.');
|
||||
done_decimal_point = true;
|
||||
|
||||
/* Always print at least one digit to the right of the decimal point. */
|
||||
|
||||
@@ -203,6 +226,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
||||
/* Print the decimal point */
|
||||
|
||||
obj->put(obj, '.');
|
||||
done_decimal_point = true;
|
||||
|
||||
/* Print any leading zeros to the right of the decimal point */
|
||||
|
||||
@@ -249,6 +273,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
||||
/* Print the decimal point */
|
||||
|
||||
obj->put(obj, '.');
|
||||
done_decimal_point = true;
|
||||
|
||||
/* Always print at least one digit to the right of the decimal
|
||||
* point.
|
||||
@@ -285,8 +310,9 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
||||
}
|
||||
|
||||
/* Finally, print any trailing zeroes */
|
||||
|
||||
zeroes(obj, prec);
|
||||
if (done_decimal_point) {
|
||||
zeroes(obj, prec);
|
||||
}
|
||||
|
||||
/* Is this memory supposed to be freed or not? */
|
||||
|
||||
|
||||
@@ -1215,7 +1215,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
|
||||
fmt = FMT_RJUST;
|
||||
width = 0;
|
||||
#ifdef CONFIG_LIBC_FLOATINGPOINT
|
||||
trunc = 0;
|
||||
trunc = 6;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1245,6 +1245,11 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
|
||||
{
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
fmt = FMT_RJUST0;
|
||||
#ifdef CONFIG_LIBC_FLOATINGPOINT
|
||||
if (IS_HASDOT(flags)) {
|
||||
trunc = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
|
||||
@@ -482,10 +482,10 @@ void ardrone_mixing_and_output(int ardrone_write, const struct actuator_controls
|
||||
motor_pwm[3] = (motor_pwm[3] > 0) ? motor_pwm[3] : 10;
|
||||
|
||||
/* Failsafe logic - should never be necessary */
|
||||
motor_pwm[0] = (motor_pwm[0] <= 512) ? motor_pwm[0] : 512;
|
||||
motor_pwm[1] = (motor_pwm[1] <= 512) ? motor_pwm[1] : 512;
|
||||
motor_pwm[2] = (motor_pwm[2] <= 512) ? motor_pwm[2] : 512;
|
||||
motor_pwm[3] = (motor_pwm[3] <= 512) ? motor_pwm[3] : 512;
|
||||
motor_pwm[0] = (motor_pwm[0] <= 511) ? motor_pwm[0] : 511;
|
||||
motor_pwm[1] = (motor_pwm[1] <= 511) ? motor_pwm[1] : 511;
|
||||
motor_pwm[2] = (motor_pwm[2] <= 511) ? motor_pwm[2] : 511;
|
||||
motor_pwm[3] = (motor_pwm[3] <= 511) ? motor_pwm[3] : 511;
|
||||
|
||||
/* send motors via UART */
|
||||
ardrone_write_motor_commands(ardrone_write, motor_pwm[0], motor_pwm[1], motor_pwm[2], motor_pwm[3]);
|
||||
|
||||
@@ -6,4 +6,5 @@ SRCS = px4fmu_can.c \
|
||||
px4fmu_init.c \
|
||||
px4fmu_pwm_servo.c \
|
||||
px4fmu_spi.c \
|
||||
px4fmu_usb.c
|
||||
px4fmu_usb.c \
|
||||
px4fmu_led.c
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -91,6 +91,19 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ideally we'd be able to get these from up_internal.h,
|
||||
* but since we want to be able to disable the NuttX use
|
||||
* of leds for system indication at will and there is no
|
||||
* separate switch, we need to build independent of the
|
||||
* CONFIG_ARCH_LEDS configuration switch.
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
extern void led_init();
|
||||
extern void led_on(int led);
|
||||
extern void led_off(int led);
|
||||
__END_DECLS
|
||||
|
||||
/****************************************************************************
|
||||
* Protected Functions
|
||||
****************************************************************************/
|
||||
@@ -114,7 +127,7 @@ __EXPORT void stm32_boardinitialize(void)
|
||||
/* configure SPI interfaces */
|
||||
stm32_spiinitialize();
|
||||
|
||||
/* configure LEDs */
|
||||
/* configure LEDs (empty call to NuttX' ledinit) */
|
||||
up_ledinit();
|
||||
}
|
||||
|
||||
@@ -178,11 +191,11 @@ __EXPORT int nsh_archinitialize(void)
|
||||
(hrt_callout)stm32_serial_dma_poll,
|
||||
NULL);
|
||||
|
||||
// initial LED state
|
||||
// drv_led_start();
|
||||
up_ledoff(LED_BLUE);
|
||||
up_ledoff(LED_AMBER);
|
||||
up_ledon(LED_BLUE);
|
||||
/* initial LED state */
|
||||
drv_led_start();
|
||||
led_off(LED_AMBER);
|
||||
led_on(LED_BLUE);
|
||||
|
||||
|
||||
/* Configure SPI-based devices */
|
||||
|
||||
|
||||
@@ -39,19 +39,27 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "up_arch.h"
|
||||
#include "up_internal.h"
|
||||
#include "stm32_internal.h"
|
||||
#include "px4fmu_internal.h"
|
||||
|
||||
__EXPORT void up_ledinit()
|
||||
#include <arch/board/board.h>
|
||||
|
||||
/*
|
||||
* Ideally we'd be able to get these from up_internal.h,
|
||||
* but since we want to be able to disable the NuttX use
|
||||
* of leds for system indication at will and there is no
|
||||
* separate switch, we need to build independent of the
|
||||
* CONFIG_ARCH_LEDS configuration switch.
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
extern void led_init();
|
||||
extern void led_on(int led);
|
||||
extern void led_off(int led);
|
||||
__END_DECLS
|
||||
|
||||
__EXPORT void led_init()
|
||||
{
|
||||
/* Configure LED1-2 GPIOs for output */
|
||||
|
||||
@@ -59,7 +67,7 @@ __EXPORT void up_ledinit()
|
||||
stm32_configgpio(GPIO_LED2);
|
||||
}
|
||||
|
||||
__EXPORT void up_ledon(int led)
|
||||
__EXPORT void led_on(int led)
|
||||
{
|
||||
if (led == 0)
|
||||
{
|
||||
@@ -73,7 +81,7 @@ __EXPORT void up_ledon(int led)
|
||||
}
|
||||
}
|
||||
|
||||
__EXPORT void up_ledoff(int led)
|
||||
__EXPORT void led_off(int led)
|
||||
{
|
||||
if (led == 0)
|
||||
{
|
||||
|
||||
@@ -53,6 +53,15 @@ namespace device __EXPORT
|
||||
class __EXPORT I2C : public CDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*/
|
||||
uint16_t get_address() {
|
||||
return _address;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The number of times a read or write operation will be retried on
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Airspeed driver interface.
|
||||
* @author Simon Wilks
|
||||
*/
|
||||
|
||||
#ifndef _DRV_AIRSPEED_H
|
||||
#define _DRV_AIRSPEED_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "drv_sensor.h"
|
||||
#include "drv_orb_dev.h"
|
||||
|
||||
#define AIRSPEED_DEVICE_PATH "/dev/airspeed"
|
||||
|
||||
/*
|
||||
* ioctl() definitions
|
||||
*
|
||||
* Airspeed drivers also implement the generic sensor driver
|
||||
* interfaces from drv_sensor.h
|
||||
*/
|
||||
|
||||
#define _AIRSPEEDIOCBASE (0x7700)
|
||||
#define __AIRSPEEDIOC(_n) (_IOC(_AIRSPEEDIOCBASE, _n))
|
||||
|
||||
|
||||
#endif /* _DRV_AIRSPEED_H */
|
||||
@@ -109,6 +109,12 @@ ORB_DECLARE(output_pwm);
|
||||
/** selects servo update rates, one bit per servo. 0 = default (50Hz), 1 = alternate */
|
||||
#define PWM_SERVO_SELECT_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 4)
|
||||
|
||||
/** set the 'ARM ok' bit, which activates the safety switch */
|
||||
#define PWM_SERVO_SET_ARM_OK _IOC(_PWM_SERVO_BASE, 5)
|
||||
|
||||
/** clear the 'ARM ok' bit, which deactivates the safety switch */
|
||||
#define PWM_SERVO_CLEAR_ARM_OK _IOC(_PWM_SERVO_BASE, 6)
|
||||
|
||||
/** set a single servo to a specific value */
|
||||
#define PWM_SERVO_SET(_servo) _IOC(_PWM_SERVO_BASE, 0x20 + _servo)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Makefile to build the Eagle Tree Airspeed V3 driver.
|
||||
#
|
||||
|
||||
MODULE_COMMAND = ets_airspeed
|
||||
MODULE_STACKSIZE = 1024
|
||||
|
||||
SRCS = ets_airspeed.cpp
|
||||
+10
-1
@@ -285,6 +285,10 @@ GPS::task_main()
|
||||
unlock();
|
||||
if (_Helper->configure(_baudrate) == 0) {
|
||||
unlock();
|
||||
|
||||
// GPS is obviously detected successfully, reset statistics
|
||||
_Helper->reset_update_rates();
|
||||
|
||||
while (_Helper->receive(TIMEOUT_5HZ) > 0 && !_task_should_exit) {
|
||||
// lock();
|
||||
/* opportunistic publishing - else invalid data would end up on the bus */
|
||||
@@ -301,6 +305,8 @@ GPS::task_main()
|
||||
_rate = last_rate_count / ((float)((hrt_absolute_time() - last_rate_measurement)) / 1000000.0f);
|
||||
last_rate_measurement = hrt_absolute_time();
|
||||
last_rate_count = 0;
|
||||
_Helper->store_update_rates();
|
||||
_Helper->reset_update_rates();
|
||||
}
|
||||
|
||||
if (!_healthy) {
|
||||
@@ -372,7 +378,10 @@ GPS::print_info()
|
||||
warnx("position lock: %dD, last update %4.2f seconds ago", (int)_report.fix_type,
|
||||
(double)((float)(hrt_absolute_time() - _report.timestamp_position) / 1000000.0f));
|
||||
warnx("lat: %d, lon: %d, alt: %d", _report.lat, _report.lon, _report.alt);
|
||||
warnx("update rate: %6.2f Hz", (double)_rate);
|
||||
warnx("rate position: \t%6.2f Hz", (double)_Helper->get_position_update_rate());
|
||||
warnx("rate velocity: \t%6.2f Hz", (double)_Helper->get_velocity_update_rate());
|
||||
warnx("rate publication:\t%6.2f Hz", (double)_rate);
|
||||
|
||||
}
|
||||
|
||||
usleep(100000);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
|
||||
* Copyright (C) 2012,2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
*
|
||||
@@ -36,9 +36,39 @@
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include "gps_helper.h"
|
||||
|
||||
/* @file gps_helper.cpp */
|
||||
/**
|
||||
* @file gps_helper.cpp
|
||||
*/
|
||||
|
||||
float
|
||||
GPS_Helper::get_position_update_rate()
|
||||
{
|
||||
return _rate_lat_lon;
|
||||
}
|
||||
|
||||
float
|
||||
GPS_Helper::get_velocity_update_rate()
|
||||
{
|
||||
return _rate_vel;
|
||||
}
|
||||
|
||||
float
|
||||
GPS_Helper::reset_update_rates()
|
||||
{
|
||||
_rate_count_vel = 0;
|
||||
_rate_count_lat_lon = 0;
|
||||
_interval_rate_start = hrt_absolute_time();
|
||||
}
|
||||
|
||||
float
|
||||
GPS_Helper::store_update_rates()
|
||||
{
|
||||
_rate_vel = _rate_count_vel / (((float)(hrt_absolute_time() - _interval_rate_start)) / 1000000.0f);
|
||||
_rate_lat_lon = _rate_count_lat_lon / (((float)(hrt_absolute_time() - _interval_rate_start)) / 1000000.0f);
|
||||
}
|
||||
|
||||
int
|
||||
GPS_Helper::set_baudrate(const int &fd, unsigned baud)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
*
|
||||
@@ -33,7 +33,9 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* @file gps_helper.h */
|
||||
/**
|
||||
* @file gps_helper.h
|
||||
*/
|
||||
|
||||
#ifndef GPS_HELPER_H
|
||||
#define GPS_HELPER_H
|
||||
@@ -44,9 +46,22 @@
|
||||
class GPS_Helper
|
||||
{
|
||||
public:
|
||||
virtual int configure(unsigned &baud) = 0;
|
||||
virtual int configure(unsigned &baud) = 0;
|
||||
virtual int receive(unsigned timeout) = 0;
|
||||
int set_baudrate(const int &fd, unsigned baud);
|
||||
int set_baudrate(const int &fd, unsigned baud);
|
||||
float get_position_update_rate();
|
||||
float get_velocity_update_rate();
|
||||
float reset_update_rates();
|
||||
float store_update_rates();
|
||||
|
||||
protected:
|
||||
uint8_t _rate_count_lat_lon;
|
||||
uint8_t _rate_count_vel;
|
||||
|
||||
float _rate_lat_lon;
|
||||
float _rate_vel;
|
||||
|
||||
uint64_t _interval_rate_start;
|
||||
};
|
||||
|
||||
#endif /* GPS_HELPER_H */
|
||||
|
||||
@@ -263,6 +263,10 @@ MTK::handle_message(gps_mtk_packet_t &packet)
|
||||
_gps_position->time_gps_usec += timeinfo_conversion_temp * 1e3;
|
||||
_gps_position->timestamp_position = _gps_position->timestamp_time = hrt_absolute_time();
|
||||
|
||||
// Position and velocity update always at the same time
|
||||
_rate_count_vel++;
|
||||
_rate_count_lat_lon++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,14 +87,14 @@ class MTK : public GPS_Helper
|
||||
public:
|
||||
MTK(const int &fd, struct vehicle_gps_position_s *gps_position);
|
||||
~MTK();
|
||||
int receive(unsigned timeout);
|
||||
int configure(unsigned &baudrate);
|
||||
int receive(unsigned timeout);
|
||||
int configure(unsigned &baudrate);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Parse the binary MTK packet
|
||||
*/
|
||||
int parse_char(uint8_t b, gps_mtk_packet_t &packet);
|
||||
int parse_char(uint8_t b, gps_mtk_packet_t &packet);
|
||||
|
||||
/**
|
||||
* Handle the package once it has arrived
|
||||
|
||||
+97
-67
@@ -60,7 +60,8 @@
|
||||
UBX::UBX(const int &fd, struct vehicle_gps_position_s *gps_position) :
|
||||
_fd(fd),
|
||||
_gps_position(gps_position),
|
||||
_waiting_for_ack(false)
|
||||
_waiting_for_ack(false),
|
||||
_disable_cmd_counter(0)
|
||||
{
|
||||
decode_init();
|
||||
}
|
||||
@@ -139,12 +140,12 @@ UBX::configure(unsigned &baudrate)
|
||||
cfg_rate_packet.clsID = UBX_CLASS_CFG;
|
||||
cfg_rate_packet.msgID = UBX_MESSAGE_CFG_RATE;
|
||||
cfg_rate_packet.length = UBX_CFG_RATE_LENGTH;
|
||||
cfg_rate_packet.measRate = UBX_CFG_RATE_PAYLOAD_MEASRATE;
|
||||
cfg_rate_packet.measRate = UBX_CFG_RATE_PAYLOAD_MEASINTERVAL;
|
||||
cfg_rate_packet.navRate = UBX_CFG_RATE_PAYLOAD_NAVRATE;
|
||||
cfg_rate_packet.timeRef = UBX_CFG_RATE_PAYLOAD_TIMEREF;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_rate_packet, sizeof(cfg_rate_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
@@ -164,74 +165,41 @@ UBX::configure(unsigned &baudrate)
|
||||
cfg_nav5_packet.fixMode = UBX_CFG_NAV5_PAYLOAD_FIXMODE;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_nav5_packet, sizeof(cfg_nav5_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
|
||||
type_gps_bin_cfg_msg_packet_t cfg_msg_packet;
|
||||
memset(&cfg_msg_packet, 0, sizeof(cfg_msg_packet));
|
||||
|
||||
_clsID_needed = UBX_CLASS_CFG;
|
||||
_msgID_needed = UBX_MESSAGE_CFG_MSG;
|
||||
|
||||
cfg_msg_packet.clsID = UBX_CLASS_CFG;
|
||||
cfg_msg_packet.msgID = UBX_MESSAGE_CFG_MSG;
|
||||
cfg_msg_packet.length = UBX_CFG_MSG_LENGTH;
|
||||
/* Choose fast 5Hz rate for all messages except SVINFO which is big and not important */
|
||||
cfg_msg_packet.rate[1] = UBX_CFG_MSG_PAYLOAD_RATE1_5HZ;
|
||||
|
||||
cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
|
||||
cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_POSLLH;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
|
||||
cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_TIMEUTC;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
|
||||
cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_SVINFO;
|
||||
/* For satelites info 1Hz is enough */
|
||||
cfg_msg_packet.rate[1] = UBX_CFG_MSG_PAYLOAD_RATE1_1HZ;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
|
||||
cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_SOL;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
|
||||
cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_VELNED;
|
||||
|
||||
send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
|
||||
if (receive(UBX_CONFIG_TIMEOUT) < 0) {
|
||||
/* try next baudrate */
|
||||
continue;
|
||||
}
|
||||
// cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
|
||||
// cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_DOP;
|
||||
|
||||
// cfg_msg_packet.msgClass_payload = UBX_CLASS_RXM;
|
||||
// cfg_msg_packet.msgID_payload = UBX_MESSAGE_RXM_SVSI;
|
||||
configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_POSLLH,
|
||||
UBX_CFG_MSG_PAYLOAD_RATE1_5HZ);
|
||||
/* insist of receiving the ACK for this packet */
|
||||
// if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
|
||||
// continue;
|
||||
configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_TIMEUTC,
|
||||
1);
|
||||
// /* insist of receiving the ACK for this packet */
|
||||
// if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
|
||||
// continue;
|
||||
configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_SOL,
|
||||
1);
|
||||
// /* insist of receiving the ACK for this packet */
|
||||
// if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
|
||||
// continue;
|
||||
configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_VELNED,
|
||||
1);
|
||||
// /* insist of receiving the ACK for this packet */
|
||||
// if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
|
||||
// continue;
|
||||
// configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_DOP,
|
||||
// 0);
|
||||
// /* insist of receiving the ACK for this packet */
|
||||
// if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
|
||||
// continue;
|
||||
configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_SVINFO,
|
||||
0);
|
||||
// /* insist of receiving the ACK for this packet */
|
||||
// if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
|
||||
// continue;
|
||||
|
||||
_waiting_for_ack = false;
|
||||
return 0;
|
||||
@@ -239,6 +207,15 @@ UBX::configure(unsigned &baudrate)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
UBX::wait_for_ack(unsigned timeout)
|
||||
{
|
||||
_waiting_for_ack = true;
|
||||
int ret = receive(timeout);
|
||||
_waiting_for_ack = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
UBX::receive(unsigned timeout)
|
||||
{
|
||||
@@ -498,6 +475,8 @@ UBX::handle_message()
|
||||
_gps_position->eph_m = (float)packet->hAcc * 1e-3f; // from mm to m
|
||||
_gps_position->epv_m = (float)packet->vAcc * 1e-3f; // from mm to m
|
||||
|
||||
_rate_count_lat_lon++;
|
||||
|
||||
/* Add timestamp to finish the report */
|
||||
_gps_position->timestamp_position = hrt_absolute_time();
|
||||
/* only return 1 when new position is available */
|
||||
@@ -653,6 +632,8 @@ UBX::handle_message()
|
||||
_gps_position->c_variance_rad = (float)packet->cAcc * M_DEG_TO_RAD_F * 1e-5f;
|
||||
_gps_position->vel_ned_valid = true;
|
||||
_gps_position->timestamp_velocity = hrt_absolute_time();
|
||||
|
||||
_rate_count_vel++;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -693,6 +674,12 @@ UBX::handle_message()
|
||||
|
||||
default: //we don't know the message
|
||||
warnx("UBX: Unknown message received: %d-%d\n",_message_class,_message_id);
|
||||
if (_disable_cmd_counter++ == 0) {
|
||||
// Don't attempt for every message to disable, some might not be disabled */
|
||||
warnx("Disabling message 0x%02x 0x%02x", (unsigned)_message_class, (unsigned)_message_id);
|
||||
configure_message_rate(_message_class, _message_id, 0);
|
||||
}
|
||||
return ret;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
@@ -736,6 +723,25 @@ UBX::add_checksum_to_message(uint8_t* message, const unsigned length)
|
||||
message[length-1] = ck_b;
|
||||
}
|
||||
|
||||
void
|
||||
UBX::add_checksum(uint8_t* message, const unsigned length, uint8_t &ck_a, uint8_t &ck_b)
|
||||
{
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
ck_a = ck_a + message[i];
|
||||
ck_b = ck_b + ck_a;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UBX::configure_message_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate)
|
||||
{
|
||||
struct ubx_cfg_msg_rate msg;
|
||||
msg.msg_class = msg_class;
|
||||
msg.msg_id = msg_id;
|
||||
msg.rate = rate;
|
||||
send_message(CFG, UBX_MESSAGE_CFG_MSG, &msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void
|
||||
UBX::send_config_packet(const int &fd, uint8_t *packet, const unsigned length)
|
||||
{
|
||||
@@ -753,3 +759,27 @@ UBX::send_config_packet(const int &fd, uint8_t *packet, const unsigned length)
|
||||
if (ret != (int)length + (int)sizeof(sync_bytes)) // XXX is there a neater way to get rid of the unsigned signed warning?
|
||||
warnx("ubx: config write fail");
|
||||
}
|
||||
|
||||
void
|
||||
UBX::send_message(uint8_t msg_class, uint8_t msg_id, void *msg, uint8_t size)
|
||||
{
|
||||
struct ubx_header header;
|
||||
uint8_t ck_a=0, ck_b=0;
|
||||
header.sync1 = UBX_SYNC1;
|
||||
header.sync2 = UBX_SYNC2;
|
||||
header.msg_class = msg_class;
|
||||
header.msg_id = msg_id;
|
||||
header.length = size;
|
||||
|
||||
add_checksum((uint8_t *)&header.msg_class, sizeof(header)-2, ck_a, ck_b);
|
||||
add_checksum((uint8_t *)msg, size, ck_a, ck_b);
|
||||
|
||||
// Configure receive check
|
||||
_clsID_needed = msg_class;
|
||||
_msgID_needed = msg_id;
|
||||
|
||||
write(_fd, (const char *)&header, sizeof(header));
|
||||
write(_fd, (const char *)msg, size);
|
||||
write(_fd, (const char *)&ck_a, 1);
|
||||
write(_fd, (const char *)&ck_b, 1);
|
||||
}
|
||||
|
||||
+51
-27
@@ -65,26 +65,27 @@
|
||||
#define UBX_MESSAGE_CFG_RATE 0x08
|
||||
|
||||
#define UBX_CFG_PRT_LENGTH 20
|
||||
#define UBX_CFG_PRT_PAYLOAD_PORTID 0x01 /**< UART1 */
|
||||
#define UBX_CFG_PRT_PAYLOAD_MODE 0x000008D0 /**< 0b0000100011010000: 8N1 */
|
||||
#define UBX_CFG_PRT_PAYLOAD_BAUDRATE 38400 /**< always choose 38400 as GPS baudrate */
|
||||
#define UBX_CFG_PRT_PAYLOAD_INPROTOMASK 0x01 /**< UBX in */
|
||||
#define UBX_CFG_PRT_PAYLOAD_OUTPROTOMASK 0x01 /**< UBX out */
|
||||
#define UBX_CFG_PRT_PAYLOAD_PORTID 0x01 /**< UART1 */
|
||||
#define UBX_CFG_PRT_PAYLOAD_MODE 0x000008D0 /**< 0b0000100011010000: 8N1 */
|
||||
#define UBX_CFG_PRT_PAYLOAD_BAUDRATE 38400 /**< always choose 38400 as GPS baudrate */
|
||||
#define UBX_CFG_PRT_PAYLOAD_INPROTOMASK 0x01 /**< UBX in */
|
||||
#define UBX_CFG_PRT_PAYLOAD_OUTPROTOMASK 0x01 /**< UBX out */
|
||||
|
||||
#define UBX_CFG_RATE_LENGTH 6
|
||||
#define UBX_CFG_RATE_PAYLOAD_MEASRATE 200 /**< 200ms for 5Hz */
|
||||
#define UBX_CFG_RATE_PAYLOAD_MEASINTERVAL 200 /**< 200ms for 5Hz */
|
||||
#define UBX_CFG_RATE_PAYLOAD_NAVRATE 1 /**< cannot be changed */
|
||||
#define UBX_CFG_RATE_PAYLOAD_TIMEREF 0 /**< 0: UTC, 1: GPS time */
|
||||
|
||||
|
||||
#define UBX_CFG_NAV5_LENGTH 36
|
||||
#define UBX_CFG_NAV5_PAYLOAD_MASK 0x0001 /**< only update dynamic model and fix mode */
|
||||
#define UBX_CFG_NAV5_PAYLOAD_MASK 0x0005 /**< XXX only update dynamic model and fix mode */
|
||||
#define UBX_CFG_NAV5_PAYLOAD_DYNMODEL 7 /**< 0: portable, 2: stationary, 3: pedestrian, 4: automotive, 5: sea, 6: airborne <1g, 7: airborne <2g, 8: airborne <4g */
|
||||
#define UBX_CFG_NAV5_PAYLOAD_FIXMODE 2 /**< 1: 2D only, 2: 3D only, 3: Auto 2D/3D */
|
||||
#define UBX_CFG_NAV5_PAYLOAD_FIXMODE 2 /**< 1: 2D only, 2: 3D only, 3: Auto 2D/3D */
|
||||
|
||||
#define UBX_CFG_MSG_LENGTH 8
|
||||
#define UBX_CFG_MSG_PAYLOAD_RATE1_5HZ 0x01 /**< {0x00, 0x01, 0x00, 0x00, 0x00, 0x00} the second entry is for UART1 */
|
||||
#define UBX_CFG_MSG_PAYLOAD_RATE1_1HZ 0x05 /**< {0x00, 0x05, 0x00, 0x00, 0x00, 0x00} the second entry is for UART1 */
|
||||
#define UBX_CFG_MSG_PAYLOAD_RATE1_05HZ 10
|
||||
|
||||
#define UBX_MAX_PAYLOAD_LENGTH 500
|
||||
|
||||
@@ -92,6 +93,14 @@
|
||||
/** the structures of the binary packets */
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct ubx_header {
|
||||
uint8_t sync1;
|
||||
uint8_t sync2;
|
||||
uint8_t msg_class;
|
||||
uint8_t msg_id;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t time_milliseconds; /**< GPS Millisecond Time of Week */
|
||||
int32_t lon; /**< Longitude * 1e-7, deg */
|
||||
@@ -274,11 +283,17 @@ typedef struct {
|
||||
uint16_t length;
|
||||
uint8_t msgClass_payload;
|
||||
uint8_t msgID_payload;
|
||||
uint8_t rate[6];
|
||||
uint8_t rate;
|
||||
uint8_t ck_a;
|
||||
uint8_t ck_b;
|
||||
} type_gps_bin_cfg_msg_packet_t;
|
||||
|
||||
struct ubx_cfg_msg_rate {
|
||||
uint8_t msg_class;
|
||||
uint8_t msg_id;
|
||||
uint8_t rate;
|
||||
};
|
||||
|
||||
|
||||
// END the structures of the binary packets
|
||||
// ************
|
||||
@@ -341,55 +356,64 @@ class UBX : public GPS_Helper
|
||||
public:
|
||||
UBX(const int &fd, struct vehicle_gps_position_s *gps_position);
|
||||
~UBX();
|
||||
int receive(unsigned timeout);
|
||||
int configure(unsigned &baudrate);
|
||||
int receive(unsigned timeout);
|
||||
int configure(unsigned &baudrate);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Parse the binary MTK packet
|
||||
*/
|
||||
int parse_char(uint8_t b);
|
||||
int parse_char(uint8_t b);
|
||||
|
||||
/**
|
||||
* Handle the package once it has arrived
|
||||
*/
|
||||
int handle_message(void);
|
||||
int handle_message(void);
|
||||
|
||||
/**
|
||||
* Reset the parse state machine for a fresh start
|
||||
*/
|
||||
void decode_init(void);
|
||||
void decode_init(void);
|
||||
|
||||
/**
|
||||
* While parsing add every byte (except the sync bytes) to the checksum
|
||||
*/
|
||||
void add_byte_to_checksum(uint8_t);
|
||||
void add_byte_to_checksum(uint8_t);
|
||||
|
||||
/**
|
||||
* Add the two checksum bytes to an outgoing message
|
||||
*/
|
||||
void add_checksum_to_message(uint8_t* message, const unsigned length);
|
||||
void add_checksum_to_message(uint8_t* message, const unsigned length);
|
||||
|
||||
/**
|
||||
* Helper to send a config packet
|
||||
*/
|
||||
void send_config_packet(const int &fd, uint8_t *packet, const unsigned length);
|
||||
void send_config_packet(const int &fd, uint8_t *packet, const unsigned length);
|
||||
|
||||
int _fd;
|
||||
void configure_message_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate);
|
||||
|
||||
void send_message(uint8_t msg_class, uint8_t msg_id, void *msg, uint8_t size);
|
||||
|
||||
void add_checksum(uint8_t* message, const unsigned length, uint8_t &ck_a, uint8_t &ck_b);
|
||||
|
||||
int wait_for_ack(unsigned timeout);
|
||||
|
||||
int _fd;
|
||||
struct vehicle_gps_position_s *_gps_position;
|
||||
ubx_config_state_t _config_state;
|
||||
bool _waiting_for_ack;
|
||||
uint8_t _clsID_needed;
|
||||
uint8_t _msgID_needed;
|
||||
bool _waiting_for_ack;
|
||||
uint8_t _clsID_needed;
|
||||
uint8_t _msgID_needed;
|
||||
ubx_decode_state_t _decode_state;
|
||||
uint8_t _rx_buffer[RECV_BUFFER_SIZE];
|
||||
unsigned _rx_count;
|
||||
uint8_t _rx_ck_a;
|
||||
uint8_t _rx_ck_b;
|
||||
ubx_message_class_t _message_class;
|
||||
uint8_t _rx_buffer[RECV_BUFFER_SIZE];
|
||||
unsigned _rx_count;
|
||||
uint8_t _rx_ck_a;
|
||||
uint8_t _rx_ck_b;
|
||||
ubx_message_class_t _message_class;
|
||||
ubx_message_id_t _message_id;
|
||||
unsigned _payload_size;
|
||||
unsigned _payload_size;
|
||||
uint8_t _disable_cmd_counter;
|
||||
};
|
||||
|
||||
#endif /* UBX_H_ */
|
||||
|
||||
@@ -1225,19 +1225,25 @@ start()
|
||||
|
||||
/* create the driver, attempt expansion bus first */
|
||||
g_dev = new HMC5883(PX4_I2C_BUS_EXPANSION);
|
||||
if (g_dev != nullptr && OK != g_dev->init()) {
|
||||
delete g_dev;
|
||||
g_dev = nullptr;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PX4_I2C_BUS_ONBOARD
|
||||
/* if this failed, attempt onboard sensor */
|
||||
if (g_dev == nullptr)
|
||||
if (g_dev == nullptr) {
|
||||
g_dev = new HMC5883(PX4_I2C_BUS_ONBOARD);
|
||||
if (g_dev != nullptr && OK != g_dev->init()) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (g_dev == nullptr)
|
||||
goto fail;
|
||||
|
||||
if (OK != g_dev->init())
|
||||
goto fail;
|
||||
|
||||
/* set the poll rate to default, starts automatic data collection */
|
||||
fd = open(MAG_DEVICE_PATH, O_RDONLY);
|
||||
|
||||
|
||||
@@ -42,9 +42,11 @@
|
||||
#include <string.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <unistd.h>
|
||||
#include <uORB/topics/airspeed.h>
|
||||
#include <uORB/topics/battery_status.h>
|
||||
#include <uORB/topics/sensor_combined.h>
|
||||
|
||||
static int airspeed_sub = -1;
|
||||
static int battery_sub = -1;
|
||||
static int sensor_sub = -1;
|
||||
|
||||
@@ -52,6 +54,7 @@ void messages_init(void)
|
||||
{
|
||||
battery_sub = orb_subscribe(ORB_ID(battery_status));
|
||||
sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
|
||||
airspeed_sub = orb_subscribe(ORB_ID(airspeed));
|
||||
}
|
||||
|
||||
void build_eam_response(uint8_t *buffer, int *size)
|
||||
@@ -81,6 +84,15 @@ void build_eam_response(uint8_t *buffer, int *size)
|
||||
msg.altitude_L = (uint8_t)alt & 0xff;
|
||||
msg.altitude_H = (uint8_t)(alt >> 8) & 0xff;
|
||||
|
||||
/* get a local copy of the current sensor values */
|
||||
struct airspeed_s airspeed;
|
||||
memset(&airspeed, 0, sizeof(airspeed));
|
||||
orb_copy(ORB_ID(airspeed), airspeed_sub, &airspeed);
|
||||
|
||||
uint16_t speed = (uint16_t)(airspeed.indicated_airspeed_m_s * 3.6);
|
||||
msg.speed_L = (uint8_t)speed & 0xff;
|
||||
msg.speed_H = (uint8_t)(speed >> 8) & 0xff;
|
||||
|
||||
msg.stop = STOP_BYTE;
|
||||
|
||||
memcpy(buffer, &msg, *size);
|
||||
|
||||
+13
-8
@@ -41,12 +41,17 @@
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/drv_led.h>
|
||||
|
||||
/* Ideally we'd be able to get these from up_internal.h */
|
||||
//#include <up_internal.h>
|
||||
/*
|
||||
* Ideally we'd be able to get these from up_internal.h,
|
||||
* but since we want to be able to disable the NuttX use
|
||||
* of leds for system indication at will and there is no
|
||||
* separate switch, we need to build independent of the
|
||||
* CONFIG_ARCH_LEDS configuration switch.
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
extern void up_ledinit();
|
||||
extern void up_ledon(int led);
|
||||
extern void up_ledoff(int led);
|
||||
extern void led_init();
|
||||
extern void led_on(int led);
|
||||
extern void led_off(int led);
|
||||
__END_DECLS
|
||||
|
||||
class LED : device::CDev
|
||||
@@ -74,7 +79,7 @@ int
|
||||
LED::init()
|
||||
{
|
||||
CDev::init();
|
||||
up_ledinit();
|
||||
led_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -86,11 +91,11 @@ LED::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
|
||||
switch (cmd) {
|
||||
case LED_ON:
|
||||
up_ledon(arg);
|
||||
led_on(arg);
|
||||
break;
|
||||
|
||||
case LED_OFF:
|
||||
up_ledoff(arg);
|
||||
led_off(arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,293 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file md25.cpp
|
||||
*
|
||||
* Driver for MD25 I2C Motor Driver
|
||||
*
|
||||
* references:
|
||||
* http://www.robot-electronics.co.uk/htm/md25tech.htm
|
||||
* http://www.robot-electronics.co.uk/files/rpi_md25.c
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <controllib/block/UOrbSubscription.hpp>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
/**
|
||||
* This is a driver for the MD25 motor controller utilizing the I2C interface.
|
||||
*/
|
||||
class MD25 : public device::I2C
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* modes
|
||||
*
|
||||
* NOTE: this driver assumes we are always
|
||||
* in mode 0!
|
||||
*
|
||||
* seprate speed mode:
|
||||
* motor speed1 = speed1
|
||||
* motor speed2 = speed2
|
||||
* turn speed mode:
|
||||
* motor speed1 = speed1 + speed2
|
||||
* motor speed2 = speed2 - speed2
|
||||
* unsigned:
|
||||
* full rev (0), stop(128), full fwd (255)
|
||||
* signed:
|
||||
* full rev (-127), stop(0), full fwd (128)
|
||||
*
|
||||
* modes numbers:
|
||||
* 0 : unsigned separate (default)
|
||||
* 1 : signed separate
|
||||
* 2 : unsigned turn
|
||||
* 3 : signed turn
|
||||
*/
|
||||
enum e_mode {
|
||||
MODE_UNSIGNED_SPEED = 0,
|
||||
MODE_SIGNED_SPEED,
|
||||
MODE_UNSIGNED_SPEED_TURN,
|
||||
MODE_SIGNED_SPEED_TURN,
|
||||
};
|
||||
|
||||
/** commands */
|
||||
enum e_cmd {
|
||||
CMD_RESET_ENCODERS = 32,
|
||||
CMD_DISABLE_SPEED_REGULATION = 48,
|
||||
CMD_ENABLE_SPEED_REGULATION = 49,
|
||||
CMD_DISABLE_TIMEOUT = 50,
|
||||
CMD_ENABLE_TIMEOUT = 51,
|
||||
CMD_CHANGE_I2C_SEQ_0 = 160,
|
||||
CMD_CHANGE_I2C_SEQ_1 = 170,
|
||||
CMD_CHANGE_I2C_SEQ_2 = 165,
|
||||
};
|
||||
|
||||
/** control channels */
|
||||
enum e_channels {
|
||||
CH_SPEED_LEFT = 0,
|
||||
CH_SPEED_RIGHT
|
||||
};
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param deviceName the name of the device e.g. "/dev/md25"
|
||||
* @param bus the I2C bus
|
||||
* @param address the adddress on the I2C bus
|
||||
* @param speed the speed of the I2C communication
|
||||
*/
|
||||
MD25(const char *deviceName,
|
||||
int bus,
|
||||
uint16_t address,
|
||||
uint32_t speed = 100000);
|
||||
|
||||
/**
|
||||
* deconstructor
|
||||
*/
|
||||
virtual ~MD25();
|
||||
|
||||
/**
|
||||
* @return software version
|
||||
*/
|
||||
uint8_t getVersion();
|
||||
|
||||
/**
|
||||
* @return speed of motor, normalized (-1, 1)
|
||||
*/
|
||||
float getMotor1Speed();
|
||||
|
||||
/**
|
||||
* @return speed of motor 2, normalized (-1, 1)
|
||||
*/
|
||||
float getMotor2Speed();
|
||||
|
||||
/**
|
||||
* @return number of rotations since reset
|
||||
*/
|
||||
float getRevolutions1();
|
||||
|
||||
/**
|
||||
* @return number of rotations since reset
|
||||
*/
|
||||
float getRevolutions2();
|
||||
|
||||
/**
|
||||
* @return battery voltage, volts
|
||||
*/
|
||||
float getBatteryVolts();
|
||||
|
||||
/**
|
||||
* @return motor 1 current, amps
|
||||
*/
|
||||
float getMotor1Current();
|
||||
|
||||
/**
|
||||
* @return motor 2 current, amps
|
||||
*/
|
||||
float getMotor2Current();
|
||||
|
||||
/**
|
||||
* @return the motor acceleration
|
||||
* controls motor speed change (1-10)
|
||||
* accel rate | time for full fwd. to full rev.
|
||||
* 1 | 6.375 s
|
||||
* 2 | 1.6 s
|
||||
* 3 | 0.675 s
|
||||
* 5(default) | 1.275 s
|
||||
* 10 | 0.65 s
|
||||
*/
|
||||
uint8_t getMotorAccel();
|
||||
|
||||
/**
|
||||
* @return motor output mode
|
||||
* */
|
||||
e_mode getMode();
|
||||
|
||||
/**
|
||||
* @return current command register value
|
||||
*/
|
||||
e_cmd getCommand();
|
||||
|
||||
/**
|
||||
* resets the encoders
|
||||
* @return non-zero -> error
|
||||
* */
|
||||
int resetEncoders();
|
||||
|
||||
/**
|
||||
* enable/disable speed regulation
|
||||
* @return non-zero -> error
|
||||
*/
|
||||
int setSpeedRegulation(bool enable);
|
||||
|
||||
/**
|
||||
* set the timeout for the motors
|
||||
* enable/disable timeout (motor stop)
|
||||
* after 2 sec of no i2c messages
|
||||
* @return non-zero -> error
|
||||
*/
|
||||
int setTimeout(bool enable);
|
||||
|
||||
/**
|
||||
* sets the device address
|
||||
* can only be done with one MD25
|
||||
* on the bus
|
||||
* @return non-zero -> error
|
||||
*/
|
||||
int setDeviceAddress(uint8_t address);
|
||||
|
||||
/**
|
||||
* set motor 1 speed
|
||||
* @param normSpeed normalize speed between -1 and 1
|
||||
* @return non-zero -> error
|
||||
*/
|
||||
int setMotor1Speed(float normSpeed);
|
||||
|
||||
/**
|
||||
* set motor 2 speed
|
||||
* @param normSpeed normalize speed between -1 and 1
|
||||
* @return non-zero -> error
|
||||
*/
|
||||
int setMotor2Speed(float normSpeed);
|
||||
|
||||
/**
|
||||
* main update loop that updates MD25 motor
|
||||
* speeds based on actuator publication
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* probe for device
|
||||
*/
|
||||
virtual int probe();
|
||||
|
||||
/**
|
||||
* search for device
|
||||
*/
|
||||
int search();
|
||||
|
||||
/**
|
||||
* read data from i2c
|
||||
*/
|
||||
int readData();
|
||||
|
||||
/**
|
||||
* print status
|
||||
*/
|
||||
void status(char *string, size_t n);
|
||||
|
||||
private:
|
||||
/** poll structure for control packets */
|
||||
struct pollfd _controlPoll;
|
||||
|
||||
/** actuator controls subscription */
|
||||
control::UOrbSubscription<actuator_controls_s> _actuators;
|
||||
|
||||
// local copy of data from i2c device
|
||||
uint8_t _version;
|
||||
float _motor1Speed;
|
||||
float _motor2Speed;
|
||||
float _revolutions1;
|
||||
float _revolutions2;
|
||||
float _batteryVoltage;
|
||||
float _motor1Current;
|
||||
float _motor2Current;
|
||||
uint8_t _motorAccel;
|
||||
e_mode _mode;
|
||||
e_cmd _command;
|
||||
|
||||
// private methods
|
||||
int _writeUint8(uint8_t reg, uint8_t value);
|
||||
int _writeInt8(uint8_t reg, int8_t value);
|
||||
float _uint8ToNorm(uint8_t value);
|
||||
uint8_t _normToUint8(float value);
|
||||
|
||||
/**
|
||||
* set motor control mode,
|
||||
* this driver assumed we are always in mode 0
|
||||
* so we don't let the user change the mode
|
||||
* @return non-zero -> error
|
||||
*/
|
||||
int _setMode(e_mode);
|
||||
};
|
||||
|
||||
// unit testing
|
||||
int md25Test(const char *deviceName, uint8_t bus, uint8_t address);
|
||||
|
||||
// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
|
||||
@@ -0,0 +1,264 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ file md25.cpp
|
||||
*
|
||||
* Driver for MD25 I2C Motor Driver
|
||||
*
|
||||
* references:
|
||||
* http://www.robot-electronics.co.uk/htm/md25tech.htm
|
||||
* http://www.robot-electronics.co.uk/files/rpi_md25.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <systemlib/param/param.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
#include "md25.hpp"
|
||||
|
||||
static bool thread_should_exit = false; /**< Deamon exit flag */
|
||||
static bool thread_running = false; /**< Deamon status flag */
|
||||
static int deamon_task; /**< Handle of deamon task / thread */
|
||||
|
||||
/**
|
||||
* Deamon management function.
|
||||
*/
|
||||
extern "C" __EXPORT int md25_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Mainloop of deamon.
|
||||
*/
|
||||
int md25_thread_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Print the correct usage.
|
||||
*/
|
||||
static void usage(const char *reason);
|
||||
|
||||
static void
|
||||
usage(const char *reason)
|
||||
{
|
||||
if (reason)
|
||||
fprintf(stderr, "%s\n", reason);
|
||||
|
||||
fprintf(stderr, "usage: md25 {start|stop|status|search|test|change_address}\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deamon app only briefly exists to start
|
||||
* the background job. The stack size assigned in the
|
||||
* Makefile does only apply to this management task.
|
||||
*
|
||||
* The actual stack size should be set in the call
|
||||
* to task_create().
|
||||
*/
|
||||
int md25_main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
if (argc < 1)
|
||||
usage("missing command");
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
if (thread_running) {
|
||||
printf("md25 already running\n");
|
||||
/* this is not an error */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn("md25",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 10,
|
||||
2048,
|
||||
md25_thread_main,
|
||||
(const char **)argv);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "test")) {
|
||||
|
||||
if (argc < 4) {
|
||||
printf("usage: md25 test bus address\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const char *deviceName = "/dev/md25";
|
||||
|
||||
uint8_t bus = strtoul(argv[2], nullptr, 0);
|
||||
|
||||
uint8_t address = strtoul(argv[3], nullptr, 0);
|
||||
|
||||
md25Test(deviceName, bus, address);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "probe")) {
|
||||
if (argc < 4) {
|
||||
printf("usage: md25 probe bus address\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const char *deviceName = "/dev/md25";
|
||||
|
||||
uint8_t bus = strtoul(argv[2], nullptr, 0);
|
||||
|
||||
uint8_t address = strtoul(argv[3], nullptr, 0);
|
||||
|
||||
MD25 md25(deviceName, bus, address);
|
||||
|
||||
int ret = md25.probe();
|
||||
|
||||
if (ret == OK) {
|
||||
printf("MD25 found on bus %d at address 0x%X\n", bus, md25.get_address());
|
||||
|
||||
} else {
|
||||
printf("MD25 not found on bus %d\n", bus);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "search")) {
|
||||
if (argc < 3) {
|
||||
printf("usage: md25 search bus\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const char *deviceName = "/dev/md25";
|
||||
|
||||
uint8_t bus = strtoul(argv[2], nullptr, 0);
|
||||
|
||||
uint8_t address = strtoul(argv[3], nullptr, 0);
|
||||
|
||||
MD25 md25(deviceName, bus, address);
|
||||
|
||||
md25.search();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "change_address")) {
|
||||
if (argc < 5) {
|
||||
printf("usage: md25 change_address bus old_address new_address\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const char *deviceName = "/dev/md25";
|
||||
|
||||
uint8_t bus = strtoul(argv[2], nullptr, 0);
|
||||
|
||||
uint8_t old_address = strtoul(argv[3], nullptr, 0);
|
||||
|
||||
uint8_t new_address = strtoul(argv[4], nullptr, 0);
|
||||
|
||||
MD25 md25(deviceName, bus, old_address);
|
||||
|
||||
int ret = md25.setDeviceAddress(new_address);
|
||||
|
||||
if (ret == OK) {
|
||||
printf("MD25 new address set to 0x%X\n", new_address);
|
||||
|
||||
} else {
|
||||
printf("MD25 failed to set address to 0x%X\n", new_address);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
thread_should_exit = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (thread_running) {
|
||||
printf("\tmd25 app is running\n");
|
||||
|
||||
} else {
|
||||
printf("\tmd25 app not started\n");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
usage("unrecognized command");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int md25_thread_main(int argc, char *argv[])
|
||||
{
|
||||
printf("[MD25] starting\n");
|
||||
|
||||
if (argc < 5) {
|
||||
// extra md25 in arg list since this is a thread
|
||||
printf("usage: md25 start bus address\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const char *deviceName = "/dev/md25";
|
||||
|
||||
uint8_t bus = strtoul(argv[3], nullptr, 0);
|
||||
|
||||
uint8_t address = strtoul(argv[4], nullptr, 0);
|
||||
|
||||
// start
|
||||
MD25 md25("/dev/md25", bus, address);
|
||||
|
||||
thread_running = true;
|
||||
|
||||
// loop
|
||||
while (!thread_should_exit) {
|
||||
md25.update();
|
||||
}
|
||||
|
||||
// exit
|
||||
printf("[MD25] exiting.\n");
|
||||
thread_running = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
|
||||
@@ -0,0 +1,42 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# MD25 I2C Based Motor Controller
|
||||
# http://www.robot-electronics.co.uk/htm/md25tech.htm
|
||||
#
|
||||
|
||||
MODULE_COMMAND = md25
|
||||
|
||||
SRCS = md25.cpp \
|
||||
md25_main.cpp
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2012,2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Interface driver for the Mikrokopter BLCtrl
|
||||
#
|
||||
|
||||
MODULE_COMMAND = mkblctrl
|
||||
|
||||
SRCS = mkblctrl.cpp
|
||||
|
||||
INCLUDE_DIRS += $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
|
||||
@@ -574,7 +574,11 @@ PX4FMU::task_main()
|
||||
orb_copy(ORB_ID(actuator_armed), _t_armed, &aa);
|
||||
|
||||
/* update PWM servo armed status if armed and not locked down */
|
||||
up_pwm_servo_arm(aa.armed && !aa.lockdown);
|
||||
bool set_armed = aa.armed && !aa.lockdown;
|
||||
if (set_armed != _armed) {
|
||||
_armed = set_armed;
|
||||
up_pwm_servo_arm(set_armed);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FMU_HAVE_PPM
|
||||
@@ -675,6 +679,11 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
up_pwm_servo_arm(true);
|
||||
break;
|
||||
|
||||
case PWM_SERVO_SET_ARM_OK:
|
||||
case PWM_SERVO_CLEAR_ARM_OK:
|
||||
// these are no-ops, as no safety switch
|
||||
break;
|
||||
|
||||
case PWM_SERVO_DISARM:
|
||||
up_pwm_servo_arm(false);
|
||||
break;
|
||||
|
||||
+84
-31
@@ -108,6 +108,14 @@ public:
|
||||
*/
|
||||
int set_update_rate(int rate);
|
||||
|
||||
/**
|
||||
* Set the battery current scaling and bias
|
||||
*
|
||||
* @param amp_per_volt
|
||||
* @param amp_bias
|
||||
*/
|
||||
void set_battery_current_scaling(float amp_per_volt, float amp_bias);
|
||||
|
||||
/**
|
||||
* Print the current status of IO
|
||||
*/
|
||||
@@ -151,6 +159,10 @@ private:
|
||||
|
||||
bool _primary_pwm_device; ///< true if we are the default PWM output
|
||||
|
||||
float _battery_amp_per_volt;
|
||||
float _battery_amp_bias;
|
||||
float _battery_mamphour_total;
|
||||
uint64_t _battery_last_timestamp;
|
||||
|
||||
/**
|
||||
* Trampoline to the worker task
|
||||
@@ -314,6 +326,10 @@ PX4IO::PX4IO() :
|
||||
_to_actuators_effective(0),
|
||||
_to_outputs(0),
|
||||
_to_battery(0),
|
||||
_battery_amp_per_volt(90.0f/5.0f), // this matches the 3DR current sensor
|
||||
_battery_amp_bias(0),
|
||||
_battery_mamphour_total(0),
|
||||
_battery_last_timestamp(0),
|
||||
_primary_pwm_device(false)
|
||||
{
|
||||
/* we need this potentially before it could be set in task_main */
|
||||
@@ -400,7 +416,7 @@ PX4IO::init()
|
||||
* already armed, and has been configured for in-air restart
|
||||
*/
|
||||
if ((reg & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) &&
|
||||
(reg & PX4IO_P_SETUP_ARMING_ARM_OK)) {
|
||||
(reg & PX4IO_P_SETUP_ARMING_FMU_ARMED)) {
|
||||
|
||||
mavlink_log_emergency(_mavlink_fd, "[IO] RECOVERING FROM FMU IN-AIR RESTART");
|
||||
|
||||
@@ -484,10 +500,9 @@ PX4IO::init()
|
||||
|
||||
/* dis-arm IO before touching anything */
|
||||
io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING,
|
||||
PX4IO_P_SETUP_ARMING_ARM_OK |
|
||||
PX4IO_P_SETUP_ARMING_FMU_ARMED |
|
||||
PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK |
|
||||
PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK |
|
||||
PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK, 0);
|
||||
PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK, 0);
|
||||
|
||||
/* publish RC config to IO */
|
||||
ret = io_set_rc_config();
|
||||
@@ -686,16 +701,18 @@ PX4IO::io_set_arming_state()
|
||||
uint16_t set = 0;
|
||||
uint16_t clear = 0;
|
||||
|
||||
if (armed.armed) {
|
||||
set |= PX4IO_P_SETUP_ARMING_ARM_OK;
|
||||
if (armed.armed && !armed.lockdown) {
|
||||
set |= PX4IO_P_SETUP_ARMING_FMU_ARMED;
|
||||
} else {
|
||||
clear |= PX4IO_P_SETUP_ARMING_ARM_OK;
|
||||
clear |= PX4IO_P_SETUP_ARMING_FMU_ARMED;
|
||||
}
|
||||
if (vstatus.flag_vector_flight_mode_ok) {
|
||||
set |= PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK;
|
||||
|
||||
if (armed.ready_to_arm) {
|
||||
set |= PX4IO_P_SETUP_ARMING_IO_ARM_OK;
|
||||
} else {
|
||||
clear |= PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK;
|
||||
clear |= PX4IO_P_SETUP_ARMING_IO_ARM_OK;
|
||||
}
|
||||
|
||||
if (vstatus.flag_external_manual_override_ok) {
|
||||
set |= PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK;
|
||||
} else {
|
||||
@@ -884,11 +901,22 @@ PX4IO::io_get_status()
|
||||
/* voltage is scaled to mV */
|
||||
battery_status.voltage_v = regs[2] / 1000.0f;
|
||||
|
||||
/* current scaling should be to cA in order to avoid limiting at 65A */
|
||||
battery_status.current_a = regs[3] / 100.f;
|
||||
/*
|
||||
regs[3] contains the raw ADC count, as 12 bit ADC
|
||||
value, with full range being 3.3v
|
||||
*/
|
||||
battery_status.current_a = regs[3] * (3.3f/4096.0f) * _battery_amp_per_volt;
|
||||
battery_status.current_a += _battery_amp_bias;
|
||||
|
||||
/* this requires integration over time - not currently implemented */
|
||||
battery_status.discharged_mah = -1.0f;
|
||||
/*
|
||||
integrate battery over time to get total mAh used
|
||||
*/
|
||||
if (_battery_last_timestamp != 0) {
|
||||
_battery_mamphour_total += battery_status.current_a *
|
||||
(battery_status.timestamp - _battery_last_timestamp) * 1.0e-3f / 3600;
|
||||
}
|
||||
battery_status.discharged_mah = _battery_mamphour_total;
|
||||
_battery_last_timestamp = battery_status.timestamp;
|
||||
|
||||
/* lazily publish the battery voltage */
|
||||
if (_to_battery > 0) {
|
||||
@@ -1245,9 +1273,14 @@ PX4IO::print_status()
|
||||
((alarms & PX4IO_P_STATUS_ALARMS_FMU_LOST) ? " FMU_LOST" : ""),
|
||||
((alarms & PX4IO_P_STATUS_ALARMS_RC_LOST) ? " RC_LOST" : ""),
|
||||
((alarms & PX4IO_P_STATUS_ALARMS_PWM_ERROR) ? " PWM_ERROR" : ""));
|
||||
printf("vbatt %u ibatt %u\n",
|
||||
io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_VBATT),
|
||||
io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_IBATT));
|
||||
printf("vbatt %u ibatt %u vbatt scale %u\n",
|
||||
io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_VBATT),
|
||||
io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_IBATT),
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_VBATT_SCALE));
|
||||
printf("amp_per_volt %.3f amp_offset %.3f mAhDischarged %.3f\n",
|
||||
(double)_battery_amp_per_volt,
|
||||
(double)_battery_amp_bias,
|
||||
(double)_battery_mamphour_total);
|
||||
printf("actuators");
|
||||
for (unsigned i = 0; i < _max_actuators; i++)
|
||||
printf(" %u", io_reg_get(PX4IO_PAGE_ACTUATORS, i));
|
||||
@@ -1279,19 +1312,15 @@ PX4IO::print_status()
|
||||
uint16_t arming = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING);
|
||||
printf("arming 0x%04x%s%s%s%s\n",
|
||||
arming,
|
||||
((arming & PX4IO_P_SETUP_ARMING_ARM_OK) ? " ARM_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) ? " FMU_ARMED" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_IO_ARM_OK) ? " IO_ARM_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK) ? " MANUAL_OVERRIDE_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK) ? " VECTOR_FLIGHT_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) ? " INAIR_RESTART_OK" : ""));
|
||||
printf("rates 0x%04x default %u alt %u relays 0x%04x\n",
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATES),
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_DEFAULTRATE),
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE),
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_RELAYS));
|
||||
printf("vbatt scale %u ibatt scale %u ibatt bias %u\n",
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_VBATT_SCALE),
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_IBATT_SCALE),
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_IBATT_BIAS));
|
||||
printf("debuglevel %u\n", io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_SET_DEBUG));
|
||||
printf("controls");
|
||||
for (unsigned i = 0; i < _max_controls; i++)
|
||||
@@ -1326,21 +1355,27 @@ PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
|
||||
switch (cmd) {
|
||||
case PWM_SERVO_ARM:
|
||||
/* set the 'armed' bit */
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_ARM_OK);
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_FMU_ARMED);
|
||||
break;
|
||||
|
||||
case PWM_SERVO_SET_ARM_OK:
|
||||
/* set the 'OK to arm' bit */
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_IO_ARM_OK);
|
||||
break;
|
||||
|
||||
case PWM_SERVO_CLEAR_ARM_OK:
|
||||
/* clear the 'OK to arm' bit */
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_IO_ARM_OK, 0);
|
||||
break;
|
||||
|
||||
case PWM_SERVO_DISARM:
|
||||
/* clear the 'armed' bit */
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_ARM_OK, 0);
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_FMU_ARMED, 0);
|
||||
break;
|
||||
|
||||
case PWM_SERVO_SET_UPDATE_RATE:
|
||||
/* set the requested alternate rate */
|
||||
if ((arg >= 50) && (arg <= 400)) { /* TODO: we could go higher for e.g. TurboPWM */
|
||||
ret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE, arg);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
ret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE, arg);
|
||||
break;
|
||||
|
||||
case PWM_SERVO_SELECT_UPDATE_RATE: {
|
||||
@@ -1525,6 +1560,12 @@ PX4IO::set_update_rate(int rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO::set_battery_current_scaling(float amp_per_volt, float amp_bias)
|
||||
{
|
||||
_battery_amp_per_volt = amp_per_volt;
|
||||
_battery_amp_bias = amp_bias;
|
||||
}
|
||||
|
||||
extern "C" __EXPORT int px4io_main(int argc, char *argv[]);
|
||||
|
||||
@@ -1662,6 +1703,18 @@ px4io_main(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "current")) {
|
||||
if (g_dev != nullptr) {
|
||||
if ((argc > 3)) {
|
||||
g_dev->set_battery_current_scaling(atof(argv[2]), atof(argv[3]));
|
||||
} else {
|
||||
errx(1, "missing argument (apm_per_volt, amp_offset)");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "recovery")) {
|
||||
|
||||
if (g_dev != nullptr) {
|
||||
@@ -1789,5 +1842,5 @@ px4io_main(int argc, char *argv[])
|
||||
monitor();
|
||||
|
||||
out:
|
||||
errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug', 'recovery', 'limit' or 'update'");
|
||||
errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug', 'recovery', 'limit', 'current' or 'update'");
|
||||
}
|
||||
|
||||
@@ -127,6 +127,8 @@ PX4IO_Uploader::upload(const char *filenames[])
|
||||
if (ret != OK) {
|
||||
/* this is immediately fatal */
|
||||
log("bootloader not responding");
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -145,18 +147,25 @@ PX4IO_Uploader::upload(const char *filenames[])
|
||||
|
||||
if (filename == NULL) {
|
||||
log("no firmware found");
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(filename, &st) != 0) {
|
||||
log("Failed to stat %s - %d\n", filename, (int)errno);
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return -errno;
|
||||
}
|
||||
fw_size = st.st_size;
|
||||
|
||||
if (_fw_fd == -1)
|
||||
if (_fw_fd == -1) {
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* do the usual program thing - allow for failure */
|
||||
for (unsigned retries = 0; retries < 1; retries++) {
|
||||
@@ -167,6 +176,8 @@ PX4IO_Uploader::upload(const char *filenames[])
|
||||
if (ret != OK) {
|
||||
/* this is immediately fatal */
|
||||
log("bootloader not responding");
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@@ -178,6 +189,8 @@ PX4IO_Uploader::upload(const char *filenames[])
|
||||
log("found bootloader revision: %d", bl_rev);
|
||||
} else {
|
||||
log("found unsupported bootloader revision %d, exiting", bl_rev);
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
@@ -221,6 +234,8 @@ PX4IO_Uploader::upload(const char *filenames[])
|
||||
}
|
||||
|
||||
close(_fw_fd);
|
||||
close(_io_fd);
|
||||
_io_fd = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file main.c
|
||||
* Implementation of a fixed wing attitude controller. This file is a complete
|
||||
* fixed wing controller flying manual attitude control or auto waypoint control.
|
||||
* There is no need to touch any other system components to extend / modify the
|
||||
* complete control architecture.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_global_position_setpoint.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/debug_key_value.h>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/pid/pid.h>
|
||||
#include <systemlib/geo/geo.h>
|
||||
#include <systemlib/perf_counter.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <systemlib/err.h>
|
||||
|
||||
/* process-specific header files */
|
||||
#include "params.h"
|
||||
|
||||
/* Prototypes */
|
||||
/**
|
||||
* Daemon management function.
|
||||
*/
|
||||
__EXPORT int ex_fixedwing_control_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Mainloop of daemon.
|
||||
*/
|
||||
int fixedwing_control_thread_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Print the correct usage.
|
||||
*/
|
||||
static void usage(const char *reason);
|
||||
|
||||
void control_attitude(const struct vehicle_attitude_setpoint_s *att_sp, const struct vehicle_attitude_s *att,
|
||||
float speed_body[], float gyro[], struct vehicle_rates_setpoint_s *rates_sp,
|
||||
struct actuator_controls_s *actuators);
|
||||
|
||||
void control_heading(const struct vehicle_global_position_s *pos, const struct vehicle_global_position_setpoint_s *sp,
|
||||
const struct vehicle_attitude_s *att, struct vehicle_attitude_setpoint_s *att_sp);
|
||||
|
||||
/* Variables */
|
||||
static bool thread_should_exit = false; /**< Daemon exit flag */
|
||||
static bool thread_running = false; /**< Daemon status flag */
|
||||
static int deamon_task; /**< Handle of deamon task / thread */
|
||||
static struct params p;
|
||||
static struct param_handles ph;
|
||||
|
||||
void control_attitude(const struct vehicle_attitude_setpoint_s *att_sp, const struct vehicle_attitude_s *att,
|
||||
float speed_body[], float gyro[], struct vehicle_rates_setpoint_s *rates_sp,
|
||||
struct actuator_controls_s *actuators)
|
||||
{
|
||||
|
||||
/*
|
||||
* The PX4 architecture provides a mixer outside of the controller.
|
||||
* The mixer is fed with a default vector of actuator controls, representing
|
||||
* moments applied to the vehicle frame. This vector
|
||||
* is structured as:
|
||||
*
|
||||
* Control Group 0 (attitude):
|
||||
*
|
||||
* 0 - roll (-1..+1)
|
||||
* 1 - pitch (-1..+1)
|
||||
* 2 - yaw (-1..+1)
|
||||
* 3 - thrust ( 0..+1)
|
||||
* 4 - flaps (-1..+1)
|
||||
* ...
|
||||
*
|
||||
* Control Group 1 (payloads / special):
|
||||
*
|
||||
* ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate roll error and apply P gain
|
||||
*/
|
||||
float roll_err = att->roll - att_sp->roll_body;
|
||||
actuators->control[0] = roll_err * p.roll_p;
|
||||
|
||||
/*
|
||||
* Calculate pitch error and apply P gain
|
||||
*/
|
||||
float pitch_err = att->pitch - att_sp->pitch_body;
|
||||
actuators->control[1] = pitch_err * p.pitch_p;
|
||||
}
|
||||
|
||||
void control_heading(const struct vehicle_global_position_s *pos, const struct vehicle_global_position_setpoint_s *sp,
|
||||
const struct vehicle_attitude_s *att, struct vehicle_attitude_setpoint_s *att_sp)
|
||||
{
|
||||
|
||||
/*
|
||||
* Calculate heading error of current position to desired position
|
||||
*/
|
||||
|
||||
/* PX4 uses 1e7 scaled integers to represent global coordinates for max resolution */
|
||||
float bearing = get_bearing_to_next_waypoint(pos->lat/1e7d, pos->lon/1e7d, sp->lat/1e7d, sp->lon/1e7d);
|
||||
|
||||
/* calculate heading error */
|
||||
float yaw_err = att->yaw - bearing;
|
||||
/* apply control gain */
|
||||
att_sp->roll_body = yaw_err * p.hdng_p;
|
||||
}
|
||||
|
||||
/* Main Thread */
|
||||
int fixedwing_control_thread_main(int argc, char *argv[])
|
||||
{
|
||||
/* read arguments */
|
||||
bool verbose = false;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome user (warnx prints a line, including an appended\n, with variable arguments */
|
||||
warnx("[example fixedwing control] started");
|
||||
|
||||
/* initialize parameters, first the handles, then the values */
|
||||
parameters_init(&ph);
|
||||
parameters_update(&ph, &p);
|
||||
|
||||
/* declare and safely initialize all structs to zero */
|
||||
struct vehicle_attitude_s att;
|
||||
memset(&att, 0, sizeof(att));
|
||||
struct vehicle_attitude_setpoint_s att_sp;
|
||||
memset(&att_sp, 0, sizeof(att_sp));
|
||||
struct vehicle_rates_setpoint_s rates_sp;
|
||||
memset(&rates_sp, 0, sizeof(rates_sp));
|
||||
struct vehicle_global_position_s global_pos;
|
||||
memset(&global_pos, 0, sizeof(global_pos));
|
||||
struct manual_control_setpoint_s manual_sp;
|
||||
memset(&manual_sp, 0, sizeof(manual_sp));
|
||||
struct vehicle_status_s vstatus;
|
||||
memset(&vstatus, 0, sizeof(vstatus));
|
||||
struct vehicle_global_position_setpoint_s global_sp;
|
||||
memset(&global_sp, 0, sizeof(global_sp));
|
||||
|
||||
/* output structs */
|
||||
struct actuator_controls_s actuators;
|
||||
memset(&actuators, 0, sizeof(actuators));
|
||||
|
||||
|
||||
/* publish actuator controls */
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROLS; i++) {
|
||||
actuators.control[i] = 0.0f;
|
||||
}
|
||||
|
||||
orb_advert_t actuator_pub = orb_advertise(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, &actuators);
|
||||
orb_advert_t rates_pub = orb_advertise(ORB_ID(vehicle_rates_setpoint), &rates_sp);
|
||||
|
||||
/* subscribe */
|
||||
int att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
int att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
|
||||
int global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
|
||||
int manual_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
|
||||
int vstatus_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
int global_sp_sub = orb_subscribe(ORB_ID(vehicle_global_position_setpoint));
|
||||
int param_sub = orb_subscribe(ORB_ID(parameter_update));
|
||||
|
||||
/* Setup of loop */
|
||||
float gyro[3] = {0.0f, 0.0f, 0.0f};
|
||||
float speed_body[3] = {0.0f, 0.0f, 0.0f};
|
||||
struct pollfd fds[2] = {{ .fd = param_sub, .events = POLLIN },
|
||||
{ .fd = att_sub, .events = POLLIN }};
|
||||
|
||||
while (!thread_should_exit) {
|
||||
|
||||
/*
|
||||
* Wait for a sensor or param update, check for exit condition every 500 ms.
|
||||
* This means that the execution will block here without consuming any resources,
|
||||
* but will continue to execute the very moment a new attitude measurement or
|
||||
* a param update is published. So no latency in contrast to the polling
|
||||
* design pattern (do not confuse the poll() system call with polling).
|
||||
*
|
||||
* This design pattern makes the controller also agnostic of the attitude
|
||||
* update speed - it runs as fast as the attitude updates with minimal latency.
|
||||
*/
|
||||
int ret = poll(fds, 2, 500);
|
||||
|
||||
if (ret < 0) {
|
||||
/* poll error, this will not really happen in practice */
|
||||
warnx("poll error");
|
||||
|
||||
} else if (ret == 0) {
|
||||
/* no return value = nothing changed for 500 ms, ignore */
|
||||
} else {
|
||||
|
||||
/* only update parameters if they changed */
|
||||
if (fds[0].revents & POLLIN) {
|
||||
/* read from param to clear updated flag (uORB API requirement) */
|
||||
struct parameter_update_s update;
|
||||
orb_copy(ORB_ID(parameter_update), param_sub, &update);
|
||||
|
||||
/* if a param update occured, re-read our parameters */
|
||||
parameters_update(&ph, &p);
|
||||
}
|
||||
|
||||
/* only run controller if attitude changed */
|
||||
if (fds[1].revents & POLLIN) {
|
||||
|
||||
|
||||
/* Check if there is a new position measurement or position setpoint */
|
||||
bool pos_updated;
|
||||
orb_check(global_pos_sub, &pos_updated);
|
||||
bool global_sp_updated;
|
||||
orb_check(global_sp_sub, &global_sp_updated);
|
||||
|
||||
/* get a local copy of attitude */
|
||||
orb_copy(ORB_ID(vehicle_attitude), att_sub, &att);
|
||||
|
||||
if (global_sp_updated)
|
||||
orb_copy(ORB_ID(vehicle_global_position_setpoint), global_sp_sub, &global_sp);
|
||||
|
||||
if (pos_updated) {
|
||||
orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos);
|
||||
|
||||
if (att.R_valid) {
|
||||
speed_body[0] = att.R[0][0] * global_pos.vx + att.R[0][1] * global_pos.vy + att.R[0][2] * global_pos.vz;
|
||||
speed_body[1] = att.R[1][0] * global_pos.vx + att.R[1][1] * global_pos.vy + att.R[1][2] * global_pos.vz;
|
||||
speed_body[2] = att.R[2][0] * global_pos.vx + att.R[2][1] * global_pos.vy + att.R[2][2] * global_pos.vz;
|
||||
|
||||
} else {
|
||||
speed_body[0] = 0;
|
||||
speed_body[1] = 0;
|
||||
speed_body[2] = 0;
|
||||
|
||||
warnx("Did not get a valid R\n");
|
||||
}
|
||||
}
|
||||
|
||||
orb_copy(ORB_ID(manual_control_setpoint), manual_sp_sub, &manual_sp);
|
||||
orb_copy(ORB_ID(vehicle_status), vstatus_sub, &vstatus);
|
||||
|
||||
gyro[0] = att.rollspeed;
|
||||
gyro[1] = att.pitchspeed;
|
||||
gyro[2] = att.yawspeed;
|
||||
|
||||
/* control */
|
||||
|
||||
if (vstatus.state_machine == SYSTEM_STATE_AUTO ||
|
||||
vstatus.state_machine == SYSTEM_STATE_STABILIZED) {
|
||||
|
||||
/* simple heading control */
|
||||
control_heading(&global_pos, &global_sp, &att, &att_sp);
|
||||
|
||||
/* nail pitch and yaw (rudder) to zero. This example only controls roll (index 0) */
|
||||
actuators.control[1] = 0.0f;
|
||||
actuators.control[2] = 0.0f;
|
||||
|
||||
/* simple attitude control */
|
||||
control_attitude(&att_sp, &att, speed_body, gyro, &rates_sp, &actuators);
|
||||
|
||||
/* pass through throttle */
|
||||
actuators.control[3] = att_sp.thrust;
|
||||
|
||||
/* set flaps to zero */
|
||||
actuators.control[4] = 0.0f;
|
||||
|
||||
} else if (vstatus.state_machine == SYSTEM_STATE_MANUAL) {
|
||||
if (vstatus.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_SAS) {
|
||||
|
||||
/* if the RC signal is lost, try to stay level and go slowly back down to ground */
|
||||
if (vstatus.rc_signal_lost) {
|
||||
|
||||
/* put plane into loiter */
|
||||
att_sp.roll_body = 0.3f;
|
||||
att_sp.pitch_body = 0.0f;
|
||||
|
||||
/* limit throttle to 60 % of last value if sane */
|
||||
if (isfinite(manual_sp.throttle) &&
|
||||
(manual_sp.throttle >= 0.0f) &&
|
||||
(manual_sp.throttle <= 1.0f)) {
|
||||
att_sp.thrust = 0.6f * manual_sp.throttle;
|
||||
|
||||
} else {
|
||||
att_sp.thrust = 0.0f;
|
||||
}
|
||||
|
||||
att_sp.yaw_body = 0;
|
||||
|
||||
// XXX disable yaw control, loiter
|
||||
|
||||
} else {
|
||||
|
||||
att_sp.roll_body = manual_sp.roll;
|
||||
att_sp.pitch_body = manual_sp.pitch;
|
||||
att_sp.yaw_body = 0;
|
||||
att_sp.thrust = manual_sp.throttle;
|
||||
}
|
||||
|
||||
att_sp.timestamp = hrt_absolute_time();
|
||||
|
||||
/* attitude control */
|
||||
control_attitude(&att_sp, &att, speed_body, gyro, &rates_sp, &actuators);
|
||||
|
||||
/* pass through throttle */
|
||||
actuators.control[3] = att_sp.thrust;
|
||||
|
||||
/* pass through flaps */
|
||||
if (isfinite(manual_sp.flaps)) {
|
||||
actuators.control[4] = manual_sp.flaps;
|
||||
|
||||
} else {
|
||||
actuators.control[4] = 0.0f;
|
||||
}
|
||||
|
||||
} else if (vstatus.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_DIRECT) {
|
||||
/* directly pass through values */
|
||||
actuators.control[0] = manual_sp.roll;
|
||||
/* positive pitch means negative actuator -> pull up */
|
||||
actuators.control[1] = manual_sp.pitch;
|
||||
actuators.control[2] = manual_sp.yaw;
|
||||
actuators.control[3] = manual_sp.throttle;
|
||||
|
||||
if (isfinite(manual_sp.flaps)) {
|
||||
actuators.control[4] = manual_sp.flaps;
|
||||
|
||||
} else {
|
||||
actuators.control[4] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* publish rates */
|
||||
orb_publish(ORB_ID(vehicle_rates_setpoint), rates_pub, &rates_sp);
|
||||
|
||||
/* sanity check and publish actuator outputs */
|
||||
if (isfinite(actuators.control[0]) &&
|
||||
isfinite(actuators.control[1]) &&
|
||||
isfinite(actuators.control[2]) &&
|
||||
isfinite(actuators.control[3])) {
|
||||
orb_publish(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_pub, &actuators);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("[ex_fixedwing_control] exiting, stopping all motors.\n");
|
||||
thread_running = false;
|
||||
|
||||
/* kill all outputs */
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROLS; i++)
|
||||
actuators.control[i] = 0.0f;
|
||||
|
||||
orb_publish(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_pub, &actuators);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Startup Functions */
|
||||
|
||||
static void
|
||||
usage(const char *reason)
|
||||
{
|
||||
if (reason)
|
||||
fprintf(stderr, "%s\n", reason);
|
||||
|
||||
fprintf(stderr, "usage: ex_fixedwing_control {start|stop|status}\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* The daemon app only briefly exists to start
|
||||
* the background job. The stack size assigned in the
|
||||
* Makefile does only apply to this management task.
|
||||
*
|
||||
* The actual stack size should be set in the call
|
||||
* to task_create().
|
||||
*/
|
||||
int ex_fixedwing_control_main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
usage("missing command");
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
if (thread_running) {
|
||||
printf("ex_fixedwing_control already running\n");
|
||||
/* this is not an error */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn("ex_fixedwing_control",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 20,
|
||||
2048,
|
||||
fixedwing_control_thread_main,
|
||||
(argv) ? (const char **)&argv[2] : (const char **)NULL);
|
||||
thread_running = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
thread_should_exit = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (thread_running) {
|
||||
printf("\tex_fixedwing_control is running\n");
|
||||
|
||||
} else {
|
||||
printf("\tex_fixedwing_control not started\n");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
usage("unrecognized command");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Fixedwing Attitude Control Demo / Example Application
|
||||
#
|
||||
|
||||
MODULE_COMMAND = ex_fixedwing_control
|
||||
|
||||
SRCS = main.c \
|
||||
params.c
|
||||
@@ -0,0 +1,77 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* @file params.c
|
||||
*
|
||||
* Parameters for fixedwing demo
|
||||
*/
|
||||
|
||||
#include "params.h"
|
||||
|
||||
/* controller parameters, use max. 15 characters for param name! */
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(EXFW_HDNG_P, 0.2f);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(EXFW_ROLL_P, 0.2f);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(EXFW_PITCH_P, 0.2f);
|
||||
|
||||
int parameters_init(struct param_handles *h)
|
||||
{
|
||||
/* PID parameters */
|
||||
h->hdng_p = param_find("EXFW_HDNG_P");
|
||||
h->roll_p = param_find("EXFW_ROLL_P");
|
||||
h->pitch_p = param_find("EXFW_PITCH_P");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int parameters_update(const struct param_handles *h, struct params *p)
|
||||
{
|
||||
param_get(h->hdng_p, &(p->hdng_p));
|
||||
param_get(h->roll_p, &(p->roll_p));
|
||||
param_get(h->pitch_p, &(p->pitch_p));
|
||||
|
||||
return OK;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user