Arduino 命令行指南:使用 Git 和 Vim 摆脱 GUI!

喜欢 Arduino 但讨厌 GUI?试试 arduino-cli。

在本文中,我将探讨 Arduino 团队发布的一款新工具,它可以让您摆脱现有的基于 Java 的 Arduino 图形用户界面。这允许开发人员使用他们偏好的工具和工作流程。也许更重要的是,它将使 Arduino 工具链本身更容易、更深入地进行创新。

美好的旧时光

当我在 20 世纪 90 年代开始使用微处理器构建业余电子项目时,这个过程需要一个分立的处理器、RAM、ROM 和大量的胶合逻辑芯片,它们使用点对点或“绕线”技术连接在一起。(孩子们,查一下!)程序存储在玻璃窗口 EPROM 芯片上,需要用紫外线擦除。所有工具都很昂贵且难以使用,开发周期非常缓慢。图 1-3 显示了我 20 世纪 90 年代中期使用分立 CPU、RAM 和 ROM 的微处理器项目的一些示例。注意:没有闪存,没有 I/O,没有 DAC,没有 ADC,没有定时器——所有这些都意味着更多的芯片!

""

图 1. 20 世纪 90 年代中期的微处理器示例

""

图 2. 20 世纪 90 年代中期的微处理器示例

""

图 3. 20 世纪 90 年代中期的微处理器示例

这一切都在 2003 年随着 Arduino 的出现而改变。

“Arduino”这个词经常会引起广泛的意见,有时甚至是情绪。对于许多人来说,它代表着进入微控制器世界的极低门槛。2003 年之前的这个世界通常需要昂贵、晦涩和闭源的开发工具。Arduino 一直是一个伟大的均衡器,打破了封闭花园的大门。Arduino 现在代表着一个庞大的硬件生态系统,它使用(大部分)通用语言,并简化了从一个硬件平台到另一个硬件平台的过渡。今天,如果您是一家销售微控制器的公司,那么让您的开发板与 Arduino 协同工作符合您的最佳利益。它为您的产品快速进入大量用户手中提供了一条低摩擦的路径。

同样重要的是要注意,Arduino 的简单性并没有限制深入挖掘微控制器。没有什么能阻止您直接调整寄存器和使用高级功能。然而,这确实会降低您在板之间的可移植性。

对于嵌入式开发新手来说,Arduino 软件非常容易上手。这是它成功的一个主要原因——它开箱即用,随时可用。但对于更有经验的开发人员来说,包含的图形用户界面可能会令人沮丧。它可能成为使用现代开发工具和版本控制(如 Git)的障碍。我知道编译器和工具链都深深地埋藏在 GUI 的某个地方。我只是想使用我最喜欢的编辑器,编译我的代码,并使用我喜欢的工作流程将我的项目上传到开发板。对于许多开发人员来说,这是一个命令行或脚本化的过程。

进入 arduino-cli

之前曾有几次尝试将 Arduino 分离到命令行,但大多数都未能获得广泛的支持。然而,现在 Arduino 团队已经 alpha 发布了 arduino-cli。这个新框架不仅提供了一套全面的命令行功能,而且该团队还表示它将用作下一代 Arduino 图形界面底层的核心。这是一个令人兴奋的消息,并表明了对这个新概念的承诺。

对我来说,我首选的开发工作流程是使用 Git 进行版本控制和 Vim 编辑器,所以这就是我在本文的其余部分演示的内容。

安装 arduino-cli

在撰写本文时,arduino-cli 仍处于 alpha 发布阶段。它以 Go 源代码包和预构建二进制文件的形式分发。Go 语言生成非常可移植的二进制文件,因此您只需要下载正确的文件并将二进制文件放在 $PATH 中的某个位置即可。大多数阅读本文的用户可能需要适用于 Intel/AMD 系统的 Linux 64 位版本。这里的示例中,我的系统碰巧运行的是 Fedora 29,但任何最近的 Linux 版本都应该可以工作。查看项目的 GitHub 页面以获取更新的版本;在撰写本文时,0.3.2 是最新的 alpha 版本。最后,确保您的用户可以通过将他们添加到“dialout”组来访问串行和 USB 连接的 Arduino 开发板(注意:您需要重新登录才能获取新的组成员身份,并在最后一个命令中将“me”替换为您的用户名)


