├── .project
├── README.md
├── cmake
├── configs
│ ├── posix_rpi_cross_no_shield.cmake
│ ├── posix_rpi_cross_single.cmake
│ ├── posix_rpi_native_single.cmake
│ └── toolchains
│ │ ├── Toolchain-arm-bcm2835-linux-gnueabihf-raspbian.cmake
│ │ └── Toolchain-cross-generic.cmake
└── toolchains
│ └── Toolchain-arm-bcm2835-linx-gnueabihf-raspbian.cmake
├── posix-configs
├── arm
│ └── px4_linux.config
└── rpi
│ ├── px4.config
│ ├── px4_fw.config
│ ├── px4_hil.config
│ ├── px4_no_shield.config
│ ├── px4_noshield.config
│ └── px4_rpi.config
└── src
└── drivers
├── linux_pca9685
├── CMakeLists.txt
├── linux_pca9685.cpp
└── linux_pca9685.hpp
├── linux_sbus
├── CMakeLists.txt
├── linux_sbus.cpp
└── linux_sbus.h
├── rpi_pca9685_pwm_out
├── CMakeLists.txt
├── PCA9685.cpp
├── PCA9685.h
├── rpi_pca9685_pwm_out.cpp
└── rpi_pca9685_pwm_out.h
└── rpi_rc_in
├── CMakeLists.txt
├── rpi_rc_in.cpp
└── rpi_rc_in.h
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | raspberry-pi-px4firmware
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # raspberry-pi-px4firmware
2 | 树莓派飞控模块(遥控输入,PWM输出,编译配置文件,启动配置文件)
3 |
4 | # 使用方法
5 |
6 | git clone https://github.com/crossa/raspberry-pi-px4firmware
7 |
8 | git clone https://github.com/PX4/Firmware.git
9 |
10 | cd Firmware/
11 |
12 | git checkout <分支版本号> #此处必须要做,否则编译会出错,因为主程序里面会读取版本号,切换过分枝才会有版本号
13 |
14 | cp -rf raspberry-pi-px4firmware/* Firmware/
15 |
16 | # 追加环境变量
17 | export AUTOPILOT_HOST=XXX.XXX.XXX #此处填写ip地址
18 |
19 | export RPI_TOOLCHAIN_DIR= #工具链目录,bin目录上一层
20 |
21 | export CROSS_COMPILE_PREFIX= # 工具链前缀
22 |
23 | export PATH=$RPI_TOOLCHAIN_DIR/bin:$PATH
24 |
25 |
26 | #编译飞控固件,遇到子模块版本相关提示,默认选Y
27 |
28 | make posix_rpi_cross_single
29 |
30 | # 上传固件
31 |
32 | make posix_rpi_cross_signle upload
33 |
34 | # 首次启动飞控
35 |
36 | 登录到飞控主机后
37 |
38 | ./px4 px4_rpi.config
39 |
40 |
41 | # 注意事项
42 |
43 | 此飞控模块需配合PPM解码模块使用
44 |
45 | git clone https://github.com/crossa/raspberry-pi-ppm-rc-in
46 |
47 | ./configuration
48 |
49 | make
50 |
51 | make install
52 |
53 | sudo nohup ppmdecode -P
54 |
--------------------------------------------------------------------------------
/cmake/configs/posix_rpi_cross_no_shield.cmake:
--------------------------------------------------------------------------------
1 | # 使用这个文件可在上位机交叉编译px4firmware
2 | # use this file to cross compile px4 for raspberry pi without any shield
3 | include(configs/posix_rpi_common)
4 |
5 | if("$ENV{RPI_USE_CLANG}" STREQUAL "1")
6 | set(CMAKE_TOOLCHAIN_FILE ${PX4_SOURCE_DIR}/cmake/toolchains/Toolchain-arm-linux-gnueabihf-raspbian-clang.cmake)
7 | else()
8 | set(CMAKE_TOOLCHAIN_FILE ${PX4_SOURCE_DIR}/cmake/toolchains/Toolchain-arm-linux-gnueabihf-raspbian.cmake)
9 | endif()
10 |
11 | set(CMAKE_PROGRAM_PATH
12 | "${RPI_TOOLCHAIN_DIR}/gcc-linaro-arm-linux-gnueabihf-raspbian/bin"
13 | ${CMAKE_PROGRAM_PATH}
14 | )
15 |
--------------------------------------------------------------------------------
/cmake/configs/posix_rpi_cross_single.cmake:
--------------------------------------------------------------------------------
1 | # 使用这个文件可在上位机交叉编译px4firmware
2 | include(configs/posix_rpi_common)
3 |
4 | # 设定交叉工具链
5 | set(CMAKE_TOOLCHAIN_FILE ${PX4_SOURCE_DIR}/cmake/toolchains/Toolchain-arm-bcm2835-linux-gnueabihf-raspbian.cmake)
6 |
7 |
--------------------------------------------------------------------------------
/cmake/configs/posix_rpi_native_single.cmake:
--------------------------------------------------------------------------------
1 | # This file is shared between posix_rpi_native.cmake
2 | # and posix_rpi_cross.cmake.
3 |
4 | include(posix/px4_impl_posix)
5 |
6 | # This definition allows to differentiate if this just the usual POSIX build
7 | # or if it is for the RPi.
8 | add_definitions(
9 | -D__PX4_POSIX_RPI
10 | -D__DF_LINUX # For DriverFramework
11 | -D__DF_RPI # For raspberry pi
12 | )
13 |
14 |
15 | set(config_module_list
16 | #
17 | # Board support modules
18 | #
19 | drivers/device
20 | modules/sensors
21 | platforms/posix/drivers/df_mpu9250_wrapper
22 | #platforms/posix/drivers/df_lsm9ds1_wrapper
23 | platforms/posix/drivers/df_ms5611_wrapper
24 | #platforms/posix/drivers/df_hmc5883_wrapper
25 | platforms/posix/drivers/df_trone_wrapper
26 | #platforms/posix/drivers/df_isl29501_wrapper
27 |
28 | #
29 | # System commands
30 | #
31 | systemcmds/param
32 | systemcmds/mixer
33 | systemcmds/ver
34 | systemcmds/esc_calib
35 | systemcmds/reboot
36 | systemcmds/topic_listener
37 | systemcmds/perf
38 |
39 | #
40 | # Estimation modules
41 | #
42 | modules/attitude_estimator_q
43 | modules/position_estimator_inav
44 | modules/local_position_estimator
45 | modules/ekf2
46 |
47 | #
48 | # Vehicle Control
49 | #
50 | modules/mc_att_control
51 | modules/mc_pos_control
52 | modules/fw_att_control
53 | modules/fw_pos_control_l1
54 | modules/vtol_att_control
55 |
56 | #
57 | # Library modules
58 | #
59 | modules/sdlog2
60 | modules/logger
61 | modules/commander
62 | modules/param
63 | modules/systemlib
64 | modules/systemlib/mixer
65 | modules/uORB
66 | modules/dataman
67 | modules/land_detector
68 | modules/navigator
69 | modules/mavlink
70 |
71 | #
72 | # PX4 drivers
73 | #
74 | drivers/gps
75 | drivers/rpi_rc_in
76 | drivers/rpi_pca9685_pwm_out
77 | #drivers/navio_sysfs_rc_in
78 | #drivers/navio_sysfs_pwm_out
79 | #drivers/navio_gpio
80 | #drivers/navio_rgbled
81 |
82 | #
83 | # Libraries
84 | #
85 | lib/controllib
86 | lib/mathlib
87 | lib/mathlib/math/filter
88 | lib/geo
89 | lib/ecl
90 | lib/geo_lookup
91 | lib/launchdetection
92 | lib/external_lgpl
93 | lib/conversion
94 | lib/terrain_estimation
95 | lib/runway_takeoff
96 | lib/tailsitter_recovery
97 | lib/DriverFramework/framework
98 |
99 | #
100 | # POSIX
101 | #
102 | platforms/common
103 | platforms/posix/px4_layer
104 | platforms/posix/work_queue
105 | )
106 |
107 | #
108 | # DriverFramework driver
109 | #
110 | set(config_df_driver_list
111 | mpu9250
112 | #lsm9ds1
113 | ms5611
114 | #hmc5883
115 | trone
116 | #isl29501
117 | )
118 |
119 | set(CMAKE_TOOLCHAIN_FILE ${PX4_SOURCE_DIR}/cmake/toolchains/Toolchain-native.cmake)
120 |
--------------------------------------------------------------------------------
/cmake/configs/toolchains/Toolchain-arm-bcm2835-linux-gnueabihf-raspbian.cmake:
--------------------------------------------------------------------------------
1 | # defines:
2 | #
3 | # NM
4 | # OBJCOPY
5 | # LD
6 | # CXX_COMPILER
7 | # C_COMPILER
8 | # CMAKE_SYSTEM_NAME
9 | # CMAKE_SYSTEM_VERSION
10 | # LINKER_FLAGS
11 | # CMAKE_EXE_LINKER_FLAGS
12 | # CMAKE_FIND_ROOT_PATH
13 | # CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
14 | # CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
15 | # CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
16 |
17 | include(CMakeForceCompiler)
18 |
19 | if ("$ENV{RPI_TOOLCHAIN_DIR}" STREQUAL "")
20 | message(FATAL_ERROR "RPI_TOOLCHAIN_DIR not set")
21 | else()
22 | set(RPI_TOOLCHAIN_DIR $ENV{RPI_TOOLCHAIN_DIR})
23 | endif()
24 |
25 | if ("$ENV{CROSS_COMPILE_PREFIX}" STREQUAL "")
26 | message(FATAL_ERROR "CROSS_COMPILE_PREFIX not set")
27 | else()
28 | set(CROSS_COMPILE_PREFIX $ENV{CROSS_COMPILE_PREFIX})
29 | endif()
30 |
31 |
32 |
33 |
34 |
35 | # this one is important
36 | set(CMAKE_SYSTEM_NAME Generic)
37 |
38 | #this one not so much
39 | set(CMAKE_SYSTEM_VERSION 1)
40 |
41 | # specify the cross compiler
42 | find_program(C_COMPILER ${CROSS_COMPILE_PREFIX}-gcc
43 | PATHS ${RPI_TOOLCHAIN_DIR}/bin
44 | NO_DEFAULT_PATH
45 | )
46 |
47 | if(NOT C_COMPILER)
48 | message(FATAL_ERROR "could not find ${CROSS_COMPILE_PREFIX}-gcc compiler")
49 | endif()
50 | cmake_force_c_compiler(${C_COMPILER} GNU)
51 |
52 | find_program(CXX_COMPILER ${CROSS_COMPILE_PREFIX}-g++
53 | PATHS ${RPI_TOOLCHAIN_DIR}/bin
54 | NO_DEFAULT_PATH
55 | )
56 |
57 | if(NOT CXX_COMPILER)
58 | message(FATAL_ERROR "could not find ${CROSS_COMPILE_PREFIX}-g++ compiler")
59 | endif()
60 | cmake_force_cxx_compiler(${CXX_COMPILER} GNU)
61 |
62 | # compiler tools
63 | foreach(tool objcopy nm ld)
64 | string(TOUPPER ${tool} TOOL)
65 | find_program(${TOOL} ${CROSS_COMPILE_PREFIX}-${tool}
66 | PATHS ${RPI_TOOLCHAIN_DIR}/bin
67 | NO_DEFAULT_PATH
68 | )
69 | if(NOT ${TOOL})
70 | message(FATAL_ERROR "could not find ${CROSS_COMPILE_PREFIX}-${tool}")
71 | endif()
72 | endforeach()
73 |
74 | # os tools
75 | foreach(tool echo grep rm mkdir nm cp touch make unzip)
76 | string(TOUPPER ${tool} TOOL)
77 | find_program(${TOOL} ${tool})
78 | if(NOT ${TOOL})
79 | message(FATAL_ERROR "could not find ${TOOL}")
80 | endif()
81 | endforeach()
82 |
83 | add_definitions(
84 | -D __DF_RPI
85 | )
86 |
87 | set(LINKER_FLAGS "-Wl,-gc-sections")
88 | set(CMAKE_EXE_LINKER_FLAGS ${LINKER_FLAGS})
89 | set(CMAKE_C_FLAGS ${C_FLAGS})
90 | set(CMAKE_CXX_LINKER_FLAGS ${C_FLAGS})
91 |
92 | # where is the target environment
93 | set(CMAKE_FIND_ROOT_PATH get_file_component(${C_COMPILER} PATH))
94 |
95 | # search for programs in the build host directories
96 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
97 | # for libraries and headers in the target directories
98 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
99 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--------------------------------------------------------------------------------
/cmake/configs/toolchains/Toolchain-cross-generic.cmake:
--------------------------------------------------------------------------------
1 | # defines:
2 | #
3 | # NM
4 | # OBJCOPY
5 | # LD
6 | # CXX_COMPILER
7 | # C_COMPILER
8 | # CMAKE_SYSTEM_NAME
9 | # CMAKE_SYSTEM_VERSION
10 | # LINKER_FLAGS
11 | # CMAKE_EXE_LINKER_FLAGS
12 | # CMAKE_FIND_ROOT_PATH
13 | # CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
14 | # CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
15 | # CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
16 |
17 | include(CMakeForceCompiler)
18 |
19 | if ("$ENV{TOOLCHAIN_BIN_DIR}" STREQUAL "")
20 | message(FATAL_ERROR "TOOLCHAIN_BIN_DIR not set")
21 | else()
22 | set(TOOLCHAIN_BIN_DIR $ENV{TOOLCHAIN_BIN_DIR})
23 | endif()
24 |
25 | if ("$ENV{CROSS_COMPILE}" STREQUAL "")
26 | message(FATAL_ERROR "CROSS_COMPILE not set")
27 | else()
28 | set(CROSS_COMPILE $ENV{CROSS_COMPILE})
29 | endif()
30 |
31 | # 此处定义CROSS_COMPILE
32 | set(CROSS_COMPILE $ENV{CROSS_COMPILE})
33 |
34 | # this one is important
35 | set(CMAKE_SYSTEM_NAME Generic)
36 |
37 | #this one not so much
38 | set(CMAKE_SYSTEM_VERSION 1)
39 |
40 | # specify the cross compiler
41 | find_program(C_COMPILER ${CROSS_COMPILE}gcc
42 | PATHS ${TOOLCHAIN_BIN_DIR}
43 | NO_DEFAULT_PATH
44 | )
45 |
46 | if(NOT C_COMPILER)
47 | message(FATAL_ERROR "could not find ${CROSS_COMPILE}gcc compiler")
48 | endif()
49 | cmake_force_c_compiler(${C_COMPILER} GNU)
50 |
51 | find_program(CXX_COMPILER ${CROSS_COMPILE}g++
52 | PATHS ${TOOLCHAIN_BIN_DIR}
53 | NO_DEFAULT_PATH
54 | )
55 | if(NOT CXX_COMPILER)
56 | message(FATAL_ERROR "could not find ${CROSS_COMPILE}g++ compiler")
57 | endif()
58 | cmake_force_cxx_compiler(${CXX_COMPILER} GNU)
59 |
60 | # compiler tools
61 | foreach(tool objcopy nm ld)
62 | string(TOUPPER ${tool} TOOL)
63 | find_program(${TOOL} ${CROSS_COMPILE}${tool}
64 | PATHS ${TOOLCHAIN_BIN_DIR}
65 | NO_DEFAULT_PATH
66 | )
67 | if(NOT ${TOOL})
68 | message(FATAL_ERROR "could not find ${CROSS_COMPILE}${tool}")
69 | endif()
70 | endforeach()
71 |
72 | # os tools
73 | foreach(tool echo grep rm mkdir nm cp touch make unzip)
74 | string(TOUPPER ${tool} TOOL)
75 | find_program(${TOOL} ${tool})
76 | if(NOT ${TOOL})
77 | message(FATAL_ERROR "could not find ${TOOL}")
78 | endif()
79 | endforeach()
80 |
81 | #add_definitions(
82 | # -D __DF_RPI
83 | #)
84 |
85 | set(LINKER_FLAGS "-Wl,-gc-sections")
86 | set(CMAKE_EXE_LINKER_FLAGS ${LINKER_FLAGS})
87 | set(CMAKE_C_FLAGS ${C_FLAGS})
88 | set(CMAKE_CXX_LINKER_FLAGS ${C_FLAGS})
89 |
90 | # where is the target environment
91 | set(CMAKE_FIND_ROOT_PATH get_file_component(${C_COMPILER} PATH))
92 |
93 | # search for programs in the build host directories
94 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
95 | # for libraries and headers in the target directories
96 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
97 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
98 |
--------------------------------------------------------------------------------
/cmake/toolchains/Toolchain-arm-bcm2835-linx-gnueabihf-raspbian.cmake:
--------------------------------------------------------------------------------
1 | # defines:
2 | #
3 | # NM
4 | # OBJCOPY
5 | # LD
6 | # CXX_COMPILER
7 | # C_COMPILER
8 | # CMAKE_SYSTEM_NAME
9 | # CMAKE_SYSTEM_VERSION
10 | # LINKER_FLAGS
11 | # CMAKE_EXE_LINKER_FLAGS
12 | # CMAKE_FIND_ROOT_PATH
13 | # CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
14 | # CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
15 | # CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
16 |
17 | include(CMakeForceCompiler)
18 |
19 | if ("$ENV{RPI_TOOLCHAIN_DIR}" STREQUAL "")
20 | message(FATAL_ERROR "RPI_TOOLCHAIN_DIR not set")
21 | else()
22 | set(RPI_TOOLCHAIN_DIR $ENV{RPI_TOOLCHAIN_DIR})
23 | endif()
24 |
25 | if ("$ENV{CROSS_COMPILE_PREFIX}" STREQUAL "")
26 | message(FATAL_ERROR "CROSS_COMPILE_PREFIX not set")
27 | else()
28 | set(CROSS_COMPILE_PREFIX $ENV{CROSS_COMPILE_PREFIX})
29 | endif()
30 |
31 |
32 |
33 |
34 |
35 | # this one is important
36 | set(CMAKE_SYSTEM_NAME Generic)
37 |
38 | #this one not so much
39 | set(CMAKE_SYSTEM_VERSION 1)
40 |
41 | # specify the cross compiler
42 | find_program(C_COMPILER ${CROSS_COMPILE_PREFIX}-gcc
43 | PATHS ${RPI_TOOLCHAIN_DIR}/bin
44 | NO_DEFAULT_PATH
45 | )
46 |
47 | if(NOT C_COMPILER)
48 | message(FATAL_ERROR "could not find ${CROSS_COMPILE_PREFIX}-gcc compiler")
49 | endif()
50 | cmake_force_c_compiler(${C_COMPILER} GNU)
51 |
52 | find_program(CXX_COMPILER ${CROSS_COMPILE_PREFIX}-g++
53 | PATHS ${RPI_TOOLCHAIN_DIR}/bin
54 | NO_DEFAULT_PATH
55 | )
56 |
57 | if(NOT CXX_COMPILER)
58 | message(FATAL_ERROR "could not find ${CROSS_COMPILE_PREFIX}-g++ compiler")
59 | endif()
60 | cmake_force_cxx_compiler(${CXX_COMPILER} GNU)
61 |
62 | # compiler tools
63 | foreach(tool objcopy nm ld)
64 | string(TOUPPER ${tool} TOOL)
65 | find_program(${TOOL} ${CROSS_COMPILE_PREFIX}-${tool}
66 | PATHS ${RPI_TOOLCHAIN_DIR}/bin
67 | NO_DEFAULT_PATH
68 | )
69 | if(NOT ${TOOL})
70 | message(FATAL_ERROR "could not find ${CROSS_COMPILE_PREFIX}-${tool}")
71 | endif()
72 | endforeach()
73 |
74 | # os tools
75 | foreach(tool echo grep rm mkdir nm cp touch make unzip)
76 | string(TOUPPER ${tool} TOOL)
77 | find_program(${TOOL} ${tool})
78 | if(NOT ${TOOL})
79 | message(FATAL_ERROR "could not find ${TOOL}")
80 | endif()
81 | endforeach()
82 |
83 | add_definitions(
84 | -D __DF_RPI
85 | )
86 |
87 | set(LINKER_FLAGS "-Wl,-gc-sections")
88 | set(CMAKE_EXE_LINKER_FLAGS ${LINKER_FLAGS})
89 | set(CMAKE_C_FLAGS ${C_FLAGS})
90 | set(CMAKE_CXX_LINKER_FLAGS ${C_FLAGS})
91 |
92 | # where is the target environment
93 | set(CMAKE_FIND_ROOT_PATH get_file_component(${C_COMPILER} PATH))
94 |
95 | # search for programs in the build host directories
96 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
97 | # for libraries and headers in the target directories
98 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
99 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
100 |
--------------------------------------------------------------------------------
/posix-configs/arm/px4_linux.config:
--------------------------------------------------------------------------------
1 | uorb start
2 | param load
3 | param set SYS_AUTOSTART 4001
4 | param set MAV_BROADCAST 1
5 | param set MAV_TYPE 2
6 | param set SYS_MC_EST_GROUP 2
7 | param set BAT_CNT_V_VOLT 0.001
8 | param set BAT_V_DIV 10.9176300578
9 | param set BAT_CNT_V_CURR 0.001
10 | param set BAT_A_PER_V 15.391030303
11 | dataman start
12 | df_mpu9250_wrapper start -R 10
13 | #df_ms5611_wrapper start
14 | #gps start -d /dev/spidev0.0 -i spi -p ubx
15 | sensors start
16 | commander start
17 | navigator start
18 | ekf2 start
19 | land_detector start multicopter
20 | mc_pos_control start
21 | mc_att_control start
22 | mavlink start -u 14556 -r 1000000
23 | mavlink stream -u 14556 -s HIGHRES_IMU -r 50
24 | mavlink stream -u 14556 -s ATTITUDE -r 50
25 | #mavlink start -d /dev/ttyUSB0
26 | #mavlink stream -d /dev/ttyUSB0 -s HIGHRES_IMU -r 50
27 | #mavlink stream -d /dev/ttyUSB0 -s ATTITUDE -r 50
28 | linux_sbus start -d /dev/serial2 -c 8
29 | logger start -t -b 200
30 | mavlink boot_complete
31 |
--------------------------------------------------------------------------------
/posix-configs/rpi/px4.config:
--------------------------------------------------------------------------------
1 | uorb start
2 | param load
3 | param set SYS_AUTOSTART 4001
4 | param set MAV_BROADCAST 1
5 | param set MAV_TYPE 2
6 | param set SYS_MC_EST_GROUP 2
7 | param set BAT_CNT_V_VOLT 0.001
8 | param set BAT_V_DIV 10.9176300578
9 | param set BAT_CNT_V_CURR 0.001
10 | param set BAT_A_PER_V 15.391030303
11 | dataman start
12 | df_lsm9ds1_wrapper start -R 4
13 | #df_mpu9250_wrapper start -R 10
14 | #df_hmc5883_wrapper start
15 | df_ms5611_wrapper start
16 | navio_rgbled start
17 | navio_adc start
18 | gps start -d /dev/spidev0.0 -i spi -p ubx
19 | sensors start
20 | commander start
21 | navigator start
22 | ekf2 start
23 | land_detector start multicopter
24 | mc_pos_control start
25 | mc_att_control start
26 | mavlink start -u 14556 -r 1000000
27 | mavlink stream -u 14556 -s HIGHRES_IMU -r 50
28 | mavlink stream -u 14556 -s ATTITUDE -r 50
29 | mavlink start -d /dev/ttyUSB0
30 | mavlink stream -d /dev/ttyUSB0 -s HIGHRES_IMU -r 50
31 | mavlink stream -d /dev/ttyUSB0 -s ATTITUDE -r 50
32 | navio_sysfs_rc_in start
33 | navio_sysfs_pwm_out start
34 | logger start -t -b 200
35 | mavlink boot_complete
36 |
--------------------------------------------------------------------------------
/posix-configs/rpi/px4_fw.config:
--------------------------------------------------------------------------------
1 | uorb start
2 | param load
3 | param set MAV_BROADCAST 1
4 | #param set SYS_AUTOSTART 2104
5 | param set MAV_TYPE 1
6 | param set SYS_MC_EST_GROUP 2
7 | param set BAT_CNT_V_VOLT 0.001
8 | param set BAT_V_DIV 10.9176300578
9 | param set BAT_CNT_V_CURR 0.001
10 | param set BAT_A_PER_V 15.391030303
11 | dataman start
12 | df_lsm9ds1_wrapper start -R 4
13 | df_ms5611_wrapper start
14 | navio_rgbled start
15 | navio_adc start
16 | gps start -d /dev/spidev0.0 -i spi -p ubx
17 | sensors start
18 | commander start
19 | navigator start
20 | ekf2 start
21 | fw_att_control start
22 | fw_pos_control_l1 start
23 | mavlink start -u 14556 -r 1000000
24 | sleep 1
25 | mavlink stream -u 14556 -s HIGHRES_IMU -r 20
26 | mavlink stream -u 14556 -s ATTITUDE -r 20
27 | mavlink stream -u 14556 -s MANUAL_CONTROL -r 10
28 |
29 |
30 | navio_sysfs_rc_in start
31 | navio_sysfs_pwm_out start -m ROMFS/px4fmu_common/mixers/AERT.main.mix
32 | logger start -t -b 200
33 | mavlink boot_complete
34 |
--------------------------------------------------------------------------------
/posix-configs/rpi/px4_hil.config:
--------------------------------------------------------------------------------
1 | # HITL configuration
2 | # connect to it with jMAVSim:
3 | # ./Tools/jmavsim_run.sh -q -i -p 14577 -r 250
4 |
5 | uorb start
6 | param load
7 | param set SYS_AUTOSTART 1001
8 | param set MAV_BROADCAST 1
9 | param set MAV_TYPE 2
10 | param set SYS_MC_EST_GROUP 0
11 | dataman start
12 | sensors start -hil
13 | commander start -hil
14 | navigator start
15 | ekf2 start
16 | land_detector start multicopter
17 | mc_pos_control start
18 | mc_att_control start
19 | mavlink start -u 14577 -r 1000000
20 | navio_sysfs_rc_in start
21 | pwm_out_sim mode_pwm16
22 | mixer load /dev/pwm_output0 ROMFS/px4fmu_common/mixers/quad_x.main.mix
23 | logger start -t -b 200
24 | mavlink boot_complete
25 |
26 |
--------------------------------------------------------------------------------
/posix-configs/rpi/px4_no_shield.config:
--------------------------------------------------------------------------------
1 | uorb start
2 | param load
3 | param set SYS_AUTOSTART 4001
4 | param set MAV_BROADCAST 1
5 | sleep 1
6 | param set MAV_TYPE 2
7 | df_mpu9250_wrapper start -R 10
8 | df_ms5611_wrapper start
9 | gps start -d /dev/ttyACM0 -i uart -p ubx
10 | sensors start
11 | commander start
12 | attitude_estimator_q start
13 | position_estimator_inav start
14 | land_detector start multicopter
15 | mc_pos_control start
16 | mc_att_control start
17 | mavlink start -u 14556 -r 1000000
18 | sleep 1
19 | mavlink stream -u 14556 -s HIGHRES_IMU -r 50
20 | mavlink stream -u 14556 -s ATTITUDE -r 50
21 | #mavlink start -d /dev/ttyUSB0
22 | #mavlink stream -d /dev/ttyUSB0 -s HIGHRES_IMU -r 50
23 | #mavlink stream -d /dev/ttyUSB0 -s ATTITUDE -r 50
24 | rpi_rc_in start
25 | rpi_pca9685_pwm_out start
26 | logger start -t
27 | mavlink boot_complete
28 |
--------------------------------------------------------------------------------
/posix-configs/rpi/px4_noshield.config:
--------------------------------------------------------------------------------
1 | uorb start
2 | param load
3 | param set SYS_AUTOSTART 4001
4 | param set MAV_BROADCAST 1
5 | sleep 1
6 | param set MAV_TYPE 2
7 | df_mpu9250_wrapper start
8 | df_ms5611_wrapper start
9 | gps start -d /dev/ttyACM0 -i uart -p ubx
10 | sensors start
11 | commander start
12 | attitude_estimator_q start
13 | position_estimator_inav start
14 | land_detector start multicopter
15 | mc_pos_control start
16 | mc_att_control start
17 | mavlink start -u 14556 -r 1000000
18 | sleep 1
19 | mavlink stream -u 14556 -s HIGHRES_IMU -r 50
20 | mavlink stream -u 14556 -s ATTITUDE -r 50
21 | #mavlink start -d /dev/ttyUSB0
22 | #mavlink stream -d /dev/ttyUSB0 -s HIGHRES_IMU -r 50
23 | #mavlink stream -d /dev/ttyUSB0 -s ATTITUDE -r 50
24 | rpi_rc_in start
25 | rpi_pca9685_pwm_out start
26 | #navio_sysfs_pwm_out start
27 | logger start -t
28 | mavlink boot_complete
29 |
--------------------------------------------------------------------------------
/posix-configs/rpi/px4_rpi.config:
--------------------------------------------------------------------------------
1 | uorb start
2 | param load
3 | param set SYS_AUTOSTART 4001
4 | param set MAV_BROADCAST 1
5 | sleep 1
6 | param set MAV_TYPE 2
7 | df_mpu9250_wrapper start -R 10
8 | df_ms5611_wrapper start
9 | #gps start -d /dev/spidev0.0 -i spi -p ubx
10 | sensors start
11 | commander start
12 | attitude_estimator_q start
13 | position_estimator_inav start
14 | land_detector start multicopter
15 | mc_pos_control start
16 | mc_att_control start
17 | mavlink start -u 14556 -r 1000000
18 | sleep 1
19 | mavlink stream -u 14556 -s HIGHRES_IMU -r 50
20 | mavlink stream -u 14556 -s ATTITUDE -r 50
21 | #mavlink start -d /dev/ttyUSB0
22 | #mavlink stream -d /dev/ttyUSB0 -s HIGHRES_IMU -r 50
23 | #mavlink stream -d /dev/ttyUSB0 -s ATTITUDE -r 50
24 | rpi_rc_in start
25 | #navio_sysfs_pwm_out start
26 | logger start -t
27 | mavlink boot_complete
28 |
--------------------------------------------------------------------------------
/src/drivers/linux_pca9685/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ############################################################################
2 | #
3 | # Copyright (c) 2015-2016 PX4 Development Team. All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions
7 | # are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # 2. Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in
13 | # the documentation and/or other materials provided with the
14 | # distribution.
15 | # 3. Neither the name PX4 nor the names of its contributors may be
16 | # used to endorse or promote products derived from this software
17 | # without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 | #
32 | ############################################################################
33 | px4_add_module(
34 | MODULE drivers__linux_pca9685
35 | MAIN linux_pca9685
36 | COMPILE_FLAGS
37 | SRCS
38 | linux_pca9685.cpp
39 | DEPENDS
40 | platforms__common
41 | )
42 | # vim: set noet ft=cmake fenc=utf-8 ff=unix :
43 |
--------------------------------------------------------------------------------
/src/drivers/linux_pca9685/linux_pca9685.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (c) 2015-2016 PX4 Development Team. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in
13 | * the documentation and/or other materials provided with the
14 | * distribution.
15 | * 3. Neither the name PX4 nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software
17 | * without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | * POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | ****************************************************************************/
33 | #include "linux_pca9685.hpp"
34 |
35 | using namespace linux_pca9685;
36 | //--------------------------------------------------------------------------//
37 | int linux_pca9685::mixer_control_callback(uintptr_t handle,
38 | uint8_t control_group, uint8_t control_index, float &input) {
39 | const actuator_controls_s *controls = (actuator_controls_s *) handle;
40 | input = controls[control_group].control[control_index];
41 |
42 | return 0;
43 | }
44 |
45 | //----------------------------------------------------------------------------//
46 | int linux_pca9685::initialize_mixer(const char *mixer_filename) {
47 | char buf[4096];
48 | unsigned buflen = sizeof(buf);
49 | memset(buf, '\0', buflen);
50 |
51 | _mixer_group = new MixerGroup(mixer_control_callback,
52 | (uintptr_t) &_controls);
53 |
54 | // PX4_INFO("Trying to initialize mixer from config file %s", mixer_filename);
55 |
56 | if (load_mixer_file(mixer_filename, buf, buflen) == 0) {
57 | if (_mixer_group->load_from_buf(buf, buflen) == 0) {
58 | PX4_INFO("Loaded mixer from file %s", mixer_filename);
59 | return 0;
60 |
61 | } else {
62 | PX4_ERR("Unable to parse from mixer config file %s",
63 | mixer_filename);
64 | }
65 |
66 | } else {
67 | PX4_ERR("Unable to load config file %s", mixer_filename);
68 | }
69 |
70 | if (_mixer_group->count() <= 0) {
71 | PX4_ERR("Mixer initialization failed");
72 | return -1;
73 | }
74 |
75 | return 0;
76 | }
77 | //-----------------------------------------------------------------------------//
78 | int linux_pca9685::open_device() {
79 | /*configure pca9685*/
80 | if (0 > (device_fd = open(device_path, O_RDWR))) {
81 | PX4_ERR("Couldn't open pca9685 on %s,errno: %d .", device_path, errno);
82 | close(device_fd);
83 | return -1;
84 | }
85 | if (0 > ioctl(device_fd, I2C_SLAVE, PCA_9685_ADDR)) {
86 | PX4_ERR("Couldnn't set pca9685 as slave,errno: %d .", errno);
87 | close(device_fd);
88 | return -1;
89 | }
90 | return 0;
91 | }
92 |
93 | //----------------------------------------------------------------------------//
94 | int linux_pca9685::pwm_initialize() {
95 | /**************初始化PCA9685开始*************/
96 | /**************PCA965 initializing********/
97 | /*configure pca9685*/
98 | if(0>linux_pca9685::open_device())
99 | return -1;
100 | //Normal mode
101 | if (-1 == write_byte(device_fd, MODE1, 0x00)) {
102 | close(device_fd);
103 | return -1;
104 | }
105 | if (-1 == write_byte(device_fd, MODE2, 0x04)) {
106 | close(device_fd);
107 | return -1;
108 | }
109 |
110 | //set frequency,200HZ
111 | uint8_t prescale = (CLOCK_FREQ / MAX_PWM_RES / 200) - 1;
112 | uint8_t oldmode = 0;
113 | uint8_t newmode = (0 & 0x7F) | 0x10; //sleep
114 | write_byte(device_fd, MODE1, newmode); // go to sleep
115 | write_byte(device_fd, PRE_SCALE, prescale);
116 | write_byte(device_fd, MODE1, oldmode);
117 | usleep(10 * 1000);
118 | write_byte(device_fd, MODE1, oldmode | 0x80);
119 | /**************初始化PCA9685结束************/
120 | /**************PCA965 initialized********/
121 | close(device_fd);
122 | return 0;
123 | }
124 | //----------------------------------------------------------------------------//
125 | void linux_pca9685::pwm_deinitialize() {
126 | //Set output pwm as minmux pwm and reset
127 | if(0>linux_pca9685::open_device())
128 | return;
129 |
130 | uint16_t pwm[NUM_PWM];
131 | for (int start = 0; start < NUM_PWM; ++start) {
132 | pwm[start] = (uint16_t) _pwm_disarmed;
133 | }
134 | linux_pca9685::send_outputs_pwm(pwm);
135 | write_byte(device_fd, MODE1, 0x00);
136 | write_byte(device_fd, MODE2, 0x04);
137 | close(device_fd);
138 | }
139 | //----------------------------------------------------------------------------//
140 | void linux_pca9685::send_outputs_pwm(const uint16_t *pwm) {
141 | /*************向PCA9685发送数据*************/
142 | /*************send pwm signal to pca9685*************/
143 | if(0>linux_pca9685::open_device())
144 | return;
145 | int i;
146 |
147 | for (i = 0; i < NUM_PWM; ++i) {
148 | write_byte(device_fd, LED0_ON_L + LED_MULTIPLYER * i, 0 & 0xFF);
149 | write_byte(device_fd, LED0_ON_H + LED_MULTIPLYER * i, 0 >> 8);
150 | write_byte(device_fd, LED0_OFF_L + LED_MULTIPLYER * i,
151 | *(pwm + i) & 0xFF);
152 | write_byte(device_fd, LED0_OFF_H + LED_MULTIPLYER * i, *(pwm + i) >> 8);
153 | }
154 | close(device_fd);
155 | }
156 | //----------------------------------------------------------------------------//
157 | void linux_pca9685::subscribe() {
158 | memset(_controls, 0, sizeof(_controls));
159 | memset(_poll_fds, 0, sizeof(_poll_fds));
160 |
161 | /* set up ORB topic names */
162 | _controls_topics[0] = ORB_ID(actuator_controls_0);
163 | _controls_topics[1] = ORB_ID(actuator_controls_1);
164 | _controls_topics[2] = ORB_ID(actuator_controls_2);
165 | _controls_topics[3] = ORB_ID(actuator_controls_3);
166 |
167 | // Subscribe for orb topics
168 | for (uint8_t i = 0; i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS;
169 | i++) {
170 | if (_groups_required & (1 << i)) {
171 | PX4_DEBUG("subscribe to actuator_controls_%d", i);
172 | _controls_subs[i] = orb_subscribe(_controls_topics[i]);
173 |
174 | } else {
175 | _controls_subs[i] = -1;
176 | }
177 |
178 | if (_controls_subs[i] >= 0) {
179 | _poll_fds[_poll_fds_num].fd = _controls_subs[i];
180 | _poll_fds[_poll_fds_num].events = POLLIN;
181 | _poll_fds_num++;
182 | }
183 |
184 | _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
185 |
186 | }
187 | }
188 | //----------------------------------------------------------------------------//
189 | void linux_pca9685::task_main(int argc, char *argv[]) {
190 | _is_running = true;
191 |
192 | /***************初始化PCA9685************/
193 | /***************Inialize pca9685*************/
194 | linux_pca9685::pwm_initialize();
195 |
196 | // Set up mixer
197 | if (initialize_mixer(_mixer_filename) < 0) {
198 | PX4_ERR("无法初始化通道混合配置文件 Can't loading mixer file");
199 | return;
200 | }
201 |
202 | _mixer_group->groups_required(_groups_required);
203 | // subscribe and set up polling
204 | subscribe();
205 |
206 | // Start disarmed
207 | _armed.armed = false;
208 | _armed.prearmed = false;
209 |
210 | pwm_limit_init(&_pwm_limit);
211 |
212 | // Main loop
213 | while (!_task_should_exit) {
214 | int pret = px4_poll(_poll_fds, _poll_fds_num, 10);
215 |
216 | /* Timed out, do a periodic check for _task_should_exit. */
217 | if (pret == 0) {
218 | continue;
219 | }
220 |
221 | /* This is undesirable but not much we can do. */
222 | if (pret < 0) {
223 | PX4_WARN("poll error %d, %d", pret, errno);
224 | /* sleep a bit before next try */
225 | usleep(10000);
226 | continue;
227 | }
228 |
229 | /* get controls for required topics */
230 | unsigned poll_id = 0;
231 |
232 | for (uint8_t i = 0;
233 | i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS; i++) {
234 | if (_controls_subs[i] >= 0) {
235 | if (_poll_fds[poll_id].revents & POLLIN) {
236 | orb_copy(_controls_topics[i], _controls_subs[i],
237 | &_controls[i]);
238 | }
239 |
240 | poll_id++;
241 | }
242 | }
243 |
244 | if (nullptr != _mixer_group) {
245 | _outputs.timestamp = hrt_absolute_time();
246 | /* do mixing */
247 | _outputs.noutputs = _mixer_group->mix(_outputs.output,
248 | _outputs.NUM_ACTUATOR_OUTPUTS,
249 | NULL);
250 |
251 | /* disable unused ports by setting their output to NaN */
252 | for (size_t i = _outputs.noutputs;
253 | i < _outputs.NUM_ACTUATOR_OUTPUTS; i++) {
254 | _outputs.output[i] = NAN;
255 | }
256 |
257 | const uint16_t reverse_mask = 0;
258 | uint16_t disarmed_pwm[NUM_PWM];
259 | uint16_t min_pwm[NUM_PWM];
260 | uint16_t max_pwm[NUM_PWM];
261 |
262 | for (unsigned int i = 0; i < NUM_PWM; i++) {
263 | disarmed_pwm[i] = _pwm_disarmed;
264 | min_pwm[i] = _pwm_min;
265 | max_pwm[i] = _pwm_max;
266 | }
267 |
268 | uint16_t pwm[4];
269 |
270 | // TODO FIXME: pre-armed seems broken
271 | pwm_limit_calc(_armed.armed,
272 | false /*_armed.prearmed*/, _outputs.noutputs, reverse_mask,
273 | disarmed_pwm, min_pwm, max_pwm, _outputs.output, pwm,
274 | &_pwm_limit);
275 |
276 | if (_armed.lockdown) {
277 | send_outputs_pwm(disarmed_pwm);
278 | } else {
279 | send_outputs_pwm(pwm);
280 | }
281 |
282 | if (_outputs_pub != nullptr) {
283 | orb_publish(ORB_ID(actuator_outputs), _outputs_pub, &_outputs);
284 |
285 | } else {
286 | _outputs_pub = orb_advertise(ORB_ID(actuator_outputs),
287 | &_outputs);
288 | }
289 |
290 | } else {
291 | PX4_ERR("Could not mix output! Exiting...");
292 | _task_should_exit = true;
293 | }
294 |
295 | bool updated;
296 | orb_check(_armed_sub, &updated);
297 |
298 | if (updated) {
299 | orb_copy(ORB_ID(actuator_armed), _armed_sub, &_armed);
300 | }
301 | }
302 | pwm_deinitialize();
303 |
304 | for (uint8_t i = 0; i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS;
305 | i++) {
306 | if (_controls_subs[i] >= 0) {
307 | orb_unsubscribe(_controls_subs[i]);
308 | }
309 | }
310 |
311 | orb_unsubscribe(_armed_sub);
312 |
313 | _is_running = false;
314 |
315 | }
316 | //----------------------------------------------------------------------------//
317 | void linux_pca9685::task_main_trampoline(int argc, char *argv[]) {
318 | task_main(argc, argv);
319 | }
320 | //----------------------------------------------------------------------------//
321 | void linux_pca9685::start() {
322 | ASSERT(_task_handle == -1);
323 | _task_should_exit = false;
324 | /* init pca9685 device*/
325 | if (-1 == linux_pca9685::pwm_initialize()) {
326 | return;
327 | }
328 | /* start the task */
329 | _task_handle = px4_task_spawn_cmd("pwm_out_main", SCHED_DEFAULT,
330 | SCHED_PRIORITY_MAX, 1500, (px4_main_t) &task_main_trampoline, nullptr);
331 |
332 | if (_task_handle < 0) {
333 | PX4_WARN("task start failed");
334 | return;
335 | }
336 |
337 | }
338 | //---------------------------------------------------------------------------------------------------------------------//
339 | int linux_pca9685::write_byte(int fd, uint8_t address, uint8_t data) {
340 | uint8_t buff[2];
341 | buff[0] = address;
342 | buff[1] = data;
343 | if (2 != write(fd, buff, sizeof(buff))) {
344 | PX4_ERR("Faild to write data into PCA9685, errno: %d", errno);
345 | usleep(5000);
346 | return -1;
347 | }
348 | return 0;
349 | }
350 | //----------------------------------------------------------------------------//
351 | void linux_pca9685::stop() {
352 | _task_should_exit = true;
353 |
354 | while (_is_running) {
355 | usleep(200000);
356 | PX4_INFO(".");
357 | }
358 | _task_handle = -1;
359 | }
360 | //----------------------------------------------------------------------------//
361 | void linux_pca9685::usage() {
362 | PX4_INFO(
363 | "usage: linux_pca9685 start [-d pca9685 device] -m mixerfile --motors 4");
364 | PX4_INFO(" -d pwmdevice : pca9685 device for pwm generation");
365 | PX4_INFO(" (default /sys/class/pwm/pwmchip0)");
366 | PX4_INFO(" -m mixerfile : path to mixerfile");
367 | PX4_INFO(" --motors quantity of motors : 4 is default");
368 | PX4_INFO(
369 | " (default ROMFS/px4fmu_common/mixers/quad_x.main.mix)");
370 | PX4_INFO(" linux_pca9685 stop");
371 | PX4_INFO(" linux_pca9685 status");
372 | }
373 | //----------------------------------------------------------------------------//
374 | int linux_pca9685_main(int argc, char **argv) {
375 | if (5 > argc) {
376 | linux_pca9685::usage();
377 | return 1;
378 | }
379 |
380 | int command = -1; //指令 0:start,1:stop 2:status
381 |
382 | //读取控制台参数
383 | int start;
384 | for (start = 0; start < argc; ++start) {
385 | if (0 == strcmp("start", *(argv + start))) {
386 | command = 0;
387 | continue;
388 | }
389 |
390 | if (0 == strcmp("stop", *(argv + start))) {
391 | command = 1;
392 | continue;
393 | }
394 |
395 | if (0 == strcmp("status", *(argv + start))) {
396 | command = 2;
397 | continue;
398 | }
399 |
400 | if (0 == strcmp("-d", *(argv + start))) {
401 | strncpy(device_path, *(argv + start + 1), sizeof(device_path));
402 | continue;
403 | }
404 |
405 | if (0 == strcmp("-m", *(argv + start + 1))) {
406 | strncpy(_mixer_filename, *(argv + start + 1),
407 | sizeof(_mixer_filename));
408 | continue;
409 | }
410 |
411 | if (0 == strcmp("--motors", *(argv + start))) {
412 | NUM_PWM = atoi(*(argv + start) + 1);
413 | if (NUM_PWM > 8 || NUM_PWM < 4)
414 | NUM_PWM = 4;
415 | continue;
416 | }
417 | }
418 |
419 | //如果没有接收到指令,则退出
420 | if (-1 == command) {
421 | linux_pca9685::usage();
422 | return 1;
423 | }
424 |
425 | // gets the parameters for the esc's pwm
426 | param_get(param_find("PWM_DISARMED"), &linux_pca9685::_pwm_disarmed);
427 | param_get(param_find("PWM_MIN"), &linux_pca9685::_pwm_min);
428 | param_get(param_find("PWM_MAX"), &linux_pca9685::_pwm_max);
429 |
430 | // 处理命令
431 | switch (command) {
432 | case 0: //start
433 | if (linux_pca9685::_is_running) {
434 | PX4_WARN("linux_pca9685 already running");
435 | return 1;
436 | }
437 | linux_pca9685::start();
438 | break;
439 | case 1: //stop;
440 | if (!linux_pca9685::_is_running) {
441 | PX4_WARN("linux_pca9685 is not running");
442 | return 1;
443 | }
444 | linux_pca9685::stop();
445 | break;
446 | case 2: //status
447 | PX4_WARN("linux_pca9685 is %s",
448 | linux_pca9685::_is_running ? "running" : "not running");
449 | break;
450 |
451 | }
452 | return 0;
453 | }
454 |
--------------------------------------------------------------------------------
/src/drivers/linux_pca9685/linux_pca9685.hpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (c) 2015-2016 zhangfan. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in
13 | * the documentation and/or other materials provided with the
14 | * distribution.
15 | * 3. Neither the name PX4 nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software
17 | * without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | * POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | ****************************************************************************/
33 |
34 | /**
35 | * @Author Zhangfna 421395590@qq.com
36 | *
37 | */
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include /* Standard I/O functions */
44 | #include
45 | #include /* Syslog functionallity */
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include // NAN
56 |
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 | #include
64 | #include
65 | #include
66 | #include
67 |
68 |
69 | // Register Definitions
70 | // 寄存器定义
71 | #define PCA_9685_ADDR 0x40 //Mode register 1
72 | #define MODE1 0x00 //Mode register 1
73 | #define MODE2 0x01 //Mode register 2
74 | #define SUBADR1 0x02 //I2C-bus subaddress 1
75 | #define SUBADR2 0x03 //I2C-bus subaddress 2
76 | #define SUBADR3 0x04 //I2C-bus subaddress 3
77 | #define ALLCALLADR 0x05 //LED All Call I2C-bus address
78 | #define LED0 0x6 //LED0 start register
79 | #define LED0_ON_L 0x6 //LED0 output and brightness control byte 0
80 | #define LED0_ON_H 0x7 //LED0 output and brightness control byte 1
81 | #define LED0_OFF_L 0x8 //LED0 output and brightness control byte 2
82 | #define LED0_OFF_H 0x9 //LED0 output and brightness control byte 3
83 | #define LED_MULTIPLYER 4 // For the other 15 channels
84 | #define ALLLED_ON_L 0xFA //load all the LEDn_ON registers, byte 0 (turn 0-7 channels on)
85 | #define ALLLED_ON_H 0xFB //load all the LEDn_ON registers, byte 1 (turn 8-15 channels on)
86 | #define ALLLED_OFF_L 0xFC //load all the LEDn_OFF registers, byte 0 (turn 0-7 channels off)
87 | #define ALLLED_OFF_H 0xFD //load all the LEDn_OFF registers, byte 1 (turn 8-15 channels off)
88 | #define PRE_SCALE 0xFE //prescaler for output frequency
89 | #define MAX_PWM_RES 4096 //Resolution 4096=12bit 分辨率,按2的阶乘计算,12bit为4096
90 | #define CLOCK_FREQ 25000000.0 //25MHz default osc clock
91 | #define BUFFER_SIZE 0x08 //1 byte buffer
92 | #define PCA9685_DEFAULT_I2C_ADDR 0x40 // default i2c address for pca9685 默认i2c地址为0x40
93 | #define PCA9685_DEFAULT_I2C_BUS 1 // default i2c bus for pca9685 默认为1
94 |
95 | namespace linux_pca9685
96 | {
97 | static px4_task_t _task_handle = -1;
98 | volatile bool _task_should_exit = false;
99 | static bool _is_running = false;
100 |
101 | static int NUM_PWM = 4;
102 |
103 |
104 | static const int FREQUENCY_PWM = 400;
105 | static char _mixer_filename[255] = "ROMFS/px4fmu_common/mixers/quad_x.main.mix";
106 |
107 | // subscriptions
108 | int _controls_subs[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
109 | int _armed_sub;
110 |
111 | // publications
112 | orb_advert_t _outputs_pub = nullptr;
113 | orb_advert_t _rc_pub = nullptr;
114 |
115 | // topic structures
116 | actuator_controls_s _controls[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
117 | orb_id_t _controls_topics[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
118 | actuator_outputs_s _outputs;
119 | actuator_armed_s _armed;
120 |
121 | // polling
122 | uint8_t _poll_fds_num = 0;
123 | px4_pollfd_struct_t _poll_fds[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
124 |
125 | // control groups related
126 | uint32_t _groups_required = 0;
127 | uint32_t _groups_subscribed = 0;
128 |
129 | pwm_limit_t _pwm_limit;
130 |
131 | // esc parameters
132 | int32_t _pwm_disarmed;
133 | int32_t _pwm_min;
134 | int32_t _pwm_max;
135 | MixerGroup *_mixer_group = nullptr;
136 |
137 | // device param
138 | int device_fd=-1;
139 | char device_path[30]="/dev/i2c-0";
140 |
141 | void usage();
142 |
143 | void start();
144 |
145 | void stop();
146 |
147 | int pwm_initialize();
148 |
149 | void pwm_deinitialize();
150 |
151 | int open_device();
152 |
153 | void send_outputs_pwm(const uint16_t *pwm);
154 |
155 | void task_main_trampoline(int argc, char *argv[]);
156 |
157 | void subscribe();
158 |
159 | void task_main(int argc, char *argv[]);
160 |
161 | int write_byte(int fd, uint8_t address, uint8_t data);
162 | /* mixer initialization */
163 | int initialize_mixer(const char *mixer_filename);
164 | int mixer_control_callback(uintptr_t handle, uint8_t control_group,
165 | uint8_t control_index, float &input);
166 | }
167 | extern "C" __EXPORT int linux_pca9685_main(int, char **);
168 |
--------------------------------------------------------------------------------
/src/drivers/linux_sbus/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ############################################################################
2 | #
3 | # Copyright (c) 2016 PX4 Development Team. All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions
7 | # are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # 2. Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in
13 | # the documentation and/or other materials provided with the
14 | # distribution.
15 | # 3. Neither the name PX4 nor the names of its contributors may be
16 | # used to endorse or promote products derived from this software
17 | # without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 | #
32 | ############################################################################
33 | px4_add_module(
34 | MODULE drivers__linux_sbus
35 | MAIN linux_sbus
36 | STACK_MAIN 1200
37 | COMPILE_FLAGS
38 | SRCS
39 | linux_sbus.cpp
40 | DEPENDS
41 | platforms__common
42 | )
43 | # vim: set noet ft=cmake fenc=utf-8 ff=unix :
44 |
--------------------------------------------------------------------------------
/src/drivers/linux_sbus/linux_sbus.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (C) 2015 Mark Charl. All rights reserved.
4 | * Copyright (C) 2017 Fan.zhang. All rights reserved. 421395590@qq.com
5 | * Copyright (C) 2016 PX4 Development Team. All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | *
11 | * 1. Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in
15 | * the documentation and/or other materials provided with the
16 | * distribution.
17 | * 3. Neither the name PX4 nor the names of its contributors may be
18 | * used to endorse or promote products derived from this software
19 | * without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | * POSSIBILITY OF SUCH DAMAGE.
33 | *
34 | ****************************************************************************/
35 | #include "linux_sbus.h"
36 |
37 | using namespace linux_sbus;
38 | //---------------------------------------------------------------------------------------------------------//
39 | int RcInput::init() {
40 | int i;
41 | //--------------发布所有通道的数据------------------------//
42 | for (i = 0; i < input_rc_s::RC_INPUT_MAX_CHANNELS; ++i) {
43 | _data.values[i] = UINT16_MAX;
44 | }
45 |
46 | _rcinput_pub = orb_advertise(ORB_ID(input_rc), &_data);
47 |
48 | if (nullptr == _rcinput_pub) {
49 | PX4_WARN("error: advertise failed");
50 | return -1;
51 | }
52 |
53 | //初始化串口,供sbus读写
54 | _device_fd = open(_device, O_RDWR | O_NONBLOCK | O_CLOEXEC);
55 | if (-1 == _device_fd) {
56 | PX4_ERR("Open SBUS input %s faild,status %d \n", _device,
57 | (int ) _device_fd);
58 | fflush (stdout);
59 | return -1;
60 | }
61 | struct termios2 tio { };
62 |
63 | if (0 != ioctl(_device_fd, TCGETS2, &tio)) {
64 | close(_device_fd);
65 | _device_fd = -1;
66 | return -1;
67 | }
68 | // Setting serial port,8E2, non-blocking.100Kbps
69 | tio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL
70 | | IXON);
71 | tio.c_iflag |= (INPCK | IGNPAR);
72 | tio.c_oflag &= ~OPOST;
73 | tio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
74 | tio.c_cflag &= ~(CSIZE | CRTSCTS | PARODD | CBAUD);
75 | // use BOTHER to specify speed directly in c_[io]speed member
76 | tio.c_cflag |= (CS8 | CSTOPB | CLOCAL | PARENB | BOTHER | CREAD);
77 | tio.c_ispeed = 100000;
78 | tio.c_ospeed = 100000;
79 | // see select() comment below
80 | tio.c_cc[VMIN] = 25;
81 | tio.c_cc[VTIME] = 0;
82 | if (0 != ioctl(_device_fd, TCSETS2, &tio)) {
83 | close(_device_fd);
84 | _device_fd = -1;
85 | return -1;
86 | }
87 | return 0;
88 | }
89 | //---------------------------------------------------------------------------------------------------------//
90 | int RcInput::start(char *device, int channels) {
91 | int result = 0;
92 | strcpy(_device, device);
93 | _channels = channels;
94 | result = init();
95 |
96 | if (0 != result) {
97 | PX4_WARN("error: RC initialization failed");
98 | return -1;
99 | }
100 |
101 | _isRunning = true;
102 | result = work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline,
103 | this, 0);
104 |
105 | if (result == -1) {
106 | _isRunning = false;
107 | }
108 |
109 | return result;
110 | }
111 | //---------------------------------------------------------------------------------------------------------//
112 | void RcInput::stop() {
113 | close(_device_fd);
114 | _shouldExit = true;
115 | }
116 | //---------------------------------------------------------------------------------------------------------//
117 | void RcInput::cycle_trampoline(void *arg) {
118 | RcInput *dev = reinterpret_cast(arg);
119 | dev->_cycle();
120 | }
121 | //---------------------------------------------------------------------------------------------------------//
122 | void RcInput::_cycle() {
123 | _measure();
124 |
125 | if (!_shouldExit) {
126 | work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline, this,
127 | USEC2TICK(RCINPUT_MEASURE_INTERVAL_US));
128 | }
129 | }
130 | //---------------------------------------------------------------------------------------------------------//
131 | void RcInput::_measure(void) {
132 | uint64_t ts;
133 |
134 | //开始解析SBUS数据
135 | int nread;
136 | fd_set fds;
137 | struct timeval tv;
138 | FD_ZERO(&fds);
139 | FD_SET(_device_fd, &fds);
140 | select(_device_fd + 1, &fds, nullptr, nullptr, &tv);
141 | int count = 0; //error counter;
142 | while (1) {
143 | nread = read(_device_fd, &_sbusData, sizeof(_sbusData));
144 | if (25 == nread) {
145 | if (0x0f == _sbusData[0] && 0x00 == _sbusData[24]) {
146 | break;
147 | }
148 | }
149 | ++count;
150 | usleep(RCINPUT_MEASURE_INTERVAL_US);
151 | }
152 |
153 | // pars sbus data to pwm
154 | _channels_data[0] = (uint16_t) (((_sbusData[1] | _sbusData[2] << 8) & 0x07FF)
155 | * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
156 | _channels_data[1] =
157 | (uint16_t) (((_sbusData[2] >> 3 | _sbusData[3] << 5) & 0x07FF)
158 | * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
159 | _channels_data[2] = (uint16_t) (((_sbusData[3] >> 6 | _sbusData[4] << 2
160 | | _sbusData[5] << 10) & 0x07FF) * SBUS_SCALE_FACTOR + .5f)
161 | + SBUS_SCALE_OFFSET;
162 | _channels_data[3] =
163 | (uint16_t) (((_sbusData[5] >> 1 | _sbusData[6] << 7) & 0x07FF)
164 | * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
165 | _channels_data[4] =
166 | (uint16_t) (((_sbusData[6] >> 4 | _sbusData[7] << 4) & 0x07FF)
167 | * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
168 | _channels_data[5] = (uint16_t) (((_sbusData[7] >> 7 | _sbusData[8] << 1
169 | | _sbusData[9] << 9) & 0x07FF) * SBUS_SCALE_FACTOR + .5f)
170 | + SBUS_SCALE_OFFSET;
171 | _channels_data[6] = (uint16_t) (((_sbusData[9] >> 2 | _sbusData[10] << 6)
172 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
173 | _channels_data[7] = (uint16_t) (((_sbusData[10] >> 5 | _sbusData[11] << 3)
174 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET; // & the other 8 + 2 channels if you need them
175 | _channels_data[8] = (uint16_t) (((_sbusData[12] | _sbusData[13] << 8) & 0x07FF)
176 | * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
177 | ;
178 | _channels_data[9] = (uint16_t) (((_sbusData[13] >> 3 | _sbusData[14] << 5)
179 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
180 | ;
181 | _channels_data[10] = (uint16_t) (((_sbusData[14] >> 6 | _sbusData[15] << 2
182 | | _sbusData[16] << 10) & 0x07FF) * SBUS_SCALE_FACTOR + .5f)
183 | + SBUS_SCALE_OFFSET;
184 | _channels_data[11] = (uint16_t) (((_sbusData[16] >> 1 | _sbusData[17] << 7)
185 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
186 | _channels_data[12] = (uint16_t) (((_sbusData[17] >> 4 | _sbusData[18] << 4)
187 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
188 | _channels_data[13] = (uint16_t) (((_sbusData[18] >> 7 | _sbusData[19] << 1
189 | | _sbusData[20] << 9) & 0x07FF) * SBUS_SCALE_FACTOR + .5f)
190 | + SBUS_SCALE_OFFSET;
191 | _channels_data[14] = (uint16_t) (((_sbusData[20] >> 2 | _sbusData[21] << 6)
192 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
193 | _channels_data[15] = (uint16_t) (((_sbusData[21] >> 5 | _sbusData[22] << 3)
194 | & 0x07FF) * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
195 |
196 | // PWM数据发布
197 | int i = 0;
198 | for (i = 0; i < _channels; ++i) {
199 | _data.values[i] = _channels_data[i];
200 | }
201 | ts = hrt_absolute_time();
202 | _data.timestamp = ts;
203 | _data.timestamp_last_signal = ts;
204 | _data.channel_count = _channels;
205 | _data.rssi = 100;
206 | _data.rc_lost_frame_count = 0;
207 | _data.rc_total_frame_count = 1;
208 | _data.rc_ppm_frame_length = 0;
209 | _data.rc_failsafe = (_sbusData[23] & (1 << 3)) ? true : false;
210 | _data.rc_lost = (_sbusData[23] & (1 << 2)) ? true : false;
211 | _data.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_SBUS;
212 | orb_publish(ORB_ID(input_rc), _rcinput_pub, &_data);
213 | }
214 | //---------------------------------------------------------------------------------------------------------//
215 | /**
216 | * Print the correct usage.
217 | */
218 |
219 | static void linux_sbus::usage(const char *reason) {
220 | if (reason) {
221 | PX4_ERR("%s", reason);
222 | }
223 | PX4_INFO("用法: linux_sbus {start|stop|status} -d -c ");
224 | }
225 | //---------------------------------------------------------------------------------------------------------//
226 | int linux_sbus_main(int argc, char **argv) {
227 | if (argc < 7) {
228 | usage("linux_sbus {start|stop|status} -d -c ");
229 | return 1;
230 | }
231 | int start;
232 | char device[30];
233 | int max_channel = 8; //8 channel for default setting
234 |
235 | // Get device and channels count from console
236 | for (start = 0; start < argc; ++start) {
237 | if (0 == strcmp(argv[start], "-d")) {
238 | strcpy(device, argv[start] + 1);
239 | continue;
240 | }
241 |
242 | if (0 == strcmp(argv[start], "-c")) {
243 | max_channel = atoi(argv[start]+1);
244 | continue;
245 | }
246 | }
247 | //Channels count should less than 16;
248 | max_channel = (max_channel > 16) ? 16 : max_channel;
249 |
250 | if (!strcmp(argv[1], "start")) {
251 |
252 | if (nullptr != rc_input && rc_input->isRunning()) {
253 | PX4_WARN("运行中。running");
254 | /* this is not an error */
255 | return 0;
256 | }
257 |
258 | rc_input = new RcInput();
259 |
260 | // Check if alloc worked.
261 | if (nullptr == rc_input) {
262 | PX4_ERR("遥控输入模块初始化错误。Rc input moduel initialization faild");
263 | return -1;
264 | }
265 |
266 | int ret = rc_input->start(device, max_channel);
267 |
268 | if (ret != 0) {
269 | PX4_ERR("遥控输入模块未能启动。 Rc input module failure");
270 | }
271 |
272 | return 0;
273 | }
274 |
275 | if (!strcmp(argv[1], "stop")) {
276 |
277 | if (rc_input == nullptr || !rc_input->isRunning()) {
278 | PX4_WARN("模块未运行。 Not runing");
279 | /* this is not an error */
280 | return 0;
281 | }
282 |
283 | rc_input->stop();
284 |
285 | // Wait for task to die
286 | int i = 0;
287 |
288 | do {
289 | /* wait up to 3s */
290 | usleep(100000);
291 |
292 | } while (rc_input->isRunning() && ++i < 30);
293 |
294 | delete rc_input;
295 | rc_input = nullptr;
296 |
297 | return 0;
298 | }
299 |
300 | if (!strcmp(argv[1], "status")) {
301 | if (rc_input != nullptr && rc_input->isRunning()) {
302 | PX4_INFO("运行中。 running");
303 |
304 | } else {
305 | PX4_INFO("未运行。 Not runing\n");
306 | }
307 |
308 | return 0;
309 | }
310 |
311 | usage("不知道你要做什么。 linux_sbus start|stop|status -d -c ");
312 | return 1;
313 |
314 | }
315 | //---------------------------------------------------------------------------------------------------------//
316 |
--------------------------------------------------------------------------------
/src/drivers/linux_sbus/linux_sbus.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (C) 2015 Mark Charl. All rights reserved.
4 | * Copyright (C) 2017 Fan.zhang. All rights reserved. 421395590@qq.com
5 | * Copyright (C) 2016 PX4 Development Team. All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | *
11 | * 1. Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in
15 | * the documentation and/or other materials provided with the
16 | * distribution.
17 | * 3. Neither the name PX4 nor the names of its contributors may be
18 | * used to endorse or promote products derived from this software
19 | * without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | * POSSIBILITY OF SUCH DAMAGE.
33 | *
34 | ****************************************************************************/
35 |
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include /*Unix 标准函数定义*/
43 | #include /*文件控制定义*/
44 | #include
45 | #include
46 | #include /*错误号定义*/
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #define RCINPUT_MEASURE_INTERVAL_US 4700
54 | /* define range mapping here, -+100% -> 1000..2000 */
55 | #define SBUS_RANGE_MIN 200.0f
56 | #define SBUS_RANGE_MAX 1800.0f
57 |
58 | #define SBUS_TARGET_MIN 1000.0f
59 | #define SBUS_TARGET_MAX 2000.0f
60 |
61 | /* pre-calculate the floating point stuff as far as possible at compile time */
62 | #define SBUS_SCALE_FACTOR ((SBUS_TARGET_MAX - SBUS_TARGET_MIN) / (SBUS_RANGE_MAX - SBUS_RANGE_MIN))
63 | #define SBUS_SCALE_OFFSET (int)(SBUS_TARGET_MIN - (SBUS_SCALE_FACTOR * SBUS_RANGE_MIN + 0.5f))
64 |
65 | namespace linux_sbus {
66 | class RcInput {
67 | public:
68 | RcInput() :
69 | _shouldExit(false), _isRunning(false), _work { }, _rcinput_pub(
70 | nullptr), //D8R-II plus
71 | _data { }, _sbusData { 0x0f, 0x01, 0x04, 0x20, 0x00, 0xff, 0x07,
72 | 0x40, 0x00, 0x02, 0x10, 0x80, 0x2c, 0x64, 0x21, 0x0b, 0x59,
73 | 0x08, 0x40, 0x00, 0x02, 0x10, 0x80, 0x00, 0x00 } {
74 | //memset(_ch_fd, 0, sizeof(_ch_fd));
75 | }
76 | ~RcInput() {
77 | work_cancel(HPWORK, &_work);
78 | _isRunning = false;
79 | close(_device_fd);
80 | }
81 |
82 | /* @return 0 on success, -errno on failure */
83 | int start(char *device, int channels);
84 |
85 | /* @return 0 on success, -errno on failure */
86 | void stop();
87 |
88 | /* Trampoline for the work queue. */
89 | static void cycle_trampoline(void *arg);
90 |
91 | bool isRunning() {
92 | return _isRunning;
93 | }
94 |
95 | private:
96 | void _cycle();
97 | void _measure();
98 | bool _shouldExit;
99 | bool _isRunning;
100 | struct work_s _work;
101 | orb_advert_t _rcinput_pub;
102 | struct input_rc_s _data;
103 | uint8_t _sbusData[25];
104 | int _channels;
105 | int _device_fd; // serial port device to read SBUS;
106 | int _channels_data[16]; // 16 channels support;
107 | uint8_t _buffer[25];
108 | char _device[30];
109 | bool _failsafe;
110 | bool _rc_loss;
111 | int init();
112 | };
113 |
114 | static void usage(const char *reason);
115 | static RcInput *rc_input = nullptr;
116 | }
117 | extern "C" __EXPORT int linux_sbus_main(int argc, char **argv);
118 |
--------------------------------------------------------------------------------
/src/drivers/rpi_pca9685_pwm_out/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ############################################################################
2 | #
3 | # Copyright (c) 2015-2016 PX4 Development Team. All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions
7 | # are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # 2. Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in
13 | # the documentation and/or other materials provided with the
14 | # distribution.
15 | # 3. Neither the name PX4 nor the names of its contributors may be
16 | # used to endorse or promote products derived from this software
17 | # without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 | #
32 | ############################################################################
33 | px4_add_module(
34 | MODULE drivers__rpi_pca9685_pwm_out
35 | MAIN rpi_pca9685_pwm_out
36 | COMPILE_FLAGS
37 | SRCS
38 | PCA9685.cpp
39 | rpi_pca9685_pwm_out.cpp
40 | DEPENDS
41 | platforms__common
42 | )
43 | # vim: set noet ft=cmake fenc=utf-8 ff=unix :
44 |
--------------------------------------------------------------------------------
/src/drivers/rpi_pca9685_pwm_out/PCA9685.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (c) 2015-2017 PX4 Development Team. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in
13 | * the documentation and/or other materials provided with the
14 | * distribution.
15 | * 3. Neither the name PX4 nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software
17 | * without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | * POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | *
33 | * Original Author : Georgi Todorov
34 | * Edited by : Tord Wessman
35 | * Created on : Nov 22, 2013
36 | * Rewrite : Fan.zhang 421395590@qq.com
37 | * Updated on : Mar 2, 2017
38 | ****************************************************************************/
39 |
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include /* Standard I/O functions */
45 | #include
46 | #include /* Syslog functionallity */
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | //
53 |
54 | #include "PCA9685.h"
55 |
56 | //! Constructor takes bus and address arguments
57 | /*!
58 | \param bus the bus to use in /dev/i2c-%d.
59 | \param address the device address on bus
60 | */
61 |
62 | void PCA9685::init(int bus, int address) {
63 | _i2cbus = bus;
64 | _i2caddr = address;
65 | snprintf(busfile, sizeof(busfile), "/dev/i2c-%d", bus);
66 | reset();
67 | //usleep(10*1000);
68 | }
69 |
70 |
71 | PCA9685::PCA9685() :
72 | _i2caddr(PCA9685_DEFAULT_I2C_ADDR),
73 | _i2cbus(PCA9685_DEFAULT_I2C_BUS),
74 | dataBuffer {}
75 | {
76 |
77 | }
78 |
79 | PCA9685::PCA9685(int bus,int address) :
80 | busfile {},
81 | dataBuffer {}
82 | {
83 | _i2cbus = bus;
84 | _i2caddr = address;
85 | snprintf(busfile, sizeof(busfile), "/dev/i2c-%d", bus);
86 | reset();
87 | }
88 |
89 | PCA9685::~PCA9685() {
90 | reset();
91 | }
92 | //! Sets PCA9685 mode to 00
93 | void PCA9685::reset() {
94 | int fd = openfd();
95 | if (fd != -1) {
96 | write_byte(fd, MODE1, 0x00); //Normal mode
97 | write_byte(fd, MODE2, 0x04); //Normal mode
98 | close(fd);
99 | }
100 | }
101 | //! Set the frequency of PWM
102 | /*!
103 | \param freq desired frequency. 40Hz to 1000Hz using internal 25MHz oscillator.
104 | */
105 | void PCA9685::setPWMFreq(int freq) {
106 | int fd = openfd();
107 | if (fd != -1) {
108 | uint8_t prescale = (CLOCK_FREQ / MAX_PWM_RES / freq) - 1;
109 | //printf ("Setting prescale value to: %d\n", prescale);
110 | //printf ("Using Frequency: %d\n", freq);
111 |
112 | uint8_t oldmode = read_byte(fd, MODE1);
113 | uint8_t newmode = (oldmode & 0x7F) | 0x10; //sleep
114 | write_byte(fd, MODE1, newmode); // go to sleep
115 | write_byte(fd, PRE_SCALE, prescale);
116 | write_byte(fd, MODE1, oldmode);
117 | usleep(10*1000);
118 | write_byte(fd, MODE1, oldmode | 0x80);
119 |
120 | close(fd);
121 | }
122 | }
123 |
124 | //! PWM a single channel
125 | /*!
126 | \param led channel to set PWM value for
127 | \param value 0-4095 value for PWM
128 | */
129 | void PCA9685::setPWM(uint8_t led, int value) {
130 | setPWM(led, 0, value);
131 | }
132 | //! PWM a single channel with custom on time
133 | /*!
134 | \param led channel to set PWM value for
135 | \param on_value 0-4095 value to turn on the pulse
136 | \param off_value 0-4095 value to turn off the pulse
137 | */
138 | void PCA9685::setPWM(uint8_t led, int on_value, int off_value) {
139 | int fd = openfd();
140 | if (fd != -1) {
141 |
142 | write_byte(fd, LED0_ON_L + LED_MULTIPLYER * led, on_value & 0xFF);
143 |
144 | write_byte(fd, LED0_ON_H + LED_MULTIPLYER * led, on_value >> 8);
145 |
146 | write_byte(fd, LED0_OFF_L + LED_MULTIPLYER * led, off_value & 0xFF);
147 |
148 | write_byte(fd, LED0_OFF_H + LED_MULTIPLYER * led, off_value >> 8);
149 |
150 | close(fd);
151 | }
152 |
153 | }
154 |
155 | //! Read a single byte from PCA9685
156 | /*!
157 | \param fd file descriptor for I/O
158 | \param address register address to read from
159 | */
160 | uint8_t PCA9685::read_byte(int fd, uint8_t address) {
161 |
162 | return 0;
163 |
164 | uint8_t buff[BUFFER_SIZE];
165 | buff[0] = address;
166 | if (write(fd, buff, BUFFER_SIZE) != BUFFER_SIZE) {
167 | printf("I2C slave 0x%x failed to go to register 0x%x [read_byte():write %d]", _i2caddr, address, errno);
168 | return (-1);
169 | } else {
170 | if (read(fd, dataBuffer, BUFFER_SIZE) != BUFFER_SIZE) {
171 | printf ("Could not read from I2C slave 0x%x, register 0x%x [read_byte():read %d]", _i2caddr, address, errno);
172 | return (-1);
173 | }
174 | }
175 |
176 |
177 | }
178 | //! Write a single byte from PCA9685
179 | /*!
180 | \param fd file descriptor for I/O
181 | \param address register address to write to
182 | \param data 8 bit data to write
183 | */
184 | void PCA9685::write_byte(int fd, uint8_t address, uint8_t data) {
185 | uint8_t buff[2];
186 | buff[0] = address;
187 | buff[1] = data;
188 | if (write(fd, buff, sizeof(buff)) != 2) {
189 | printf("Failed to write to I2C Slave 0x%x @ register 0x%x [write_byte():write %d]", _i2caddr, address, errno);
190 | usleep(5000);
191 | }else{
192 | //printf("Wrote to I2C Slave 0x%x @ register 0x%x [0x%x]\n", _i2caddr, address, data);
193 | }
194 | }
195 | //! Open device file for PCA9685 I2C bus
196 | /*!
197 | \return fd returns the file descriptor number or -1 on error
198 | */
199 | int PCA9685::openfd() {
200 | int fd;
201 | if ((fd = open(busfile, O_RDWR)) < 0) {
202 | printf ("Couldn't open I2C Bus %d [openfd():open %d]", _i2cbus, errno);
203 | return -1;
204 | }
205 | if (ioctl(fd, I2C_SLAVE, _i2caddr) < 0) {
206 | printf ("I2C slave %d failed [openfd():ioctl %d]", _i2caddr, errno);
207 | return -1;
208 | }
209 |
210 | return fd;
211 | }
212 |
--------------------------------------------------------------------------------
/src/drivers/rpi_pca9685_pwm_out/PCA9685.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (c) 2015-2017 PX4 Development Team. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in
13 | * the documentation and/or other materials provided with the
14 | * distribution.
15 | * 3. Neither the name PX4 nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software
17 | * without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | * POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | *
33 | * Original Author : Georgi Todorov
34 | * Edited by : Tord Wessman
35 | * Created on : Nov 22, 2013
36 | * Rewrite : Fan.zhang 421395590@qq.com
37 | * Updated on : Mar 2, 2017
38 | ****************************************************************************/
39 |
40 | #ifndef _PCA9685_H
41 | #define _PCA9685_H
42 | #include
43 |
44 | // Register Definitions
45 | // 寄存器定义
46 | #define MODE1 0x00 //Mode register 1
47 | #define MODE2 0x01 //Mode register 2
48 | #define SUBADR1 0x02 //I2C-bus subaddress 1
49 | #define SUBADR2 0x03 //I2C-bus subaddress 2
50 | #define SUBADR3 0x04 //I2C-bus subaddress 3
51 | #define ALLCALLADR 0x05 //LED All Call I2C-bus address
52 | #define LED0 0x6 //LED0 start register
53 | #define LED0_ON_L 0x6 //LED0 output and brightness control byte 0
54 | #define LED0_ON_H 0x7 //LED0 output and brightness control byte 1
55 | #define LED0_OFF_L 0x8 //LED0 output and brightness control byte 2
56 | #define LED0_OFF_H 0x9 //LED0 output and brightness control byte 3
57 | #define LED_MULTIPLYER 4 // For the other 15 channels
58 | #define ALLLED_ON_L 0xFA //load all the LEDn_ON registers, byte 0 (turn 0-7 channels on)
59 | #define ALLLED_ON_H 0xFB //load all the LEDn_ON registers, byte 1 (turn 8-15 channels on)
60 | #define ALLLED_OFF_L 0xFC //load all the LEDn_OFF registers, byte 0 (turn 0-7 channels off)
61 | #define ALLLED_OFF_H 0xFD //load all the LEDn_OFF registers, byte 1 (turn 8-15 channels off)
62 | #define PRE_SCALE 0xFE //prescaler for output frequency
63 | #define MAX_PWM_RES 4096 //Resolution 4096=12bit 分辨率,按2的阶乘计算,12bit为4096
64 | #define CLOCK_FREQ 25000000.0 //25MHz default osc clock
65 | #define BUFFER_SIZE 0x08 //1 byte buffer
66 | #define PCA9685_DEFAULT_I2C_ADDR 0x40 // default i2c address for pca9685 默认i2c地址为0x40
67 | #define PCA9685_DEFAULT_I2C_BUS 1 // default i2c bus for pca9685 默认为1
68 | //! Main class that exports features for PCA9685 chip
69 | class PCA9685 {
70 | public:
71 |
72 | PCA9685();
73 | PCA9685(int,int);
74 | void init(int,int);
75 | virtual ~PCA9685();
76 | void reset(void);
77 | void setPWMFreq(int);
78 | void setPWM(uint8_t, int, int);
79 | void setPWM(uint8_t, int);
80 | private:
81 | int _i2caddr;
82 | int _i2cbus;
83 | char busfile[64];
84 | uint8_t dataBuffer[BUFFER_SIZE];
85 | uint8_t read_byte(int, uint8_t);
86 | void write_byte(int, uint8_t, uint8_t);
87 | int openfd();
88 | };
89 | #endif
90 |
--------------------------------------------------------------------------------
/src/drivers/rpi_pca9685_pwm_out/rpi_pca9685_pwm_out.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (c) 2015-2016 PX4 Development Team. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in
13 | * the documentation and/or other materials provided with the
14 | * distribution.
15 | * 3. Neither the name PX4 nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software
17 | * without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | * POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | ****************************************************************************/
33 | #include "rpi_pca9685_pwm_out.h"
34 |
35 | using namespace rpi_pca9685_pwm_out;
36 | //--------------------------------------------------------------------------//
37 | int rpi_pca9685_pwm_out::mixer_control_callback(uintptr_t handle,
38 | uint8_t control_group,
39 | uint8_t control_index,
40 | float &input)
41 | {
42 | const actuator_controls_s *controls = (actuator_controls_s *)handle;
43 | input = controls[control_group].control[control_index];
44 |
45 | return 0;
46 | }
47 |
48 | //----------------------------------------------------------------------------//
49 | int rpi_pca9685_pwm_out::initialize_mixer(const char *mixer_filename)
50 | {
51 | char buf[4096];
52 | unsigned buflen = sizeof(buf);
53 | memset(buf, '\0', buflen);
54 |
55 | _mixer_group = new MixerGroup(mixer_control_callback, (uintptr_t) &_controls);
56 |
57 | // PX4_INFO("Trying to initialize mixer from config file %s", mixer_filename);
58 |
59 | if (load_mixer_file(mixer_filename, buf, buflen) == 0) {
60 | if (_mixer_group->load_from_buf(buf, buflen) == 0) {
61 | PX4_INFO("Loaded mixer from file %s", mixer_filename);
62 | return 0;
63 |
64 | } else {
65 | PX4_ERR("Unable to parse from mixer config file %s", mixer_filename);
66 | }
67 |
68 | } else {
69 | PX4_ERR("Unable to load config file %s", mixer_filename);
70 | }
71 |
72 | if (_mixer_group->count() <= 0) {
73 | PX4_ERR("Mixer initialization failed");
74 | return -1;
75 | }
76 |
77 | return 0;
78 | }
79 | //----------------------------------------------------------------------------//
80 | int rpi_pca9685_pwm_out::pwm_initialize()
81 | {
82 | /**************初始化PCA9685开始*************/
83 | /**************PCA965 initializing********/
84 | pwm.init(_pca9685_bus, 0x40);
85 | usleep(1000 * 100);
86 | /****12BIT 精度输出下,好赢电调可以到200HZ刷新***/
87 | /****200HZ for 12bit Resolution, support most of the esc***/
88 | pwm.setPWMFreq(200);
89 | usleep(1000 * 1000);
90 | /**************初始化PCA9685结束************/
91 | /**************PCA965 initialized********/
92 | return 0;
93 | }
94 | //----------------------------------------------------------------------------//
95 | void rpi_pca9685_pwm_out::pwm_deinitialize()
96 | {
97 | rpi_pca9685_pwm_out::pwm.reset();
98 | }
99 | //----------------------------------------------------------------------------//
100 | void rpi_pca9685_pwm_out::send_outputs_pwm(const uint16_t *pwm)
101 | {
102 | /*************向PCA9685发送数据*************/
103 | /*************send pwm signal to pca9685 initializing*************/
104 | int i;
105 |
106 | for (i = 0; i < NUM_PWM; ++i) {
107 | //PX4_WARN("PWM%d:%d\n",i,*(pwm+i));
108 | rpi_pca9685_pwm_out::pwm.setPWM(i, *(pwm + i));
109 | }
110 | }
111 | //----------------------------------------------------------------------------//
112 | void rpi_pca9685_pwm_out::subscribe()
113 | {
114 | memset(_controls, 0, sizeof(_controls));
115 | memset(_poll_fds, 0, sizeof(_poll_fds));
116 |
117 | /* set up ORB topic names */
118 | _controls_topics[0] = ORB_ID(actuator_controls_0);
119 | _controls_topics[1] = ORB_ID(actuator_controls_1);
120 | _controls_topics[2] = ORB_ID(actuator_controls_2);
121 | _controls_topics[3] = ORB_ID(actuator_controls_3);
122 |
123 | // Subscribe for orb topics
124 | for (uint8_t i = 0; i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS; i++) {
125 | if (_groups_required & (1 << i)) {
126 | PX4_DEBUG("subscribe to actuator_controls_%d", i);
127 | _controls_subs[i] = orb_subscribe(_controls_topics[i]);
128 |
129 | } else {
130 | _controls_subs[i] = -1;
131 | }
132 |
133 | if (_controls_subs[i] >= 0) {
134 | _poll_fds[_poll_fds_num].fd = _controls_subs[i];
135 | _poll_fds[_poll_fds_num].events = POLLIN;
136 | _poll_fds_num++;
137 | }
138 |
139 | _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
140 |
141 | }
142 | }
143 | //----------------------------------------------------------------------------//
144 | void rpi_pca9685_pwm_out::task_main(int argc, char *argv[])
145 | {
146 | _is_running = true;
147 |
148 | /***************初始化PCA9685************/
149 | /***************rpc_pca9685_pwm_out*************/
150 | rpi_pca9685_pwm_out::pwm_initialize();
151 |
152 | // Set up mixer
153 | if (initialize_mixer(_mixer_filename) < 0) {
154 | PX4_ERR("无法初始化通道混合配置文件 Can't loading mixer file");
155 | return;
156 | }
157 |
158 | _mixer_group->groups_required(_groups_required);
159 | // subscribe and set up polling
160 | subscribe();
161 |
162 | // Start disarmed
163 | _armed.armed = false;
164 | _armed.prearmed = false;
165 |
166 | pwm_limit_init(&_pwm_limit);
167 |
168 | // Main loop
169 | while (!_task_should_exit) {
170 | int pret = px4_poll(_poll_fds, _poll_fds_num, 10);
171 |
172 | /* Timed out, do a periodic check for _task_should_exit. */
173 | if (pret == 0) {
174 | continue;
175 | }
176 |
177 | /* This is undesirable but not much we can do. */
178 | if (pret < 0) {
179 | PX4_WARN("poll error %d, %d", pret, errno);
180 | /* sleep a bit before next try */
181 | usleep(10000);
182 | continue;
183 | }
184 |
185 | /* get controls for required topics */
186 | unsigned poll_id = 0;
187 |
188 | for (uint8_t i = 0; i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS; i++) {
189 | if (_controls_subs[i] >= 0) {
190 | if (_poll_fds[poll_id].revents & POLLIN) {
191 | orb_copy(_controls_topics[i], _controls_subs[i], &_controls[i]);
192 | }
193 |
194 | poll_id++;
195 | }
196 | }
197 |
198 | if (_mixer_group != nullptr) {
199 | _outputs.timestamp = hrt_absolute_time();
200 | /* do mixing */
201 | _outputs.noutputs = _mixer_group->mix(_outputs.output,
202 | _outputs.NUM_ACTUATOR_OUTPUTS,
203 | NULL);
204 |
205 | /* disable unused ports by setting their output to NaN */
206 | for (size_t i = _outputs.noutputs;
207 | i < _outputs.NUM_ACTUATOR_OUTPUTS;
208 | i++) {
209 | _outputs.output[i] = NAN;
210 | }
211 |
212 | const uint16_t reverse_mask = 0;
213 | uint16_t disarmed_pwm[4];
214 | uint16_t min_pwm[4];
215 | uint16_t max_pwm[4];
216 |
217 | for (unsigned int i = 0; i < NUM_PWM; i++) {
218 | disarmed_pwm[i] = _pwm_disarmed;
219 | min_pwm[i] = _pwm_min;
220 | max_pwm[i] = _pwm_max;
221 | }
222 |
223 | uint16_t pwm[4];
224 |
225 | // TODO FIXME: pre-armed seems broken
226 | pwm_limit_calc(_armed.armed,
227 | false/*_armed.prearmed*/,
228 | _outputs.noutputs,
229 | reverse_mask,
230 | disarmed_pwm,
231 | min_pwm,
232 | max_pwm,
233 | _outputs.output,
234 | pwm,
235 | &_pwm_limit);
236 |
237 | if (_armed.lockdown) {
238 | send_outputs_pwm(disarmed_pwm);
239 |
240 | } else {
241 | send_outputs_pwm(pwm);
242 | }
243 |
244 | if (_outputs_pub != nullptr) {
245 | orb_publish(ORB_ID(actuator_outputs), _outputs_pub, &_outputs);
246 |
247 | } else {
248 | _outputs_pub = orb_advertise(ORB_ID(actuator_outputs), &_outputs);
249 | }
250 |
251 | } else {
252 | PX4_ERR("Could not mix output! Exiting...");
253 | _task_should_exit = true;
254 | }
255 |
256 | bool updated;
257 | orb_check(_armed_sub, &updated);
258 |
259 | if (updated) {
260 | orb_copy(ORB_ID(actuator_armed), _armed_sub, &_armed);
261 | }
262 | }
263 |
264 | pwm_deinitialize();
265 |
266 | for (uint8_t i = 0; i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS; i++) {
267 | if (_controls_subs[i] >= 0) {
268 | orb_unsubscribe(_controls_subs[i]);
269 | }
270 | }
271 |
272 | orb_unsubscribe(_armed_sub);
273 |
274 | _is_running = false;
275 |
276 | }
277 | //----------------------------------------------------------------------------//
278 | void rpi_pca9685_pwm_out::task_main_trampoline(int argc, char *argv[])
279 | {
280 | task_main(argc, argv);
281 | }
282 | //----------------------------------------------------------------------------//
283 | void rpi_pca9685_pwm_out::start()
284 | {
285 | ASSERT(_task_handle == -1);
286 | _task_should_exit = false;
287 |
288 | /* start the task */
289 | _task_handle = px4_task_spawn_cmd("pwm_out_main",
290 | SCHED_DEFAULT,
291 | SCHED_PRIORITY_MAX,
292 | 1500,
293 | (px4_main_t)&task_main_trampoline,
294 | nullptr);
295 |
296 | if (_task_handle < 0) {
297 | warn("task start failed");
298 | return;
299 | }
300 |
301 | }
302 | //----------------------------------------------------------------------------//
303 | void rpi_pca9685_pwm_out::stop()
304 | {
305 | _task_should_exit = true;
306 |
307 | while (_is_running) {
308 | usleep(200000);
309 | PX4_INFO(".");
310 | }
311 |
312 | _task_handle = -1;
313 | }
314 | //----------------------------------------------------------------------------//
315 | void rpi_pca9685_pwm_out::usage()
316 | {
317 | PX4_INFO("usage: pwm_out start [-d pwmdevice] -m mixerfile");
318 | PX4_INFO(" -d pwmdevice : sysfs device for pwm generation");
319 | PX4_INFO(" (default /sys/class/pwm/pwmchip0)");
320 | PX4_INFO(" -m mixerfile : path to mixerfile");
321 | PX4_INFO(" (default ROMFS/px4fmu_common/mixers/quad_x.main.mix)");
322 | PX4_INFO(" pwm_out stop");
323 | PX4_INFO(" pwm_out status");
324 | }
325 | //----------------------------------------------------------------------------//
326 | int rpi_pca9685_pwm_out_main(int argc, char **argv)
327 | {
328 | int ch;
329 | int myoptind = 1;
330 | const char *myoptarg = nullptr;
331 |
332 | char *verb = nullptr;
333 |
334 | if (argc >= 2) {
335 | verb = argv[1];
336 |
337 | } else {
338 | return 1;
339 | }
340 |
341 | while ((ch = px4_getopt(argc, argv, "d:m:", &myoptind, &myoptarg)) != EOF) {
342 | switch (ch) {
343 | case 'd':
344 | strncpy(rpi_pca9685_pwm_out::_device, myoptarg, sizeof(rpi_pca9685_pwm_out::_device));
345 | break;
346 |
347 | case 'm':
348 | strncpy(rpi_pca9685_pwm_out::_mixer_filename, myoptarg, sizeof(rpi_pca9685_pwm_out::_mixer_filename));
349 | break;
350 | }
351 | }
352 |
353 | // gets the parameters for the esc's pwm
354 | param_get(param_find("PWM_DISARMED"), &rpi_pca9685_pwm_out::_pwm_disarmed);
355 | param_get(param_find("PWM_MIN"), &rpi_pca9685_pwm_out::_pwm_min);
356 | param_get(param_find("PWM_MAX"), &rpi_pca9685_pwm_out::_pwm_max);
357 |
358 | /*
359 | * Start/load the driver.
360 | */
361 | if (!strcmp(verb, "start")) {
362 | if (rpi_pca9685_pwm_out::_is_running) {
363 | PX4_WARN("pwm_out already running");
364 | return 1;
365 | }
366 |
367 | rpi_pca9685_pwm_out::start();
368 | }
369 |
370 | else if (!strcmp(verb, "stop")) {
371 | if (!rpi_pca9685_pwm_out::_is_running) {
372 | PX4_WARN("pwm_out is not running");
373 | return 1;
374 | }
375 |
376 | rpi_pca9685_pwm_out::stop();
377 | }
378 |
379 | else if (!strcmp(verb, "status")) {
380 | PX4_WARN("pwm_out is %s", rpi_pca9685_pwm_out::_is_running ? "running" : "not running");
381 | return 0;
382 |
383 | } else {
384 | rpi_pca9685_pwm_out::usage();
385 | return 1;
386 | }
387 |
388 | return 0;
389 | }
390 |
--------------------------------------------------------------------------------
/src/drivers/rpi_pca9685_pwm_out/rpi_pca9685_pwm_out.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (c) 2015-2016 zhangfan. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in
13 | * the documentation and/or other materials provided with the
14 | * distribution.
15 | * 3. Neither the name PX4 nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software
17 | * without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | * POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | ****************************************************************************/
33 | #include
34 |
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include // NAN
40 |
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include "PCA9685.h"
52 |
53 | namespace rpi_pca9685_pwm_out
54 | {
55 | static px4_task_t _task_handle = -1;
56 | volatile bool _task_should_exit = false;
57 | static bool _is_running = false;
58 |
59 | static const int NUM_PWM = 4;
60 | static char _device[64] = "/sys/class/pwm/pwmchip0";
61 | //static int _pwm_fd[NUM_PWM];
62 |
63 | static const int FREQUENCY_PWM = 400;
64 | static char _mixer_filename[64] = "ROMFS/px4fmu_common/mixers/quad_x.main.mix";
65 |
66 | // subscriptions
67 | int _controls_subs[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
68 | int _armed_sub;
69 |
70 | // publications
71 | orb_advert_t _outputs_pub = nullptr;
72 | orb_advert_t _rc_pub = nullptr;
73 |
74 | // topic structures
75 | actuator_controls_s _controls[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
76 | orb_id_t _controls_topics[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
77 | actuator_outputs_s _outputs;
78 | actuator_armed_s _armed;
79 |
80 | // polling
81 | uint8_t _poll_fds_num = 0;
82 | px4_pollfd_struct_t _poll_fds[actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS];
83 |
84 | // control groups related
85 | uint32_t _groups_required = 0;
86 | uint32_t _groups_subscribed = 0;
87 |
88 | pwm_limit_t _pwm_limit;
89 |
90 | // esc parameters
91 | int32_t _pwm_disarmed;
92 | int32_t _pwm_min;
93 | int32_t _pwm_max;
94 |
95 | //PCA9685 device
96 | ::PCA9685 pwm;
97 | int _pca9685_bus=1; //默认兼容树莓派
98 |
99 | MixerGroup *_mixer_group = nullptr;
100 |
101 | void usage();
102 |
103 | void start();
104 |
105 | void stop();
106 |
107 | int pwm_initialize();
108 |
109 | void pwm_deinitialize();
110 |
111 | void send_outputs_pwm(const uint16_t *pwm);
112 |
113 | void task_main_trampoline(int argc, char *argv[]);
114 |
115 | void subscribe();
116 |
117 | void task_main(int argc, char *argv[]);
118 |
119 | /* mixer initialization */
120 | int initialize_mixer(const char *mixer_filename);
121 | int mixer_control_callback(uintptr_t handle, uint8_t control_group,
122 | uint8_t control_index, float &input);
123 | }
124 | extern "C" __EXPORT int rpi_pca9685_pwm_out_main(int, char **);
125 |
--------------------------------------------------------------------------------
/src/drivers/rpi_rc_in/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ############################################################################
2 | #
3 | # Copyright (c) 2016 PX4 Development Team. All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions
7 | # are met:
8 | #
9 | # 1. Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # 2. Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in
13 | # the documentation and/or other materials provided with the
14 | # distribution.
15 | # 3. Neither the name PX4 nor the names of its contributors may be
16 | # used to endorse or promote products derived from this software
17 | # without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 | # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 | #
32 | ############################################################################
33 | px4_add_module(
34 | MODULE drivers__rpi_rc_in
35 | MAIN rpi_rc_in
36 | STACK_MAIN 1200
37 | COMPILE_FLAGS
38 | SRCS
39 | rpi_rc_in.cpp
40 | DEPENDS
41 | platforms__common
42 | )
43 | # vim: set noet ft=cmake fenc=utf-8 ff=unix :
44 |
--------------------------------------------------------------------------------
/src/drivers/rpi_rc_in/rpi_rc_in.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (C) 2015 Mark Charl. All rights reserved.
4 | * Copyright (C) 2017 Fan.zhang. All rights reserved. 421395590@qq.com
5 | * Copyright (C) 2016 PX4 Development Team. All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | *
11 | * 1. Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in
15 | * the documentation and/or other materials provided with the
16 | * distribution.
17 | * 3. Neither the name PX4 nor the names of its contributors may be
18 | * used to endorse or promote products derived from this software
19 | * without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | * POSSIBILITY OF SUCH DAMAGE.
33 | *
34 | ****************************************************************************/
35 | #include "rpi_rc_in.h"
36 |
37 | using namespace rpi_rc_in;
38 | //---------------------------------------------------------------------------------------------------------//
39 | int RcInput::rpi_rc_init() {
40 | int i;
41 | //--------------初始化共享内存映射----------------------------//
42 | if ((this->shmid = shmget(this->key, sizeof(int) * this->_channels, 0666))
43 | < 0) {
44 | PX4_WARN("无法访问共享内存。Faild to access shared memory");
45 | return -1;
46 | }
47 |
48 | if ((this->mem = (int*) shmat(this->shmid, NULL, 0)) == (void *) -1) {
49 | PX4_WARN("无法映射共享内存。Faild to mapping shared memory");
50 | return -1;
51 | }
52 |
53 | //--------------发布所有通道的数据------------------------//
54 | for (i = 0; i < input_rc_s::RC_INPUT_MAX_CHANNELS; ++i) {
55 | _data.values[i] = UINT16_MAX;
56 | }
57 |
58 | _rcinput_pub = orb_advertise(ORB_ID(input_rc), &_data);
59 |
60 | if (_rcinput_pub == nullptr) {
61 | PX4_WARN("error: advertise failed");
62 | return -1;
63 | }
64 |
65 | return 0;
66 | }
67 | //---------------------------------------------------------------------------------------------------------//
68 | int RcInput::start() {
69 | int result = 0;
70 |
71 | result = rpi_rc_init();
72 |
73 | if (result != 0) {
74 | PX4_WARN("error: RC initialization failed");
75 | return -1;
76 | }
77 |
78 | _isRunning = true;
79 | result = work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline,
80 | this, 0);
81 |
82 | if (result == -1) {
83 | _isRunning = false;
84 | }
85 |
86 | return result;
87 | }
88 | //---------------------------------------------------------------------------------------------------------//
89 | void RcInput::stop() {
90 | _shouldExit = true;
91 | }
92 | //---------------------------------------------------------------------------------------------------------//
93 | void RcInput::cycle_trampoline(void *arg) {
94 | RcInput *dev = reinterpret_cast(arg);
95 | dev->_cycle();
96 | }
97 | //---------------------------------------------------------------------------------------------------------//
98 | void RcInput::_cycle() {
99 | _measure();
100 |
101 | if (!_shouldExit) {
102 | work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline, this,
103 | USEC2TICK(RCINPUT_MEASURE_INTERVAL_US));
104 | }
105 | }
106 | //---------------------------------------------------------------------------------------------------------//
107 | void RcInput::_measure(void) {
108 | uint64_t ts;
109 | // PWM数据发布
110 | // read pwm value from shared memory
111 | int i=0;
112 | for(i=0;i<_channels;++i){
113 | _data.values[i] = (*(this->mem+i)<=0)?UINT16_MAX:*(this->mem+i);
114 | }
115 |
116 | ts = hrt_absolute_time();
117 | _data.timestamp = ts;
118 | _data.timestamp_last_signal = ts;
119 | _data.channel_count = _channels;
120 | _data.rssi = 100;
121 | _data.rc_lost_frame_count = 0;
122 | _data.rc_total_frame_count = 1;
123 | _data.rc_ppm_frame_length = 100;
124 | _data.rc_failsafe = false;
125 | _data.rc_lost = false;
126 | _data.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_PPM;
127 |
128 | orb_publish(ORB_ID(input_rc), _rcinput_pub, &_data);
129 | }
130 | //---------------------------------------------------------------------------------------------------------//
131 | /**
132 | * Print the correct usage.
133 | */
134 |
135 | static void rpi_rc_in::usage(const char *reason) {
136 | if (reason) {
137 | PX4_ERR("%s", reason);
138 | }
139 | PX4_INFO("用法: rpi_rc_in {start|stop|status}");
140 | }
141 | //---------------------------------------------------------------------------------------------------------//
142 | int rpi_rc_in_main(int argc, char **argv) {
143 | if (argc < 2) {
144 | usage("missing command");
145 | return 1;
146 | }
147 |
148 | if (!strcmp(argv[1], "start")) {
149 |
150 | if (rc_input != nullptr && rc_input->isRunning()) {
151 | PX4_WARN("运行中。running");
152 | /* this is not an error */
153 | return 0;
154 | }
155 |
156 | rc_input = new RcInput();
157 |
158 | // Check if alloc worked.
159 | if (nullptr == rc_input) {
160 | PX4_ERR("遥控输入模块初始化错误。Rc input moduel initialization faild");
161 | return -1;
162 | }
163 |
164 | int ret = rc_input->start();
165 |
166 | if (ret != 0) {
167 | PX4_ERR("遥控输入模块未能启动。 Rc input module failure");
168 | }
169 |
170 | return 0;
171 | }
172 |
173 | if (!strcmp(argv[1], "stop")) {
174 |
175 | if (rc_input == nullptr || !rc_input->isRunning()) {
176 | PX4_WARN("模块未运行。 Not runing");
177 | /* this is not an error */
178 | return 0;
179 | }
180 |
181 | rc_input->stop();
182 |
183 | // Wait for task to die
184 | int i = 0;
185 |
186 | do {
187 | /* wait up to 3s */
188 | usleep(100000);
189 |
190 | } while (rc_input->isRunning() && ++i < 30);
191 |
192 | delete rc_input;
193 | rc_input = nullptr;
194 |
195 | return 0;
196 | }
197 |
198 | if (!strcmp(argv[1], "status")) {
199 | if (rc_input != nullptr && rc_input->isRunning()) {
200 | PX4_INFO("运行中。 running");
201 |
202 | } else {
203 | PX4_INFO("未运行。 Not runing\n");
204 | }
205 |
206 | return 0;
207 | }
208 |
209 | usage("不知道你要做什么。 rpi_rc_in start|stop|status");
210 | return 1;
211 |
212 | }
213 | //---------------------------------------------------------------------------------------------------------//
214 |
--------------------------------------------------------------------------------
/src/drivers/rpi_rc_in/rpi_rc_in.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | *
3 | * Copyright (C) 2015 Mark Charl. All rights reserved.
4 | * Copyright (C) 2017 Fan.zhang. All rights reserved. 421395590@qq.com
5 | * Copyright (C) 2016 PX4 Development Team. All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | *
11 | * 1. Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in
15 | * the documentation and/or other materials provided with the
16 | * distribution.
17 | * 3. Neither the name PX4 nor the names of its contributors may be
18 | * used to endorse or promote products derived from this software
19 | * without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | * POSSIBILITY OF SUCH DAMAGE.
33 | *
34 | ****************************************************************************/
35 |
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 |
44 | #include
45 | #include
46 | #include
47 |
48 | #include
49 |
50 | #include
51 | #include
52 | #define RCINPUT_MEASURE_INTERVAL_US 20000
53 | namespace rpi_rc_in {
54 | class RcInput {
55 | public:
56 | int *mem;
57 | key_t key;
58 | int shmid;
59 | RcInput() :
60 | mem(nullptr),key(4096),shmid(0),_shouldExit(false), _isRunning(false), _work { }, _rcinput_pub(
61 | nullptr), _channels(8),//D8R-II plus
62 | _data { } {
63 | //memset(_ch_fd, 0, sizeof(_ch_fd));
64 | }
65 | ~RcInput() {
66 | this->mem = nullptr;
67 | work_cancel(HPWORK, &_work);
68 | _isRunning = false;
69 | }
70 |
71 | /* @return 0 on success, -errno on failure */
72 | int start();
73 |
74 | /* @return 0 on success, -errno on failure */
75 | void stop();
76 |
77 | /* Trampoline for the work queue. */
78 | static void cycle_trampoline(void *arg);
79 |
80 | bool isRunning() {
81 | return _isRunning;
82 | }
83 |
84 | private:
85 | void _cycle();
86 | void _measure();
87 |
88 | bool _shouldExit;bool _isRunning;
89 | struct work_s _work;
90 | orb_advert_t _rcinput_pub;
91 | int _channels;
92 | //int _ch_fd[input_rc_s::RC_INPUT_MAX_CHANNELS];
93 | struct input_rc_s _data;
94 |
95 | int rpi_rc_init();
96 | };
97 |
98 | static void usage(const char *reason);
99 | static RcInput *rc_input = nullptr;
100 | }
101 | extern "C" __EXPORT int rpi_rc_in_main(int argc, char **argv);
102 |
--------------------------------------------------------------------------------