最近在Windows下面编写NDK应用,在检查编译完成后的so文件的时候,发现,objdump,readelf,nm,ldd等命令不能在默认安装的Cygwin中使用。解决方法是,下载Cygwin的安装包,然后点击安装,从选择包里面增加 binutils包,如下图所示:(注意,只选择Devel版本即可,正常情况下我们一般不会需要携带调试信息的版本)
Windows下使用命令行执行需要用SSH keys登录的Git
Windows下使用Git的时候,大家都习惯了使用TortoiseGit来执行操作。但是在某些情况下,必须在Git Bash下面执行命令的时候,就比较麻烦了,尤其是服务器设置了SSH keys登陆的时候。默认情况下,TortoiseGit会自动加载puttygen生成的.PPK文件来完成认证工作,但是在Git Bash 下面,只能是根据Linux下面的配置来进行登陆认证了。
1.在Git Bash中输入“puttygen”,如下图所示:
弹出如下图形界面:
对于已经有PPK文件的情况,点击"Load"来加载,没有PPK文件,请点击"Generate"来生成。加载完成后,点击菜单上的“Conversions”按钮,如下图所示:
导出的文件没有扩展名,命名为“id_rsa”,注意,必须是这个名字,没有扩展名。
2.拷贝文件“id_rsa”到当前用户目录下面的 “.ssh”目录下面,当前用户目录的位置,请在Git Bash中输入“echo ~”来显示出来,最后的结果如下图所示
3.在Git Bash中继续执行命令,就可以了!
将已有的Git项目的某个目录分离成独立子模块
当一个项目在开发若干时间后,希望将某个目录单独出一个项目来开发,此时就可以利用这个subtree的功能分离里。
具体的操作方式是这样的:(只能在Git Bash的命令行中操作)
1. 首先cd到需要处理的项目的根目录:
1 2 3 4 5 |
$ pushd ./ $ git subtree split -P <name-of-folder> -b <name-of-new-branch> # 将需要分离的目录的提交日志分离成一个独立的临时版本 $ popd |
注意
<name-of-folder> 必须是从工程的根目录开始算起,类似“project/hello/world”的格式。
<name-of-new-branch> 的名字,尽量取简单。
2. 创建一个新的repo(项目)(离开原有的项目的文件夹,在另外的地方新建一个项目)
1 2 3 4 5 6 7 |
$ mkdir <new-repo> $ pushd <new-repo> $ git init $ git pull </path/to/big-repo> <name-of-new-branch> |
注意
</path/to/big-repo>是我们需要拉取数据的根目录的绝对路径,类似 “D:\Source\Project”的格式。
<name-of-new-branch> 是我们刚刚分离出来的分支的名字。
3. 添加子模块(到原来工程的根目录下面)
1 |
$ git submodule add git@github.com:my-user/new-repo.git <name-of-folder> |
可以看到,在原来的Git工程的根目录下面增加了一个名为“.gitmodules”的文件,里面的内容如下:
1 2 3 |
[submodule "<name-of-folder>"] path = <name-of-folder> url = git@github.com:my-user/new-repo.git |
fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.
最近在使用 VS2015 编译以前用VS2008的项目的时候,提示错误:fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.
解决方法:在项目的“预处理器定义”中增加 "_XKEYCHECK_H"
如何在Android Studio中更新jar包
Linux计算MD5和Sha1的命令
MD5
MD5即Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。
Sha1
安全散列算法(英语:Secure Hash Algorithm)是一种能计算出一个数位讯息所对应到的,长度固定的字串(又称讯息摘要)的算法。且若输入的讯息不同,它们对应到不同字串的机率很高;而SHA是FIPS所认证的五种安全散列算法。这些算法之所以称作“安全”是基于以下两点(根据官方标准的描述):“1)由讯息摘要反推原输入讯息,从计算理论上来说是很困难的。2)想要找到两组不同的讯息对应到相同的讯息摘要,从计算理论上来说也是很困难的。任何对输入讯息的变动,都有很高的机率导致其产生的讯息摘要迥异。
MD5 与 SHA1 是当前最常用的两种哈希算法。那在Linux下如何计算这两种哈希值呢,基本上所有的 Linux 发行版都内置了这两个命令,比如要校检的文件命为OurUnix.tar:
计算文件的 MD5 – md5sum
1 2 |
$ md5sum OurUnix.tar b9555cc1915652237948e37ccc9c484e OurUnix.tar |
计算文件的 SHA1 – sha1sum
1 2 |
$sha1sum OurUnix.tar bb7d67fb5776c2854edf35ec4a585ff8adc3dbda OurUnix.tar |
Android Studio 1.3 配置编译NDK参考文档
Experimental Plugin User Guide
Introduction
The new experimental plugin is based on Gradle’s new component model mechanism, while allows significant reduction in configuration time. It also includes NDK integration for building JNI applications. This user guides provides details on how to use it and highlights the difference between the new plugin and the original plugin.
WARNING: Note that this is plugin is at the experimental stage. The Gradle API for the new component model is not final, which means it’ll only work with a specific version of Gradle until the APIs are final.
Additionally, the DSL is likely change significantly, as APIs to create the DSL are finalized.
Requirements
- Gradle 2.5 only
- Android NDK r10e (if you are using NDK)
- SDK with Build Tools at least version 19.0.0 and we aim to minimize the amount of changes needed for the migration process in the future. Some features may require a more recent version.
Migrating from Traditional Android Gradle Plugin
A typical Android Studio project may have a directory structure as follows. File that needs to be change is highlighted in red:
There are some significant changes in the DSL between the new plugin and the traditional one.
.
├── app/
│ ├── app.iml
│ ├── build.gradle
│ └── src/
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew*
├── gradlew.bat
├── local.properties
├── MyApplication.iml
└── settings.gradle
./gradle/wrapper/gradle-wrapper.properties
-
The new plugin supports only gradle-2.5.
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
./build.gradle
-
Classpath for the plugin is com.android.tools.build:gradle-experimental instead of com.android.tools.build:gradle.
-
The current version is 0.2.0.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.2.0'
// NOTE: Do not place your application dependencies here
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
./app/build.gradle
There are significant changes to the DSL of the plugin. We understand that many of the changes are frustrating and seem unnecessary, and our goal is to remove some of these current changes to minimize the migration process from the traditional plugin in the future.
DSL Changes:
-
Plugin name is com.android.model.application instead of com.android.application. Or use apply plugin: 'com.android.model.library' if you want to create an Android aar library.
-
Configuration is wrapped with the model { } block
-
Most properties require the = operator
-
Adding elements to a Collection should be done using the += operator.
Current DSL Limitations that will hopefully go away:
-
buildTypes, productFlavors and signingConfigs must be place outside of the android { } block.
-
Nested options within the android { } block must be configured using the with keyword.
-
Properties are only set with their direct types only, with no way to accept other types and adapting them. For instance:
-
Properties of type File accepts only File instead of File and String objects.
-
minSdkVersion cannot directly receive either an integer or string (for codename).
-
-
Creating a buildType or productFlavor requires calling the create method. Modifying an existing one such as the release and debug buildType can be done using the just the name.
-
The DSL for modifying variants and their tasks is very, very limited right now.
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 22
buildToolsVersion = "22.0.1"
defaultConfig.with {
applicationId = "com.example.user.myapplication"
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 22
versionCode = 1
versionName = "1.0"
buildConfigFields.with {
create() {
type = "int"
name = "VALUE"
value = "1"
}
}
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.pro')
}
}
android.productFlavors {
create("flavor1") {
applicationId = ‘com.app’
}
}
// Configures source set directory.
android.sources {
main {
java {
source {
srcDir 'src'
}
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
}
Ndk Integration
The experimental plugin comes with NDK integration for creating native applications. To use the NDK integration:
-
Use the SDK Manager inside Studio to download the NDK.
-
Set ndk.dir in local.properties or the ANDROID_NDK_HOME environment variable to the directory containing the NDK.
-
Add an android.ndk block to the model in build.gradle.
Known Limitations
- There’s no support for NDK-only modules. The only supported project types are hybrid app projects and hybrid Library Projects.
- Consumed Library project don’t impact compilation of jni code in the consuming project (ie the AAR so files are simply packaged in the APK)
- No support for creating and depending on static libraries
- No support for using a NDK modules like cpu_features
- No support for integrating external build systems.
The build.gradle of a simple NDK application may look like this:
1 2 3 4 5 6 7 8 9 10 11 |
apply plugin: 'com.android.model.application' model { android { compileSdkVersion = 22 buildToolsVersion = "22.0.1" } android.ndk { moduleName = "native" } } |
*Note that the moduleName is required. It determines the name of the resulting native library.
By default, it will look in src/main/jni for C/C++ file. Configure android.sources to change the source directory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
model { android { compileSdkVersion = 22 buildToolsVersion = "22.0.1" } android.ndk { moduleName = "native" } android.sources { main { jni { source { srcDir 'src' } } } } } |
Various build options can be set within the android.ndk { } block. For example,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
model { android { compileSdkVersion = 22 buildToolsVersion = "22.0.1" } android.ndk { // All configurations that can be changed in android.ndk. moduleName = "native" toolchain = "clang" toolchainVersion = "3.5" // Note that CFlags has a capital C, which is inconsistent with // the naming convention of other properties. This is a // technical limitation that will be resolved CFlags += "-DCUSTOM_DEFINE" cppFlags += "-DCUSTOM_DEFINE" ldFlags += "-L/custom/lib/path" ldLibs += "log" stl = "stlport_static" } android.buildTypes { release { ndk.with { debuggable = true } } } android.productFlavors { create("arm") { ndk.with { // You can customize the NDK configurations for each // productFlavors and buildTypes. abiFilters += "armeabi-v7a" } } create("fat") { // If ndk.abiFilters is not configured, the application // compile and package all suppported ABI. } } // You can modify the NDK configuration for each variant. components.android { binaries.afterEach { binary ->binary.mergedNdkConfig.cppFlags.add("-DVARIANT=\"" + binary.name + "\"")} } } |
Samples
Additional samples can be found at https://github.com/googlesamples/android-ndk.
对于不能正常访问GitHub的,可以点击这里下载最近保存的版本。
Android Studio 1.3.2 NDK编译报错 'com.android.build.gradle.managed.ProductFlavor_Impl'
Android Studio 1.3.2已经支持NDK的编译,调试。但是已经跟老的项目通过配置 Application.mk,Android.mk来编译NDK的形式完全不同了。参考编译配置文档,采用了Gradle 2.5的配置方式(详细配置参考 Android Studio 1.3 配置编译NDK参考文档,Google官方链接),结果在编译报错,显示如下信息:
Possible causes for this unexpected error include:
- You are using JDK version 'java version "1.7.0_80"'. Some versions of JDK 1.7 (e.g. 1.7.0_10) may cause class loading errors in Gradle.
Please update to a newer version (e.g. 1.7.0_67).
Open JDK Settings - Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
Re-download dependencies and sync project (requires network) - The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
Stop Gradle build processes (requires restart) - Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.
In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.
查找了好长时间原因,最后发现,是由于build.gradle中修改有问题。
先看看有问题的build.gradle,注意defaultConfig.with部分的差别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
apply plugin: 'com.android.model.application' model { android { compileSdkVersion = 23 buildToolsVersion = "23.0.0" defaultConfig.with { applicationId = "com.helloworld" minSdkVersion = 14 targetSdkVersion = 22 } } android.buildTypes { release { minifyEnabled = false proguardFiles += file('proguard-rules.txt') } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' } |
修改后的为(注意defaultConfig.with部分的差别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
apply plugin: 'com.android.model.application' model { android { compileSdkVersion = 23 buildToolsVersion = "23.0.0" defaultConfig.with { applicationId = "com.helloworld" minSdkVersion.apiLevel = 14 targetSdkVersion.apiLevel = 22 } } android.buildTypes { release { minifyEnabled = false proguardFiles += file('proguard-rules.txt') } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' } |
一个疏忽,浪费时间很多啊!
CC3D四轴
最近折腾了一下四轴飞行器,于是在淘宝上买了一套“图腾Q250 FPV穿越机架组装套装”,整个的装备如下图所示。
整个的组装,调试过程相当的心酸,主要还是经验不足,导致了一系列的调试问题。
我是在淘宝这家店买的套装 王子模型世界 不得不吐槽一下店家确实没有什么售后,一切都是要靠自己摸索前进。
目录
1.配件选择
店家给的配件如下:
包装清单
1 x Q250 迷你四轴机架
4 x 银燕EMAX MT2204 KV2300 电机(含16颗螺丝)
4 x 12A电调
1 x CC3D飞控板
1 x FS-I6 遥控器
1 x 遥控挂带
4 x 5030桨(黑色和黄色正反桨)
1 x ST 动力电池
1 x E3 充电器
1 x BB响
送线材配件:
(1)送1条15cm反扣魔术贴扎带
(2)送2根20cm的航模耐高温硅胶线 (红色和黑色各一根)
(3)送2根10cm的热缩管.(Φ4.0mm ) (红色和黑色各一根)
(4)送1根50cm的热缩管.(Φ3.0mm ) (黑色)
(5)送T型插头1个(公头)
(6)送10根尼龙扎带
(7)送 2.00MM香蕉头(公母各12个)
这些配件看起来很多,但是其实有很多是远远不够的,比如红色标注的部分。
主要原因是新手,往往会反反复复的修改,导致耗材不够用。
要注意以下几点:
- CC3D飞控板
CC3D飞控板分为弯针跟直针的版本,店家给出的图片是弯针版本的图片,但发货的却是直针的版本。两者在功能上面没什么差别,但是直针版本的,由于针脚高度的问题,导致了超过高度,在这款机架中空间狭窄,导致比较难操作,因此购买的时候,一定要求卖家发弯针的版本!
弯针与直针版本如图所示
如果你想把直针版本的按照店家图片上的安装方式来安装,会发现非常的狭窄,拥挤,难以操作。
如下图所示,整个挤压在一起,太难操作了点。
- 5030桨
店家附赠的四条正反桨叶,是绝对不够用的,仅仅在试飞阶段,基本上就全部报废掉了,因此,建议直接追加20套吧,反正也不贵,基本上一块钱一对的样子,这样还省了邮费跟时间。注意,螺旋桨分为正反两种,购买的时候,正反各一半,不要买错。
- 尼龙扎带
属于严重的耗材,店家赠送的,必须是刚刚好一次成功,才勉强够用。其实根本不够用,建议到文具店去买好了,十块钱一袋子,有一百多根,我反复折腾,差不多消耗了30根的样子。
- 银燕EMAX MT2204 KV2300 电机
需要注意的是,该电机配备了8颗螺丝,4颗为一组,一组比较长,一组比较短。我们在本次组装的时候,一定要采用比较短的那一组,如果螺丝太长,可能会在拧紧的时候,接触到电机的漆包线,导致短路,烧毁电机。
- 锂电池防爆袋
强烈建议购买两个,价格在几十块钱左右,主要是我们使用的锂电池是“动力锂电池”,这种锂电池实质上就是拿掉了过流保护板的锂电池,放电电流极大,一旦短路,后果不堪设想,有兴趣可以优酷搜索一下相关的视频。我前面几次操作都是手抖着插T型开关的,每次插上都冒火星,心里直冒汗。
实物如下图所示:
2.基础知识
- 正反转电机
从电机的正上方向下观看,顺时针旋转的电机为正向电机,逆时针旋转的电机为反转电机。
旋转方向反向后,问题不大,但是建议按照这个规则来安装电机。
- 自锁(自紧)电机
电机按照规定的方向旋转,电机的螺帽会自动锁紧,而不是脱落。这种电机有规定的转动方向,如果转动方向反了,则螺帽非常容易从电机上面脱落,导致螺旋桨容易被甩出。而如果旋转方向正确,则螺帽会越来越紧,紧紧卡住螺旋桨。
银燕EMAX MT2204 KV2300 电机 属于自锁电机,螺帽分为白色,黑色两种,白色螺帽的电机必须逆时针旋转,安装反桨。黑色螺帽的电机必须顺时针旋转安装正桨。
区分自锁(自紧)电机转向是否正确的简单方法,电机的螺帽拧到一半,或者刚刚拧上一点点,然后上电,让电机旋转,如果螺母自动拧紧,则代表方向正确,如果螺母飞掉或者松动了,则说明方向反了。
- 正反螺旋桨
四轴飞行器为了抵消螺旋桨的自旋,相隔的桨旋转方向是不一样的,所以需要正反桨。正反桨的风都向下吹。顺时针旋转的叫正桨、逆时针旋转的是反桨。安装的时候,一定记得无论正反桨,有字的一面是向上的。
对于5030桨,印有5030R的为正桨,印有5030的为反桨。
- 机头
四轴飞行器向前飞的方向,称之为“机头”。机头在CC3D的板子上面已经用一个三角箭头标识出来了。如图所示
对于有外壳的CC3D,外壳上面一般也会标识出机头方向。
3.正式组装
- 组装机架
参考大疆F450的安装手册,两者的安装规则差不多。
F450_User_Manual_v2.1_cn
注意,先焊线,后组装
焊接线的时候,依据红正黑负的原则,红色电源线焊接到正极,黑色电源线焊接到板子上面的负极。具体的焊接如图所示(注意,这个图片是F450的接线图,其中连接电池部分与QV250的接线图有所不同):
组装完成后的机架,如下图所示(没有焊接线路):
电机,电调安装完成后的样子,如图所示(窃取的别人的图片):
不建议大家按照上图的方式排布电调,主要是电调的发热量还是很大的,两个挤压在一起的话,散热很成问题。建议按照下图的方式安装电调:
- 焊接香焦头
之所以单独把这部分拎出来讲一下,主要是,当我打开包装的时候,看见一大堆这玩意,犯迷糊了,不知道哪里的零件!
香蕉头是连接电调跟电机部分用的,因为我们往往需要调整电机转动的方向,因此,连接线不能直接焊死,否则比较麻烦,所以用香蕉头来,方便重新插拔。香焦头分公母,如上图所示。
电调三根线,需要三个公(或者母)的香焦头,电机上的三根线也是需要三个香焦头(如果电调端用公头,对应的电机端就要用母头)。
焊接好后差不多是这个样子的:
电调跟电机插上后,注意用热缩管绝缘,否则可能短路烧掉!
- 连接飞控
以上操作都差不多完成了,就可以连接CC3D跟电调的连线了。
可以看到,银燕12A电调上有三根线,分别是黄色,红色,棕色。其中,信号线只有一根,另外两根是供电线,目的是给CC3D芯片提供电源。其中黄色线为信号线,红色为正极,棕色为负极。
刚刚好对应下图的CC3D接线示意图,Signal 为信号线,Vcc正极,Gnd负极。
有一个问题就是,我们有四个电调,因此如果都插上,也就变成了四路供电,会不会把CC3D烧掉?我当时就蛮担心这个问题的,结论就是,没问题了,放心插上就可以了,只是正负极不要搞反掉就好了!
- 连接遥控器
这部分的难度,主要是管脚的确定,关键是供电管脚,其他管脚可以随便接入的,后期可以在软件设置的时候进行更改调整。
CC3D与遥控器相关的管脚信息如下表:
颜色 | 功能 | CC3D主板针脚 | 遥控器针脚 |
黑色 | 地线(负极,给遥控器供电) | 1 | 1 |
红色 | 正极(4.8V - 15V,给遥控器供电) | 2 | 1 |
白色 | PWM 信号输入通道 1 或 PPM+NoOneShot 信号输入通道 | 3 | 1 |
蓝色 | PWM 信号输入通道 2 | 4 | 2 |
黄色 | PWM 信号输入通道 3 或 PWM 信号输出通道 7 | 5 | 3 |
绿色 | PWM 信号输入通道 4 或 PWM 信号输出通道 8 | 6 | 4 |
紫色 | PWM 信号输入通道 5 或 PWM 信号输出通道 9 | 7 | 5 |
橙色 | PWM 信号输入通道 6 或 PWM 信号输出通道 10 或 PPM+OneShot 信号输入通道 | 8 | 6 |
上面是CC3D芯片的管脚示意图。
接下来是 FS-I6 遥控器的接收模块的管脚示意图,如下图所示:
注意,这里面有七个插头,从下面到上面是 1-6号PWM通道,对应上面的CC3D的六根信号输入线。最上面的一根信号线留空即可。信号线右边的两根插头是供电插头,其中的任意一组接入CC3D的电源输出接口就可以了,其他都留空就可以了!
我的接线图如下图所示:
完整的说明书点击下载富斯i6说明书FS-i6-MANUAL
4.软件调试
注意,到这一步的时候,还不能安装螺旋桨,主要是为了安全。
- 地面站的安装
目前随着最新的OpenPilot Revolution(CC3D REVO)的发布,OpenPilot GCS软件对于早期的CC3D芯片的支持是到15.02.02版本,最新的版本 15.05.02貌似只支持CC3D REVO 。
早期版本用户请点击这里下载 OpenPilot 15.02.02
CC3D REVO 用户请点击下载 OpenPilot 15.05.02
默认安装,一路Next即可。安装最后窗口弹出提示安装驱动,点击确认安装即可。安装驱动程序之后用数据线将CC3D与电脑连接,有可能你的电脑会提示该驱动安装未成功,在设备管理器里COM端口有出现但是Copter Control黄色感叹号标识,如下图所示。这个时候,其实上位机和CC3D飞控已经可以正常通信。
目前的Window 10已经可以自动识别,并且自动安装驱动,一般不会出现这类现象了。
- CC3D向导配置
进入地面站,首先查看端口通信是否连接,点击Vehicle Setup Wizard进入向导配置界面如图所示。
CC3D飞控使用mini USB接口和上位机相连
进入设置向导后,会出现红色标识,上位机非常人性的提示在配置之前卸掉桨叶,以防意外发生。Next进入下一界面,固件升级界面,提示你需要将固件版本与地面站版本保持一致,初次配置,建议Upgrade升级固件。升级固件步骤:
- 断开航模电池,拔掉USB线,保证CC3D飞控已经完全断电,没有LED亮起
- 点击Upgrade按钮
- 根据进度条上的提示,待进度条走动时迅速插上USB数据线,地面站将自动写入最新固件。
飞控写入最新固件后,Next进入遥控接收器的配置,有PWM/PPM/Futaba/Spektrum四种可选。我们使用的是FS-I6遥控套件,选择PWM通信方式。
Next下一步将会提示选择飞机的类型,有Multirotor、直升机、固定翼及车类选项,选择Multirotor。
下一步将要选择多轴飞行器的机型,Multirotor type下拉框有三轴、四轴、六轴及各种飞行模式可选,右边窗口将会有示意图示意所选择的类型及各个电机转动的方向。选择四轴飞行器,X模式,即Quadcopter X。
Next下一项进入电调的选择界面,有高速电调和标准电调两项可选,选择对应电调同时还要告知工作信号的类型,H250选择高速电调,银燕的电调,支持高速电调模式;
上位机将会把刚刚所配置的信息显示,确认Next,进入传感器校准程序界面。在进入传感器校准之前,需要将飞控板保持水平状态,避免误差。
硬件配置总结:关于配置这块,如果担心记不清楚选项或者初次接触不知如何入设置,我们就按默认选项即可,CC3D的默认选项即可。
- 电机输出校准
校准传感器Next进入电机输出校准界面。在这里提醒大家卸掉桨叶接通电源!输出校准是设置电机的中性环境。方法是点击Start,鼠标拖动滑块向右移动直到电机转动,然后点击Stop,待电机完全停下,点击开始,观察点击能否自己启动,左右移动滑块调节电机启动的临界点。这里需要注意电机的位置及电机的旋转方向,若电机位置不一致,匹配飞控输出通道与电机所对应电调;若旋转方向不一致,只需将电机的任意两根线互换即可。
电机2、3、4的输出校准同电机1一样,按照电机1的设置步骤即可。四个电机参数设定之后,Next进入参数写入界面,点击Save。
- 遥控器配置
CC3D的地面站在配置遥控时默认把油门解锁关闭,建议配置遥控参数先检查油门有没有锁定,以防配置过程中忘记卸掉电池造成不必要的伤害。承接上面的配置过程,点击Radio Setup Wizard直接进入遥控配置界面。也可以点击Finish退出,从Configuration->Input->Start Configuration Wizard进入配置界面。如下图所示。
进入遥控配置向导后,操作将会提示按照屏幕上的指示去操控遥控杆,任意时刻都可以取消或者返回上一步。将接收器和CC3D连接正确,CC3D使用电池供电,开启遥控器电源。看到接收器FS-R6B上红色的LED亮起,则表示遥控器和接收器连接(对频)成功,可以进行后面的操作。如果LED未亮起,可以从下面几点检查:
- 接收器和CC3D连接是否正确。注意连接线的正反和顺序。
- CC3D电源供电是否开启。测试发现,只使用USB给CC3D供电是无法满足接收器的供电的。
- 接收器和遥控器是否需要对频。
Next,进入遥控器发射机类型选择,Acro类型或者直升机类型。Acro类型适用于固定翼或四轴,我们选择Acro类型。
Next,进入遥控器操作模式选择,也就是常说的美国手或者日本手选择。提供4种模式,根据个人习惯去选择,笔者选择默认模式美国手,即Mode 2。油门和方向在左,俯仰和横滚在右。
Next,根据屏幕指示去操作遥控器,分别对油门、横滚、俯仰、方向即模式进行校准。
Next,飞行模式校准,这里由于富斯I6的遥控,没有对应的通道切换开关,但是富斯I6的VRA旋钮开关与之对应,可通过旋钮开关进行配置。Next还有关于Accessory0、Accessory1、Accessory2的配置,没有对应开关选择点击Next直接跳过。
各项对应配置完成之后,操作界面将会提示将各通道开关归中。由于遥控没有后面对应的遥控通道,在配置中直接跳过,这里选择跳过。
Next,操作提示随意拨动油门、横滚、俯仰、方向摇杆及模式切换开关,观察是否与实际的摇杆动作方向一致。若某个通道方向相反,可以通过勾选其对应通过取反,无需在遥控器上配置,如图所示。
截止以上,遥控的通道操作基本配置完成,点击右下角Save保存,Next进入遥控的解锁配置操作,CC3D的地面站在配置遥控时默认把油门解锁关闭,解锁方式根据自己的个人习惯而定,提供自定义解锁方式,下面还有一个配置栏是设定无信号接收等待时间自动上锁,默认为30s。一般我们都会配置解锁操作为:油门拉到最低(throttle off),同时右手摇杆向左横打(Roll Left)。
最后点击Save保存设置。
最后可以测试遥控器配置是否正确。为了安全首先去掉桨叶。将CC3D上电,并且连上遥控器,可以看到CC3D上蓝色LED慢速闪烁,接收机上红色LED亮起。按照上面设定的解锁操作解锁飞机。如果解锁成功,CC3D上蓝色LED会快速闪烁。轻推油门到一定值,这时候电机就会开始转动。
- 导出保存设置信息
一番辛苦的设置之后,要记得导出当前的设置信息,否则,一旦某个地方调整了,或者固件升级了,顺便又抹除了数据,又要再折腾一遍。
5.试飞与调试参数
以上软件,硬件调整完成后,就可以装上螺旋桨进行试飞了。
如果试飞的时候,发生侧倾,翻转等问题的时候,可以参考下图进行细微的调整(一定要记得导出备份数据,调整参数真的很辛苦):
6.BB响
BB响,是一个简单测量整体电压的东西,精度够用,作用明显,有电压显示,低于设定电压就会BB叫,作用就是当电池电压不够的时候,提醒操作者,防止失控。
BB响的接线: BB响9个爪,插电池的充电接口(又称为平衡充接口)黑线在外面,红线在里面。如下图:
7.Q&A
- 电调,电机必须是统一型号的吗?
开始我也很纠结,不同型号,批次的电机,电调,频率不同,转速不同,会不会出现控制乱套的情况? 实际上,由于CC3D可以独立控制每一路的输出信号,并且依赖自身的陀螺仪来调整姿态,因此,没有这么严格的要求。实际上,就算是同一批次,同一型号的电调,电机,他们也是彼此之间存在误差的。比如,我这个四轴,由于其中的一个银燕的电机,电调烧毁了,我就替换成了一个朗科的电机跟好盈的电调,其他三个还是银燕的,也是能正常飞行的,只是参数要调整一下就好了。
8.资料网站
在Android Studio中进行单元测试和UI测试
本篇教程翻译自Google I/O 2015中关于测试的codelab,掌握科学上网的同学请点击这里阅读:Unit and UI Testing in Android Studio。能力有限,如有翻译错误,请批评指正。如需转载,请注明出处。
Github下载测试源码
目录
1.概述
在这个codelab中,你将学习如何在Android Studio中配置工程用于测试,在开发机器上编写并运行单元测试,以及如何在手机上做功能UI测试。
你会学到什么
- 更新包含JUnit和Android Testing Support Library的Gradle构建文件
- 编写运行在本机Java虚拟机上的单元测试
- 编写运行在手机或者虚拟机上的Espresso测试
你需要什么
- Android Studio v1.3.1+
- Android 4.0+的测试设备
2.创建新的Android Studio工程
如果是第一次启动Android Studio,从欢迎页选择“Start a new Android Studio project”。如果已经打开了一个工程,选择File>New>New Project...
“Create new project”向导会指导整个过程,在第一页输入如下内容:
Setting | Value |
---|---|
Application Name | TestingExample |
Company demain | testing.example.com |
这样会保证你的代码同codelab讲解的内容具有一致的命名。其他的选项都设置为默认,一路点击Next直到工程创建完毕。
点击Run按钮检查app是否运行正常,要么从模拟器列表中选择一个启动,要么确认开启了debug模式的设备通过USB同电脑正确连接。
app目前没有做任何事情,但是屏幕上应该显示“Hello world!”和app的名字。
经常被问及的问题
3.配置支持单元测试的工程
在写测试之前,让我们做下简单的检查,确保工程配置正确。
首先,确认在Build Variants窗口内的Test Artifact中选择了"Unit Tests"。
然后,在工程的src
文件夹内创建test
和test/java
文件夹。需要注意的是,你不能在Android视图下进行这些操作,要么在系统的文件管理器内创建,要么在工程窗口左上方点击下拉菜单选择Project视图。最终的工程结构应该是这样的:
(在codelab的剩余部分,你可以返回继续使用Android工程视图)
最后,打开工程的build.gradle(Module:app)
文件,添加JUnit4依赖,点击Gradle sync按钮。
1 2 3 4 5 |
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.1.1' testCompile 'junit:junit:4.12' } |
当你同步Gradle配置时,可能需要联网下载JUnit依赖。
4.创建第一个单元测试
现在,万事俱备,让我们开始写第一个测试吧。首先,创建一个非常简单的被测类:Calculator类。
然后,向类中添加一些基本的算术运算方法,比如加法和减法。将下列代码复制到编辑器中。不用担心实际的实现,暂时让所有的方法返回0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.example.testing.testingexample; public class Calculator { public double sum(double a, double b){ return 0; } public double substract(double a, double b){ return 0; } public double divide(double a, double b){ return 0; } public double multiply(double a, double b){ return 0; } } |
Android Studio提供了一个快速创建测试类的方法。只需在编辑器内右键点击Calculator类的声明,选择Go to > Test,然后"Create a new test…"
在打开的对话窗口中,选择JUnit4和"setUp/@Before",同时为所有的计算器运算生成测试方法。
这样,就会在正确的文件夹内(app/src/test/java/com/example/testing/testingexample)
生成测试类框架,在框架内填入测试方法即可。下面是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package com.example.testing.testingexample; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class CalculatorTest { private Calculator mCalculator; @Before public void setUp() throws Exception { mCalculator = new Calculator(); } @Test public void testSum() throws Exception { //expected: 6, sum of 1 and 5 assertEquals(6d, mCalculator.sum(1d, 5d), 0); } @Test public void testSubstract() throws Exception { assertEquals(1d, mCalculator.substract(5d, 4d), 0); } @Test public void testDivide() throws Exception { assertEquals(4d, mCalculator.divide(20d, 5d), 0); } @Test public void testMultiply() throws Exception { assertEquals(10d, mCalculator.multiply(2d, 5d), 0); } } |
请将代码复制到编辑器或者使用JUnit框架提供的断言来编写自己的测试。
5.运行单元测试
终于到运行测试的时候了!右键点击CalculatorTest
类,选择Run > CalculatorTest。也可以通过命令行运行测试,在工程目录内输入:
1 |
./gradlew test |
无论如何运行测试,都应该看到输出显示4个测试都失败了。这是预期的结果,因为我们还没有实现运算操作。
让我们修改Calculator类中的sum(double a, double b)
方法返回一个正确的结果,重新运行测试。你应该看到4个测试中的3个失败了。
1 2 3 |
public double sum(double a, double b){ return a + b; } |
作为练习,你可以实现剩余的方法使所有的测试通过。
可能你已经注意到了Android Studio从来没有让你连接设备或者启动模拟器来运行测试。那是因为,位于
src/tests
目录下的测试是运行在本地电脑Java虚拟机上的单元测试。编写测试,实现功能使测试通过,然后再添加更多的测试...这种工作方式使快速迭代成为可能,我们称之为测试驱动开发。
值得注意的是,当在本地运行测试时,Gradle为你在环境变量中提供了包含Android框架的android.jar包。但是它们功能不完整(所以,打个比方,你不能单纯调用Activity
的方法并指望它们生效)。推荐使用Mockito等mocking框架来mock你需要使用的任何Android方法。对于运行在设备上,并充分利用Android框架的测试,请继续阅读本篇教程的下个部分。
6.配置支持Instrumentation测试的工程
虽然在Android框架内支持运行instrumentation测试,但是目前开发重心主要集中在刚刚发布的作为Android Testing Support Library一部分的新的AndroidJUnitRunner
。测试库包含Espresso,用于运行功能UI测试的框架。让我们通过编辑build.gradle
的相关部分来把它们添加进我们的工程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.example.testing.testingexample" minSdkVersion 15 targetSdkVersion 22 versionCode 1 versionName "1.0" //ADD THIS LINE: testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } //ADD THESE LINES: packagingOptions { exclude 'LICENSE.txt' } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.0.0' //← MAKE SURE IT’S 22.0.0 testCompile 'junit:junit:4.12' //ADD THESE LINES: androidTestCompile 'com.android.support.test:runner:0.2' androidTestCompile 'com.android.support.test:rules:0.2' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' } |
重要:由于一些依赖版本冲突,你需要确认
com.android.support:appcompat-v7
库的版本号是22.0.0
,像上面的代码片段一样。
另外,Android Studio可能会提醒你Build Tools 22.0.1
没有安装。你应该接受修复建议,Studio会为你安装Build Tools或者在build.gradle中把这行修改成已经安装在你电脑的版本。
上面的工作完成后,在Build Variants窗口内切换成Android Instrumentation Tests,你的工程应该自动同步。如果没有,点击Gradle sync按钮。
7.为app添加简单的交互
在使用Espresso进行UI测试前,让我们为app添加一些Views和简单的交互。我们使用一个用户可以输入名字的EditText,欢迎用户的Button和用于输出的TextView。打开res/layout/activity_main.xml
,粘贴如下代码:
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:hint="Enter your name here" android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/textView"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Say hello!" android:layout_below="@+id/editText" android:onClick="sayHello"/> </RelativeLayout> |
还需要在MainActivity.java
中添加onClick Handler:
1 2 3 4 5 |
public void sayHello(View v){ TextView textView = (TextView) findViewById(R.id.textView); EditText editText = (EditText) findViewById(R.id.editText); textView.setText("Hello, " + editText.getText().toString() + "!"); } |
现在可以运行app并确认一切工作正常。在点击Run按钮之前,确认你的Run Configuration没有设置为运行测试。如需更改,点击下拉选项,选择app。
8.创建并运行Espresso测试
在工程的整体视图上,找到以(androidTest
)后缀结尾的包名并创建一个新的Java类。可以将它命名为MainActivityInstrumentationTest
,将如下代码粘贴过去。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package com.example.testing.testingexample; import android.support.test.InstrumentationRegistry; import android.support.test.espresso.action.ViewActions; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.LargeTest; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; import static android.support.test.espresso.action.ViewActions.typeText; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; @RunWith(AndroidJUnit4.class) @LargeTest public class MainActivityInstrumentationTest { private static final String STRING_TO_BE_TYPED = "Peter"; @Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>( MainActivity.class); @Test public void sayHello(){ onView(withId(R.id.editText)).perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard()); //line 1 onView(withText("Say hello!")).perform(click()); //line 2 String expectedText = "Hello, " + STRING_TO_BE_TYPED + "!"; onView(withId(R.id.textView)).check(matches(withText(expectedText))); //line 3 } } |
测试类通过AndroidJUnitRunner运行,并执行sayHello()
方法。下面将逐行解释都做了什么:
- 1.首先,找到ID为
editText
的view,输入Peter
,然后关闭键盘; - 2.接下来,点击
Say hello!
的View,我们没有在布局的XML中为这个Button设置id,因此,通过搜索它上面的文字来找到它; - 3.最后,将
TextView
上的文本同预期结果对比,如果一致则测试通过;
你也可以右键点击域名运行测试,选择Run>MainActivityInstrume...(第二个带Android图标的)
这样就会在模拟器或者连接的设备上运行测试,你可以在手机屏幕上看到被执行的动作(比如在EditText
上打字)。最后会在Android Studio输出通过和失败的测试结果。
9.祝贺
我们希望你能喜欢本篇教程,并且开始着手测试你的应用程序。接着你可以学习如下内容:
- 了解更多关于单元测试和instrumentation测试的区别;
- 了解更多关于设置Android Testing Support Library;
- 观看下面非常棒的有关Android Studio的视频:
- 在Github下载Google测试示例代码