电源设计技术信息网站

订阅电子杂志   English   繁體中文   日本語   한국어

下载中心

TECH INFORaspberry Pi初学者指南

如何在Raspberry Pi运行Arduino程序

这篇文章来源于DevicePlus.com英语网站的翻译稿。

arduino code raspberry pi

Raspberry Pi是一种了不起的小型机,我很想在某些项目中使用该设备。但是存在一个小问题,那就是我几乎没有任何Python经验。几年前,我曾经编写过Python代码,但是非常基础。我比较擅长C++,尤其是Arduino程序编写。那么我们有没有办法在Raspberry Pi上施展我们的Arduino编程技能呢?那样不是非常好吗?幸运的是,有办法!

本文将告诉您如何在Raspberry Pi上运行Arduino程序!为此,我们使用RasPiArduino框架。该架构能让我们把Arduino代码编译成可以在Raspberry Pi上运行的二进制文件。但是这样做之前,我们必须在Arduino IDE和Raspberry Pi上做一些准备。

硬件

  • Raspberry Pi 3 Model B

软件

 

Arduino IDE 设置

1. 打开Arduino安装文件夹。在Windows系统中,该文件夹的路径一般是“C:\Program Files\Arduino”(32位系统)或者“C:\Program Files(x86)\Arduino”(64位系统)。

图1 Arduino安装文件夹

2. 打开文件夹“hardware”,并在该文件夹中创建一个名为“RaspberryPi”的新文件夹。

图2 新建的文件夹

3. 请打开以下链接https://github.com/me-no-dev/RasPiArduino,并将该库克隆到“RaspberryPi”内的新文件夹“piduino”中。如果您不想克隆该库,那么可以将库内容下载为zip文件,然后将其解压到“piduino”文件夹中。

图3 “piduino”文件夹的内容

4. 接下来,您必须从以下链接http://gnutoolchains.com/raspberry/下载GNU Toolchain(工具链)。您必须下载支持当前所用Raspberry OS系统的Toolchain版本。由于您可能使用了最新的Raspbian Stretch,因此您需要下载GCC 6.3.0版本。下载完成之后,运行该文件。安装路径“C:\SysGCC\raspberry”保留不变,勾选接受许可协议,然后单击“Install”按钮。安装过程需要一点时间。

arduino code raspberry pi

图4 GNU Toolchain安装程序

5. 请在Arduino安装目录中打开步骤3中创建的“piduino”文件夹。打开文件“platform.txt”,将第5行

runtime.tools.toolchain.path={runtime.platform.path}/tools/arm-linux-gnueabihf

改为

runtime.tools.toolchain.path=C:/SysGCC/Raspberry

这会将编译器指向我们在步骤4中安装的包含工具链的目录。

arduino code raspberry pi

图5 platform.txt的内容

6. 重新启动Arduino IDE,打开一个新程序。现在,在“Tools”菜单的“Board”选项下面应该有一个名为“RaspberryPI B+/2”的新板。为了确保所有组件都正确安装,请选择Raspberry Pi板,复制下面的代码并编译程序。编译时间可能比Arduino开发板更长,而且中间会产生一些警告,但是只要最后显示“Done compiling”,就可以了。

void setup() {
Console.println("This is the SETUP function");
}

void loop() {
Console.println("This is the LOOP function");
delay(1000);
}

 

arduino code raspberry pi

图6 Arduino IDE中的Raspberry Pi板

 

Raspberry Pi 设置

1. 请点击以下链接https://www.raspberrypi.org/downloads/,下载最新的Raspberry OS–Raspbian Stretch。将其安装到Raspberry(可以用NOOBS安装程序,也可以直接将其安装到SD卡)。

2. RasPiArduino 框架需要超级用户(root)权限才能运行,而且应该设置复杂密码进行保护。如果您已经在系统配置过程中设置了超级用户(root)密码,那么可以跳过此步骤。打开Raspberry终端,并输入以下命令

sudo su

您现在已经以超级用户(root)用户身份登录。请用以下命令设置密码

passwd

并在系统提示时再次输入密码进行确认。