me@mybox:~ $ wget https://downloads.arduino.cc/arduino-cli/
↪arduino-cli-0.3.2-alpha.preview-linux64.tar.bz2
***downloading***
me@mybox:~ $ tar -xjf arduino-cli-0.3.2-alpha.preview-
↪linux64.tar.bz2
me@mybox:~ $ sudo mv arduino-cli-0.3.2-alpha.preview-linux64
 ↪/usr/local/bin/arduino-cli
me@mybox:~ $ sudo usermod -a -G dialout me

假设 /usr/local/bin 在您的 $PATH 中,您应该能够以 Linux 系统上的任何用户身份运行 arduino-cli。

或者,如果您想从源代码构建 Go 包,您可以使用 get 函数从 Arduino GitHub 存储库下载、构建和安装源代码包


me@mybox:~ $ sudo dnf -y install golang
me@mybox:~ $ cd ; export GOPATH=`pwd`/go
me@mybox:~ $ go get -u github.com/arduino/arduino-cli
me@mybox:~ $ sudo mv $GOPATH/bin/arduino-cli /usr/local/bin/

Arduino 命令行指南

首先,让我们做一些内务处理。您需要拉取当前的 Arduino “核心”索引,并搜索支持您的开发板的核心。在第一个示例中,让我们安装对由 ATMega AVR 处理器驱动的经典 UNO 板的支持


me@mybox:~ $ arduino-cli core update-index
Updating index: package_index.json downloaded
me@mybox:~ $ arduino-cli core search avr
Searching for platforms matching 'avr'

ID                    Version   Name
arduino:avr           1.6.23    Arduino AVR Boards
arduino:megaavr       1.6.24    Arduino megaAVR Boards
atmel-avr-xminis:avr  0.6.0     Atmel AVR Xplained-minis
emoro:avr             3.2.2     EMORO 2560
littleBits:avr        1.0.0     littleBits Arduino AVR Modules

me@mybox:~ $ arduino-cli core install arduino:avr
*** lots of downloading omitted ***
me@mybox:~ $ arduino-cli  core list
ID                   Installed   Latest  Name
arduino:avr@1.6.23   1.6.23      1.6.23  Arduino AVR Boards

就是这样。您已经拥有了为 Arduino UNO 板创建新的 Arduino 项目所需的一切。现在,让我们创建一个名为 myBlinky 的项目。您还将初始化并设置一个 Git 存储库来管理版本控制,然后进行您的第一次提交


me@mybox:~ $ arduino-cli sketch new myBlinky
Sketch created in: /home/me/Arduino/myBlinky
me@mybox:~ $ cd /home/me/Arduino/myBlinky
me@mybox:~/Arduino/myBlinky $ git config --global
 ↪user.email "me@mybox.com"
me@mybox:~/Arduino/myBlinky $ git config --global
 ↪user.name "My Name"
me@mybox:~/Arduino/myBlinky $ git init
Initialized empty Git repository in /home/me/Arduino/
↪myBlinky/.git/
me@mybox:~/Arduino/myBlinky $ ls -la
total 16
drwxr-xr-x 3 me me 4096 Nov 22 10:45 .
drwxr-xr-x 3 me me 4096 Nov 22 10:45 ..
drwxr-xr-x 7 me me 4096 Nov 22 10:45 .git
-rw-r--r-- 1 me me   35 Nov 22 10:45 myBlinky.ino

me@mybox:~/Arduino/myBlinky $ cat myBlinky.ino

void setup() {
}

void loop() {
}