3. 可选,但强烈建议执行此步骤。本次配置的剩余部分都在Raspberry终端中完成。为了简便起见,我建议大家在电脑上用SSH通过本地网络控制Raspberry终端。否则的话,您还得在桌上放置另一个键盘和一个显示器,这会非常不方便。

在Raspberry上设置SSH非常简单,只需按照以下说明操作即可:https://www.raspberrypi.org/documentation/remote-access/ssh/

SSH设置完成后,还得在电脑上下载某种SSH终端程序。我用的程序叫做MobaXterm,该终端程序对于个人使用是免费的,并且非常易于控制。它还支持SFTP(SSH文件传输协议),凭借此协议您可以通过拖放的方式将文件移动到Raspberry。通过SSH登录时,还必须强制输入超级用户(root)密码。为此,请使用以下命令:

sed -i “s/PermitRootLogin without-password/PermitRootLogin yes/” /etc/ssh/sshd_config

4. 现在,我们必须在启动时禁用串行控制台(Serial Console)。打开文件/boot/cmdline.txt,并将其内容更改为

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

5. 接下来是用下面的命令完全禁用串行TTY:

systemctl disable serial-getty@ttyAMA0

6. 现在,我们应禁止加载内核声音模块。为此,请使用以下命令:

sed -i “s/dtparam=audio=on/#dtparam=audio=on/” /boot/config.txt

7. 可选步骤。通过设置avahi服务,您可以直接从Arduino IDE上传Arduino程序,就好像在为普通的Arduino开发板编程一样。打开文件/etc/avahi/services/arduino.service(如果该文件不存在,请创建该文件),并将以下文本复制到其中:

<?xml version=”1.0″ standalone=’no’?><!–*-nxml-*–>
<!DOCTYPE service-group SYSTEM “avahi-service.dtd”>
<service-group>
<name replace-wildcards=”yes”>%h</name>
<service>
<type>_arduino._tcp</type>
<port>22</port>
<txt-record>board=bplus</txt-record>
</service>
</service-group>

完成后,您必须使用以下命令重新启动avahi服务:

service avahi-daemon restart
8. 安装telnet和git。在终端程序上,执行此操作的最简单方法就是使用包管理器。首先,请确保将包列表更新到最新版。

apt-get update

然后,安装telnet和git。

apt-get install telnet git

9. 将RasPiArduino框架程序库克隆到您的Raspberry中。

git clone https://github.com/me-no-dev/RasPiArduino.git piduino

克隆完成后,将所有重要文件做成可执行文件。