me@mybox:~/Arduino/myBlinky $ git add -A
me@mybox:~/Arduino/myBlinky $ git commit -m "Initial Commit"
[master (root-commit) ee95972] Initial Commit
1 file changed, 6 insertions(+)
create mode 100644 myBlinky.ino

me@mybox:~/Arduino/myBlinky $ git log
commit ee9597269c5da49d573d6662fe8f8137083b7768
 ↪(HEAD -> master)
Author: My Name <me@mybox.com>
Date:   Thu Nov 22 10:48:33 2018 -0500

   Initial Commit

不错!该工具在图形工具期望找到它们的相同 Arduino 目录结构下创建项目,允许您在工具之间切换(如果您愿意)。它还创建了一个包含熟悉的 setup()loop() 函数的模板 .ino 文件。

空的 Git 存储库已初始化,您可以看到它创建了 .git 子目录,所有版本数据都将保存在其中。是时候编码了!

现在,只需在您喜欢的编辑器中打开 myBlinky.ino ——为了最大限度地提升街头信誉,当然是 Vim。永远不要 EMACS(开玩笑!)。。。说真的,使用任何你喜欢的编辑器(我听说 Eclipse 也不错)——然后输入并保存一个经典的“Hello World”闪烁程序。像这样


// Simple Demo Blinker -MEH
#define PIN_LED 13

void setup() {
       pinMode(PIN_LED,OUTPUT);
}

void loop() {
       digitalWrite(PIN_LED,HIGH);
       delay(500);
       digitalWrite(PIN_LED,LOW);
       delay(500);
}

现在,让我们编译并将其上传到 Arduino UNO。使用 board 命令集来搜索上传


me@mybox:~/Arduino/myBlinky $ arduino-cli   board list
FQBN            Port           ID          Board Name
arduino:avr:uno /dev/ttyACM0   2341:0001   Arduino/Genuino Uno

找到了开发板。现在编译


me@mybox:~/Arduino/myBlinky $ arduino-cli  compile -b
 ↪arduino:avr:uno
Build options changed, rebuilding all
Sketch uses 930 bytes (2%) of program storage space. Maximum
 ↪is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving
 ↪2039 bytes for local variables. Maximum is 2048 bytes.

编译干净利落。接下来,使用 upload 命令、开发板名称和您之前发现的端口上传到开发板


me@mybox:~/Arduino/myBlinky $ arduino-cli  upload
 ↪-b arduino:avr:uno -p /dev/ttyACM0

与命令行工具常见的情况一样,沉默是金。upload 命令完成,UNO 愉快地闪烁起来。您最好使用 git commit 锁定这种好运


me@mybox:~/Arduino/myBlinky $ git commit -a -m "It works!
 ↪First blink."
[master 35309a0] It works! First blink.
1 file changed, 7 insertions(+)

-m 选项接受提交消息;它应该是关于此提交中包含内容的注释。如果您省略消息,git 将在文本编辑器中打开一个模板消息(默认是 Vim,但您可以通过设置 $EDITOR 来更改它)。

对第三方开发板的支持

现在来点更雄心勃勃的东西,让我们尝试使用非 Arduino 开发板,并逐步完成添加第三方核心的步骤。即使使用图形用户界面,这也很棘手,但使用 arduino-cli 却非常简单。让我们以非常流行的 ESP8266 为目标。

首先,您需要将第三方存储库添加到文件中,以便 arduino-cli 知道如何定位核心。这是通过名为 .cli-config.yml 的文件完成的。您可能会认为这应该放在您的主目录或项目目录中,并且您这样想是对的。但是,arduino-cli 早期版本的一个怪癖是,该文件位于 arduino-cli 程序所在的目录中。目前,这是 /usr/local/bin,但请密切关注网站,因为这很可能在未来的版本中发生变化!在下面,您将添加一个新的开发板配置定义。此文件使用 YAML 格式,因此请注意仅在缩进中使用空格。编辑(使用 sudo),并将以下文本放在 /usr/local/bin/.cli-config.yml 中


board_manager:
 additional_urls:
   - http://arduino.esp8266.com/stable/
↪package_esp8266com_index.json

现在,像以前一样,更新索引并安装核心


me@mybox:~/Arduino/myBlinky $ arduino-cli core update-index
Updating index: package_index.json downloaded                                                                                                                            
Updating index: package_esp8266com_index.json downloaded

您可以看到它找到了并下载了 esp8266 核心的索引。很好。现在,让我们下载并安装核心本身


me@mybox:~/Arduino/myBlinky $ arduino-cli core search esp
Searching for platforms matching 'esp'

ID              Version Name
esp8266:esp8266 2.4.2   esp8266

me@mybox:~/Arduino/myBlinky $ arduino-cli core install
 ↪esp8266:esp8266
Downloading esp8266:esptool@0.4.13...
esp8266:esptool@0.4.13 downloaded  *** much omitted ***

现在,您可以为 esp8266 重建您的 myBlinky 项目并上传它。您首先需要编辑您的 myBlinky.ino 并将 #define PIN_LED 更改为具有 LED 的引脚。在我的开发板上,它是引脚 2。进行修改并保存它


#define PIN_LED 2

插入 esp8266 开发板后,您再次运行 board list 命令以尝试找到它


me@mybox:~/Arduino/myBlinky $ arduino-cli board list
FQBN    Port            ID              Board Name
       /dev/ttyUSB0    1a86:7523       unknown

它检测到了它,但无法确定它是什么。这对于像 esp8266 这样需要按下按钮或特殊编程模式的开发板来说非常常见。

接下来,在按下编程按钮的同时重置您的 esp8266 开发板后,进行编译和上传。像上次一样,使用在 list 操作期间发现的开发板名称和端口


me@mybox:~/Arduino/myBlinky $ arduino-cli board listall
 ↪|grep esp8266
Generic ESP8266 Module                  esp8266:esp8266:generic
(omitted long list)
me@mybox:~/Arduino/myBlinky $ arduino-cli upload  -b
 ↪esp8266:esp8266:generic -p /dev/ttyUSB0
Uploading 252000 bytes from /home/me/Arduino/myBlinky/
↪myBlinky.esp8266.esp8266.generic.bin to flash at 0x00000000
..................................................... [ 32% ]
..................................................... [ 64% ]
..................................................... [ 97% ]
.......                                               [ 100% ]

并且,它闪烁了!再次 git commit 并保存您的进度


me@mybox:~/Arduino/myBlinky $ git add -A
me@mybox:~/Arduino/myBlinky $ git commit  -m
 ↪"Blinking on esp8266 board"
[master 2ccff1d] Blinking on esp8266 board
5 files changed, 61 insertions(+), 1 deletion(-)
create mode 100755 myBlinky.arduino.avr.uno.elf
create mode 100644 myBlinky.arduino.avr.uno.hex
create mode 100644 myBlinky.esp8266.esp8266.generic.bin
create mode 100755 myBlinky.esp8266.esp8266.generic.elf

正如您所看到的,它将编译后的代码的二进制版本保存在项目目录中。如果您希望将这些文件从您的提交中省略,您可以将 *.bin、*.hex 和 *.elf 添加到 .gitignore 文件中。如果您保存了它们,则可以使用 -i 选项和 .bin 文件来上传特定的二进制文件。

添加库

在您的成功基础上,您应该下载并安装一个库。让我们提升闪烁游戏的水平,并安装对一些 Adafruit NeoPixels(又名 WS2812B、PL9823 等)的支持。首先,使用 lib 命令搜索它,然后下载并安装


me@mybox:~/Arduino/myBlinky $ arduino-cli  lib  search neopixel
(omitting large list)
me@mybox:~/Arduino/myBlinky $ arduino-cli  lib  install
 ↪"Adafruit NeoPixel"
Adafruit NeoPixel@1.1.7 downloaded                                                                                                                                       
Installed Adafruit NeoPixel@1.1.7

现在您需要修改程序;使用这些修改编辑 .ino 文件