chmod +x piduino/tools/arpi_bins/*

然后,将其拷到用户目录下。

cp piduino/tools/arpi_bins/* /usr/local/bin

我们不需要其余的RasPiArduino框架文件库,因此您可以将其删除。

rm -rf piduino

10. 现在您必须为run-avrdude脚本创建符号链接。该脚本是我们在上一步中复制并将其变成可执行文件的RasPiArduino文件之一。

ln -s /usr/local/bin/run-avrdude /usr/bin/run-avrdude

11. 可选步骤。您可以同步网络时间,并让程序在系统启动时开始。首先,安装NTP(网络时间协议)实用工具。

apt-get install ntpdate

接下来,打开文件/etc/rc.local,将其内容更改为:

#!/bin/sh -e

_IP=\$(hostname -I) || true if [ “\$_IP” ]; then
printf “My IP address is %s\n” “\$_IP”

fi

# Sync Time

ntpdate-debian -u > /dev/null
# Start Sketch

/usr/local/bin/run-sketch > /dev/null

exit 0

12. 大功告成!现在,我们重启Raspberry Pi。如果一切顺利,您现在能够用Arduino IDE连接Raspberry了。选择正确的板卡(RaspberryPI B+/2)和正确的端口(Raspberry的本地IP地址)。

arduino code raspberry pi

图7 Arduino IDE中的Raspberry Pi IP端口

如果按照上述步骤操作,您的Raspberry现在应该可以通过Arduino IDE进行编程了。对了,还有一个小细节需要讲一下。Arduino功能的核心是通过各种数字和模拟输入和输出与外界交互。Raspberry配有GPIO排针接头,其引脚映射和功能如下图所示。RasPiArduino Pin #(引脚编号)列中的数字与GPIO引脚编号相对应,程序中应使用该引脚编号。

arduino code raspberry pi

图8 RasPiArduino框架中的Raspberry Pi引脚映射

请注意,Raspberry Pi只有4个引脚具有PWM输出功能,没有可以读取模拟电压的引脚!此外,与大多数Arduino开发板不同,Raspberry运行在3.3V逻辑上——逻辑1对应3.3 V。Raspberry GPIO引脚无法承受5V电压!如果直接将5V电压施加到这些引脚上,那么很有可能会损坏Raspberry Pi!

 

基础示例:LED和控制台

理论描述到此为止,现在我们将其付诸实践!我们从最简单的Arduino基本功能开始:LED和串行输出。我使用的Arduino程序如下所示。我对Arduino的“淡入淡出”程序进行了简单修改。该程序通过PWM(脉冲宽度调制)调节LED的亮度,并将当前PWM值打印到控制台。

// GPIO pin with PWM support
int pwmLedPin = 12;

// GPIO pin without PWM support
int onOffLedPin = 6;

void setup() {
// set both pins to output
pinMode(pwmLedPin, OUTPUT);
pinMode(onOffLedPin, OUTPUT);
}

void loop() {
// turn the first LED fully on
digitalWrite(onOffLedPin, HIGH);
// fade in the second LED
for(int pwm = 0; pwm <= 255; pwm += 5) {
// set the PWM value
analogWrite(pwmLedPin, pwm);
// print the PWM value to console
Console.println(pwm);
delay(30);
}

// turn the first LED fully off
digitalWrite(onOffLedPin, LOW);
// fade out the second LED
for(int pwm = 255; pwm >= 0; pwm -= 5) {
// set the PWM value
analogWrite(pwmLedPin, pwm);
// print the PWM value to console
Console.println(pwm);
delay(30);
}
}

 

有了代码之后,我们需要将所有元器件连接在一起。其实并不复杂,只需连接两个LED和几个10k电阻即可。

arduino code raspberry pi

图9 本例的接线示意图

对Arduino开发板进行编程的最后一步:点击神奇的“Upload”按钮,然后系统会自动编译程序并将其上传到硬件中。在RasPiArduino框架下,将程序上传到Raspberry有两种方法。

1. 使用“Upload”按钮。将Raspberry连至您的本地网络,在“Tools”菜单中的“Ports”部分应该能看到其IP地址。选择该地址,就像选择Arduino COM端口一样,然后点击“Upload”。然后,系统会提示您输入超级用户(root)密码。输入后,系统会上传程序并自动执行。您可以在Arduino串行监视器中查看控制台输出结果。

2. 手动上传。在Arduino IDE中,进入菜单“Sketch”,然后点击“Export compiled binary”。系统会编译您的程序,并将二进制文件导出为.bin文件,文件的存放路径为程序文件夹。现在,我们得把此文件复制到Raspberry Pi。下一步是用以下命令将这个二进制文件变成可执行文件:

chmod +x exported_binary.bin

现在,您可以通过另一个命令来运行该二进制文件,必须以超级用户身份执行:

sudo ./exported_binary.bin

现在,所有控制台输出都将显示在控制台中。与其他任何终端程序一样,我们可以通过键盘快捷键Ctrl+C停止。我更喜欢手动上传,因为它不需要设置其他服务,并且通常更可靠(至少在我的配置中是这样的)。

请用以上两种方法其中的一种上传程序,然后观察两个LED。其中一个LED应该会不断闪烁,而另一个则会呈现淡入淡出效果!

arduino code raspberry pi

图10 Raspberry Pi控制两个LED

程序还将当前的PWM值打印到控制台中,具体输出情况如下图所示。

arduino code raspberry pi

图11 Raspberry Pi控制台输出

 

高级示例:SPI和I2C

显然,LED闪烁和控制台输出等功能可以完成许多不错的项目,但是我认为,如果添加一些更高级的功能,比如I2C和SPI,我们就可以做更多事情。RasPiArduino框架同样支持这些功能,所以我们可以用I2C总线将不同的传感器连至Raspberry;或者让Raspberry通过SPI总线与各通信模块进行通信。对于I2C器件,我使用的是罗姆传感器评估套件中的BH1745NUC颜色传感器;对于SPI,我用的是SX1278 LoRa模块。这两者的运行电压逻辑都是3.3V,因此只需几根线缆就可以将它们与Raspberry连接起来,非常简单。

arduino code raspberry pi

图12 本例的接线示意图

多亏了LoRaLib和RohmMultiSensor库,系统代码也非常简单!基本上就是LoRaLib库中的接收器示例代码加上RohmMultiSensor库中的BH1745NUC示例代码。

// define the sensor we will use
#define INCLUDE_BH1745NUC

// include the libraries
#include <RohmMultiSensor.h>
#include <LoRaLib.h>

// instantiate the sensor's class
BH1745NUC sensorColor;

// SX1278 digital I/O pin 0
int dio0 = 17;

// SX1278 digital I/O pin 1
int dio1 = 27;

// SX1278 SPI slave select pin
int nss = 22;

// create LoRa class instance
LoRa lora(CH_SX1278, nss, BW_125_00_KHZ, SF_9, CR_4_7, dio0, dio1);

// create empty instance of Packet class
Packet pack;

void setup() {
// start I2C communication
Wire.begin();

// initialize LoRa
uint8_t state = lora.begin();
if(state == ERR_NONE) {
Console.println("[SX1278]\tInitialization done.");
} else {
Console.print("[SX1278]\tInitialization failed, code 0x");
Console.println(state, HEX);
while(true);
}

// initialize the sensor with default settings
state = sensorColor.init();
if(state == 0) {
Console.println("[BH1745]\tInitialization done.");
} else {
Console.print("[BH1745]\tInitialization failed, code 0x");
Console.println(state, HEX);
while(true);
}

Console.println("-------------------------------------------------------------------");
}

void loop() {
Console.print("[SX1278]\tWaiting for incoming transmission ... ");

// wait for single packet
uint8_t state = lora.receive(pack);

if(state == ERR_NONE) {
// packet was suceesfully received
Console.println("success!");

// print the data of the packet
Console.print("[SX1278]\tData:\t\t");
Console.println(pack.data);

} else if(state == ERR_RX_TIMEOUT) {
// timeout occured while waiting for a packet
Console.println("timeout!");

} else if(state == ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Console.println("CRC error!");

}

Console.println("-------------------------------------------------------------------");

Console.print("[BH1745]\tColor Values (R-G-B-C):\t");

// measure the sensor values
sensorColor.measure();

// print the values to the console
Console.print(sensorColor.red);
Console.print('\t');
Console.print(sensorColor.green);
Console.print('\t');
Console.print(sensorColor.blue);
Console.print('\t');
Console.println(sensorColor.clear);

Console.println("-------------------------------------------------------------------");
}

 

电路实物如下图所示。虽然不漂亮,但是很实用。

arduino code raspberry pi

图13 已连接SX1278无线模块和BH1274NUC颜色传感器的Raspberry Pi

在此示例中,所有重要信息都被打印到Raspberry控制台。我们可以看到,SX1278成功接收到了包含字符串“Hello Raspberry!”的数据包(从Arduino通过LoRenz开发板发送),而且颜色传感器测量的值也是正确的!

arduino code raspberry pi

图14 Raspberry Pi控制台输出

结论

那么结论是:我们可以将Raspberry Pi当作Arduino开发板进行编程吗?绝对可以!但是,这两种系统都有优缺点。Raspberry的处理速度更快,Arduino功耗更低;Raspberry具有内置的HDMI和以太网端口,而Arduino具有内置的模数转换器。其他对比不再一一列举。但是,这归根结底是因为Arduino和Raspberry的应用场景不同。比如,如果您需要构建基于电池的传感器监控系统,请选Arduino。如果您需要通过机器学习来处理相机图片,请选Raspberry Pi。总之,我们必须根据系统要处理的任务类型选择适当组件,反之则不行。

DevicePlus 编辑团队
Jan Gromes

Jan目前在布尔诺理工大学学习电气工程。他拥有多年使用Arduino和其他微控制器构建项目的经验。他的特殊兴趣在于机器人系统的机械设计。

分享到社交媒体