// Fancy NeoPixel Blinky Blinker

#include <Adafruit_NeoPixel.h>
#define PIN_LED 14

Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, PIN_LED,
 ↪NEO_GRB + NEO_KHZ800);

void setup() {
       strip.begin();
}

void loop() {

       strip.setPixelColor(0,strip.Color(255,0,0))'
       delay(200);
       strip.setPixelColor(0,strip.Color(0,255,0));
       delay(200);
       strip.setPixelColor(0,strip.Color(0,0,255));
       delay(200);
}

接下来,执行相同的编译和上传步骤,当然,在将 NeoPixel 或兼容 LED 连接到引脚 14 之后


me@mybox:~/Arduino/myBlinky $ arduino-cli compile -b
 ↪esp8266:esp8266:generic
Build options changed, rebuilding all
Sketch uses 248592 bytes (49%) of program storage space.
 ↪Maximum is 499696 bytes.
Global variables use 28008 bytes (34%) of dynamic memory,
 ↪leaving 53912 bytes for local variables. Maximum
 ↪is 81920 bytes.
me@mybox:~/Arduino/myBlinky $ arduino-cli upload  -b
 ↪esp8266:esp8266:generic -p /dev/ttyUSB0
Uploading 252960 bytes from /home/me/Arduino/myBlinky/
↪myBlinky.esp8266.esp8266.generic.bin to flash at 0x00000000
.................................................... [ 32% ]
.................................................... [ 64% ]
.................................................... [ 96% ]
........                                             [ 100% ]

并且,您应该有一个彩色闪烁——非常漂亮。现在是提交更改以记录您的进度的另一个好时机


me@mybox:~/Arduino/myBlinky $ git add -A
me@mybox:~/Arduino/myBlinky $ git commit -m
 ↪"Blinky with NeoPixels"
[master 122911f] Blinky with NeoPixels
3 files changed, 20 insertions(+), 13 deletions(-)
rewrite myBlinky.ino (81%)

使用 GitHub

到目前为止,git 存储库完全位于您的项目目录中。这没什么问题,但假设您想将您的工作发布到 GitHub。入门非常快速和容易。首先,登录到 github.com 并创建一个帐户(如果您还没有帐户)。然后,单击按钮以创建一个“新存储库”。

""

图 4. 新存储库

填写您的项目的详细信息,并确保取消选中使用 README 初始化存储库的选项。这是因为您已经创建了一个存储库,并且您将“推送”您的本地存储库到 GitHub,所以您希望它是空的。

""

图 5. 创建存储库

创建后,您将看到一些关于如何将代码推送到 GitHub 的有帮助的选项。您需要“推送现有存储库”的命令。

""

图 6. 推送现有存储库

现在让我们开始吧!按照说明创建一个名为“origin”的 git “远程”条目,它将代表 GitHub。然后您将推送,它将提示您输入您的 GitHub 用户名和密码(替换您自己的 GitHub URL、用户名和密码)


me@mybox:~/Arduino/myBlinky $ git remote add origin
 ↪https://github.com/sysmatt/myBlinky.git
me@mybox:~/Arduino/myBlinky $ git push -u origin master
Username for 'https://github.com': sysmatt
Password for 'https://sysmatt@github.com':  ******************
Counting objects: 18, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (18/18), 825.31 KiB | 5.00 MiB/s, done.
Total 18 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), done.
* [new branch]      master -> master
Branch master set up to track remote branch master from origin.

现在,如果您浏览到 GitHub.com 上的存储库,您将看到您的所有文件和您的每一个提交。您可以及时回溯并查看每个版本。在实践中,您可以使用 SSH 密钥来消除每次都必须输入密码的情况。

""

图 7. 提交历史

时间旅行(又名用 Git 打破物理定律)

你说时间旅行?确实如此。假设你想及时回到过去,回顾一下你的 myBlinky 版本,当时它还在 Arduino UNO 上工作。这似乎是很久以前的事了。这很容易!您只需要识别提交 ID 并“检出”该版本。

使用 log 命令列出您的所有提交


me@mybox:~/Arduino/myBlinky $ git log
commit 122911f99dddce2dabbb251c3b640c8c7f9f98d9 (HEAD ->
 ↪master, origin/master)
Author: My Name <me@mybox.com>
Date:   Thu Nov 22 21:22:59 2018 -0500

   Blinky with NeoPixels

commit 2ccff1d7326b1523649510f24644c96df6dc6e12
Author: My Name <me@mybox.com>
Date:   Thu Nov 22 11:42:02 2018 -0500

   Blinking on esp8266 board
commit 35309a0c9e90668052abc9644f77f906ab57949c
Author: My Name <me@mybox.com>
Date:   Thu Nov 22 11:09:44 2018 -0500

   It works! First blink.

commit ee9597269c5da49d573d6662fe8f8137083b7768
Author: My Name <me@mybox.com>
Date:   Thu Nov 22 10:48:33 2018 -0500

   Initial Commit

看起来以 35309a0c 开头的提交是您想要的那个。注意:您可以将提交哈希字符串缩短到最少四个字符,只要它唯一地标识一个提交即可。让我们探索一下该版本


me@mybox:~/Arduino/myBlinky $ git checkout 35309a0c
HEAD is now at 35309a0... It works! First blink.
me@mybox:~/Arduino/myBlinky $ ls -l
-rw-r--r-- 1 me me  191 Nov 22 22:01 myBlinky.ino
me@mybox:~/Arduino/myBlinky $ cat myBlinky.ino
// Simple Demo Blinker -MEH
#define PIN_LED 13

void setup() {
        pinMode(PIN_LED,OUTPUT);
}

void loop() {
        digitalWrite(PIN_LED,HIGH);
        delay(500);
        digitalWrite(PIN_LED,LOW);
        delay(500);
}

现在假设您已经完成浏览,那么让我们及时回到今天,让一切恢复到您打破物理定律之前的状态。在简单的 git 存储库中,这意味着跳转回“master”分支中的当前提交


me@mybox:~/Arduino/myBlinky $ git checkout master
Previous HEAD position was 35309a0... It works! First blink.
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
me@mybox:~/Arduino/myBlinky $ ls -l
total 1332
-rwxr-xr-x 1 me me   13956 Nov 22 22:04
 ↪myBlinky.arduino.avr.uno.elf
-rw-r--r-- 1 me me    2640 Nov 22 22:04
 ↪myBlinky.arduino.avr.uno.hex
-rw-r--r-- 1 me me  252960 Nov 22 22:04
 ↪myBlinky.esp8266.esp8266.generic.bin
-rwxr-xr-x 1 me me 1082905 Nov 22 22:04
 ↪myBlinky.esp8266.esp8266.generic.elf
-rw-r--r-- 1 me me     436 Nov 22 22:04 myBlinky.ino

不错!您又回到了 NeoPixel 闪烁。您看,git 将所有版本的已提交代码存储在 .git 子目录中。这实际上是存储库的真实位置。您编辑的文件只是“工作区”。当您在提交之间跳转时,git 会完成修改工作区中所有文件的神奇操作。如果您想跳回去并开始修改旧版本的代码,您可以创建一个新的“分支”来包含该工作,并继续使用 AVR 和 esp8266 代码的分支。它非常强大。

我在这里只触及了皮毛。Git、GitHub 和 arduino-cli 都是非常全面的工具。我希望本文能让您了解当您为 Arduino 项目利用良好的编程工作流程时,可能会实现什么。

资源

Matthew Hoskins 是新泽西理工学院的高级企业架构师,他在那里领导着一支才华横溢的专业人士团队,他们使我们令人眼花缭乱的各种服务协同工作。系统、存储、本地和云端,我们无所不能。当一切都做得对时,没有人会注意到。Matt 在 Twitter 上的账号是 @SYSMATT。

加载 Disqus 评论