通过Arduino端口扩展Raspberry Pi
作为制造者社区的成员,我们一直在寻找创造性的方式来使用硬件和软件。 这次, Patrick Lima和我决定我们想使用Arduino开发板扩展Raspberry Pi的端口,以便我们可以访问更多功能和端口并为设备添加一层保护。 有许多方法可以使用此设置,例如,构建跟随太阳的太阳能电池板,家庭气象站,操纵杆交互等等。
我们决定从构建一个仪表盘开始,该仪表盘允许以下串行端口交互:
- 控制三个LED以打开和关闭它们
- 控制三个LED调整其光强度
- 识别正在使用的端口
- 在操纵杆上显示输入动作
- 测量温度
我们还想在一个漂亮的用户界面(UI)中显示端口,硬件和传感器之间的所有交互,如下所示:
(Bruno Muniz, CC BY-SA 4.0 )
您可以使用本文中的概念来构建使用许多不同组件的许多不同项目。 您的想象力是极限!
1.开始
(Bruno Muniz, CC BY-SA 4.0 )
第一步是将Raspberry Pi的端口扩展为也使用Arduino端口。 使用Linux ARM的本机串行通信实现可以实现这一点,该实现使您能够使用Arduino的数字,模拟和脉宽调制(PWM)端口在Raspberry Pi上运行应用程序。
该项目使用TotalCross (一种用于构建嵌入式设备的UI的开源软件开发套件)来通过终端执行外部应用程序并使用本机串行通信。 您可以使用两个类来实现此目的: Runtime.exec和PortConnector 。 它们代表执行这些操作的不同方法,因此在本教程中我们将展示如何使用这两种方法,您可以决定哪种方法最适合您。
要启动该项目,您需要:
- 1树莓派3
- 1个Arduino Uno
- 3个LED
- 2个电阻介于1K和2.2K欧姆之间
- 1个按钮
- 1个电位计,介于1K和50K欧姆之间
- 1个原型板(又名面包板)
- 跳线
2.设置Arduino
创建通信协议以接收消息,处理消息,执行请求并在Raspberry Pi和Arduino之间发送响应。 这是在Arduino上完成的。
2.1定义消息格式
每条收到的消息将具有以下格式:
- 指示的功能称为
- 使用的端口
- 字符分隔符(如果需要)
- 需要发送的值
- 消息结束的指示
下表列出了具有相应功能,示例值和示例说明的字符列表。 本示例中使用的字符选择是任意的,可以随时更改。
性格 | 功能 | 例 | 示例说明 |
---|---|---|---|
* | 指令结束 | -- | -- |
, | 分隔器 | -- | -- |
# | 设置模式 | #8,0 * | 引脚8输入模式 |
< | 设定数字值 | <1,0 * | 将引脚1设置为低电平 |
> | 获得数字价值 | > 13 * | 获取值针13 |
+ | 获取PWM值 | + 6,250 * | 设置引脚6的值250 |
- | 获得类比价值 | -14 * | 获取值引脚A0 |
2.2源代码
以下源代码实现了上面指定的通信协议。 必须将其发送到Arduino,以便它可以解释和执行消息的命令:
void setup ( ) {
Serial. begin ( 9600 ) ;
Serial. println ( "Connected" ) ;
Serial. println ( "Waiting command..." ) ;
}
void loop ( ) {
String text = "" ;
char character ;
String pin = "" ;
String value = "0" ;
char separator = '.' ;
char inst = '.' ;
while ( Serial. available ( ) ) { // verify RX is getting data
delay ( 10 ) ;
character = Serial. read ( ) ;
if ( character == '*' ) {
action ( inst , pin , value ) ;
break ;
}
else {
text. concat ( character ) ; }
if ( character == ',' ) {
separator = character ;
if ( inst == '.' ) {
inst = character ; }
else if ( separator != ',' && character != inst ) {
pin. concat ( character ) ; }
else if ( character != separator && character != inst ) {
value. concat ( character ) ; }
}
}
void action ( char instruction , String pin , String value ) {
if ( instruction == '#' ) { //pinMode
pinMode ( pin. toInt ( ) , value. toInt ( ) ) ;
}
if ( instruction == '<' ) { //digitalWrite
digitalWrite ( pin. toInt ( ) , value. toInt ( ) ) ;
}
if ( instruction == '>' ) { //digitalRead
String aux = pin + ':' + String ( digitalRead ( pin. toInt ( ) ) ) ;
Serial. println ( aux ) ;
}
if ( instruction == '+' ) { // analogWrite = PWM
analogWrite ( pin. toInt ( ) , value. toInt ( ) ) ;
}
if ( instruction == '-' ) { // analogRead
String aux = pin + ':' + String ( analogRead ( pin. toInt ( ) ) ) ;
Serial. println ( aux ) ;
}
}
2.3制作电子产品
定义您需要测试以检查与Arduino的通信并确保输入和输出按预期响应的内容:
LED以正逻辑连接。 通过电阻连接到GND引脚,并通过数字端口I / O 2和PWM 3激活它。
该按钮具有连接到数字端口I / O 4的下拉电阻,如果未按下则发送信号0,如果按下则发送信号1。
电位计的中心引脚连接到模拟输入A0,其中一个侧面引脚位于正极,而另一个侧面引脚位于负极。
(Bruno Muniz, CC BY-SA 4.0 )
2.4测试通讯
将第2.2节中的代码发送到Arduino。 发送以下命令,打开串行监视器并检查通讯协议:
#2,1*<2,1*>2*
#3,1*+3,10*
#4,0*>4*
#14,0*-14*
这应该是串行监视器中的结果:
(Bruno Muniz, CC BY-SA 4.0 )
设备上的一个LED应该以最大强度点亮,而另一个应以较低强度点亮。
(Bruno Muniz, CC BY-SA 4.0 )
发送读数命令时,按下按钮并更改电位计的位置将显示不同的值。 例如,将电位计转到正极,然后按按钮。 在仍然按下按钮的情况下,发送命令:
> 4 *
- 14 *
应该出现两行:
(Bruno Muniz, CC BY-SA 4.0 )
3.设置Raspberry Pi
使用Raspberry Pi通过终端使用
cat命令读取条目,并使用echo
命令发送消息,通过终端访问串行端口。
3.1进行串行测试
将Arduino连接到Raspberry Pi的USB端口之一,打开终端,然后执行以下命令:
cat / dev / ttyUSB0 9600
这将启动与Arduino的连接并显示返回串行的内容。
(Bruno Muniz, CC BY-SA 4.0 )
要测试发送命令,请打开一个新的终端窗口(保持前一个打开),然后发送以下命令:
echo "command" > / dev / ttyUSB0 9600
您可以发送与2.4节相同的命令。
您应该在第一个终端中看到反馈以及在2.4节中得到的相同结果:
(Bruno Muniz, CC BY-SA 4.0 )
4.创建图形用户界面
第一部分使用两个UI组件:一个列表框和一个编辑。 它们在Raspberry Pi和Arduino之间建立连接,并测试一切是否按预期工作。
模拟您在其中放置命令的终端并观察答案:
- 编辑用于发送消息。 将其放置在底部,其填充宽度可将组件扩展到屏幕的整个宽度。
- 列表框用于显示结果,例如在终端中。 将其添加到TOP位置(从左端开始),其宽度等于Edit,而FIT高度则垂直占据未被Edit填充的所有空间。
package com.totalcross.sample.serial ;
import totalcross.sys.Settings ;
import totalcross.ui.Edit ;
import totalcross.ui.ListBox ;
import totalcross.ui.MainWindow ;
import totalcross.ui.gfx.Color ;
public class SerialSample extends MainWindow {
ListBox Output ;
Edit Input ;
public SerialSample ( ) {
setUIStyle ( Settings. MATERIAL_UI ) ;
}
@Override
public void initUI ( ) {
Input = new Edit ( ) ;
add ( Input, LEFT, BOTTOM, FILL, PREFERRED ) ;
Output = new ListBox ( ) ;
Output. setBackForeColors ( Color . BLACK , Color . WHITE ) ;
add ( Output, LEFT, TOP, FILL, FIT ) ;
}
}
它看起来应该像这样:
(Bruno Muniz, CC BY-SA 4.0 )
5.设置串行通讯
如上所述,有两种设置串行通信的方法:Runtime.exec和PortConnector。
5.1选项1:使用Runtime.exec
java.lang.Runtime
类允许应用程序与其运行环境一起创建连接接口。 它允许程序使用Raspberry Pi的本机串行通信。
使用与第3.1节中使用的命令相同的命令,但现在使用UI上的“编辑”组件将命令发送到设备。
阅读序列
应用程序必须不断读取序列号,如果返回值,请使用线程将其添加到列表框中。 线程是在后台处理进程而不阻止用户交互的一种好方法。
以下代码在此线程上创建一个新进程,该进程执行cat
命令,测试串行,并启动无限循环以检查是否接收到新消息。 如果收到内容,则该值将添加到“列表框”组件的下一行。 只要应用程序正在运行,此过程就将继续运行:
new Thread ( ) {
@Override
public void run ( ) {
try {
Process Runexec2 = Runtime . getRuntime ( ) . exec ( "cat /dev/ttyUSB0 9600 \n " ) ;
LineReader lineReader = new LineReader ( Stream. asStream ( Runexec2. getInputStream ( ) ) ) ;
String input ;
while ( true ) {
if ( ( input = lineReader. readLine ( ) ) != null ) {
Output. add ( input ) ;
Output. selectLast ( ) ;
Output. repaintNow ( ) ;
}
}
} catch ( IOException ioe ) {
ioe. printStackTrace ( ) ;
}
}
} . start ( ) ;
}
发送命令
发送命令是一个简单的过程。 每当您在“编辑”组件上按Enter时 ,它就会发生。
要将命令转发到设备,如3.1节所示,您必须实例化一个新终端。 为此,Runtime类必须在Linux上执行
sh命令:
try {
Runexec = Runtime . getRuntime ( ) . exec ( "sh" ) . getOutputStream ( ) } catch ( IOException ioe ) {
ioe. printStackTrace ( ) ;
}
用户在“编辑”中编写命令并按Enter后 ,应用程序将触发一个事件,该事件以“编辑”中指示的值执行
echo命令:
Input. addKeyListener ( new KeyListener ( ) {
@Override
public void specialkeyPressed ( KeyEvent e ) {
if ( e. key == SpecialKeys. ENTER ) {
String s = Input. getText ( ) ;
Input. clear ( ) ;
try {
Runexec. write ( ( "echo \" " + s + " \" > /dev/ttyUSB0 9600 \n " ) . getBytes ( ) ) ;
} catch ( IOException ioe ) {
ioe. printStackTrace ( ) ;
}
}
}
@Override
public void keyPressed ( KeyEvent e ) { } //auto-generate code
@Override
public void actionkeyPressed ( KeyEvent e ) { } //auto-generate code
} ) ;
在连接了Arduino的Raspberry Pi上运行应用程序,然后发送命令进行测试。 结果应为:
(Bruno Muniz, CC BY-SA 4.0 )
Runtime.exec源代码
以下是解释所有部分的源代码。 它包括将在第31行读取串行的线程和将在第55行发送命令的
KeyListener :
package com.totalcross.sample.serial ;
import totalcross.ui.MainWindow ;
import totalcross.ui.event.KeyEvent ;
import totalcross.ui.event.KeyListener ;
import totalcross.ui.gfx.Color ;
import totalcross.ui.Edit ;
import totalcross.ui.ListBox ;
import java.io.IOException ;
import java.io.OutputStream ;
import totalcross.io.LineReader ;
import totalcross.io.Stream ;
import totalcross.sys.Settings ;
import totalcross.sys.SpecialKeys ;
public class SerialSample extends MainWindow {
OutputStream Runexec ;
ListBox Output ;
public SerialSample ( ) {
setUIStyle ( Settings. MATERIAL_UI ) ;
}
@Override
public void initUI ( ) {
Edit Input = new Edit ( ) ;
add ( Input, LEFT, BOTTOM, FILL, PREFERRED ) ;
Output = new ListBox ( ) ;
Output. setBackForeColors ( Color . BLACK , Color . WHITE ) ;
add ( Output, LEFT, TOP, FILL, FIT ) ;
new Thread ( ) {
@Override
public void run ( ) {
try {
Process Runexec2 = Runtime . getRuntime ( ) . exec ( "cat /dev/ttyUSB0 9600 \n " ) ;
LineReader lineReader = new
LineReader ( Stream. asStream ( Runexec2. getInputStream ( ) ) ) ;
String input ;
while ( true ) {
if ( ( input = lineReader. readLine ( ) ) != null ) {
Output. add ( input ) ;
Output. selectLast ( ) ;
Output. repaintNow ( ) ;
}
}
} catch ( IOException ioe ) {
ioe. printStackTrace ( ) ;
}
}
} . start ( ) ;
try {
Runexec = Runtime . getRuntime ( ) . exec ( "sh" ) . getOutputStream ( ) ;
} catch ( IOException ioe ) {
ioe. printStackTrace ( ) ;
}
Input. addKeyListener ( new KeyListener ( ) {
@Override
public void specialkeyPressed ( KeyEvent e ) {
if ( e. key == SpecialKeys. ENTER ) {
String s = Input. getText ( ) ;
Input. clear ( ) ;
try {
Runexec. write ( ( "echo \" " + s + " \" > /dev/ttyUSB0 9600 \n " ) . getBytes ( ) ) ;
} catch ( IOException ioe ) {
ioe. printStackTrace ( ) ;
}
}
}
@Override
public void keyPressed ( KeyEvent e ) {
}
@Override
public void actionkeyPressed ( KeyEvent e ) {
}
} ) ;
}
}
5.2选项2:使用PortConnector
PortConnector专门用于串行通信。 如果要遵循原始示例,则可以跳过本节,因为此处的目的是显示另一种更简单的串行操作方法。
更改原始源代码以与PortConnector一起使用:
package com.totalcross.sample.serial ;
import totalcross.io.LineReader ;
import totalcross.io.device.PortConnector ;
import totalcross.sys.Settings ;
import totalcross.sys.SpecialKeys ;
import totalcross.ui.Edit ;
import totalcross.ui.ListBox ;
import totalcross.ui.MainWindow ;
import totalcross.ui.event.KeyEvent ;
import totalcross.ui.event.KeyListener ;
import totalcross.ui.gfx.Color ;
public class SerialSample extends MainWindow {
PortConnector pc ;
ListBox Output ;
public SerialSample ( ) {
setUIStyle ( Settings. MATERIAL_UI ) ;
}
@Override
public void initUI ( ) {
Edit Input = new Edit ( ) ;
add ( Input, LEFT, BOTTOM, FILL, PREFERRED ) ;
Output = new ListBox ( ) ;
Output. setBackForeColors ( Color . BLACK , Color . WHITE ) ;
add ( Output, LEFT, TOP, FILL, FIT ) ;
new Thread ( ) {
@Override
public void run ( ) {
try {
pc = new PortConnector ( PortConnector. USB , 9600 ) ;
LineReader lineReader = new LineReader ( pc ) ;
String input ;
while ( true ) {
if ( ( input = lineReader. readLine ( ) ) != null ) {
Output. add ( input ) ;
Output. selectLast ( ) ;
Output. repaintNow ( ) ;
}
}
} catch ( totalcross. io . IOException ioe ) {
ioe. printStackTrace ( ) ;
}
}
} . start ( ) ;
Input. addKeyListener ( new KeyListener ( ) {
@Override
public void specialkeyPressed ( KeyEvent e ) {
if ( e. key == SpecialKeys. ENTER ) {
String s = Input. getText ( ) ;
Input. clear ( ) ;
try {
pc. writeBytes ( s ) ;
} catch ( totalcross. io . IOException ioe ) {
ioe. printStackTrace ( ) ;
}
}
}
@Override
public void keyPressed ( KeyEvent e ) {
}
@Override
public void actionkeyPressed ( KeyEvent e ) {
}
} ) ;
}
}
您可以在项目存储库中找到所有代码。
6.后续步骤
本文介绍如何通过使用Runtime或PortConnector类将Raspberry Pi串行端口与Java一起使用。 您还可以用其他语言调用外部文件,并创建无数其他项目,例如用于水族箱的水质监测系统,该水族箱可以通过模拟输入进行温度测量,或者可以控制温度和湿度的鸡笼和伺服电机来旋转卵。
以后的文章将使用PortConnector实现(因为它专注于串行连接)来完成与所有传感器的通信。 它还将添加一个数字输入并完成UI。
以下是一些参考资料,供您阅读:
TotalCross入门
TotalCross PortConnector类
使用TotalCross运行C ++应用程序
VSCode TotalCross项目扩展插件
连接Arduino和Raspberry Pi后,请在下面留下您的评论。 我们希望阅读它们!
翻译自: https://opensource.com/article/20/7/arduino-raspberry-pi
通过Arduino端口扩展Raspberry Pi相关推荐
- Arduino vs Raspberry Pi vs BeagleBone
软硬件整合是今年一再被提及的话题,如今我们也可以看到不少硬件创业的成功案例,比如Jawbone Up.Pebble手表等可穿戴设备,它们可与用户的手机同步,实现软件与硬件的结合.通过硬件创新与软件整合 ...
- Raspberry Pi, UPNP(二), Scala
Raspberry Pi 概述 树莓派(Raspberry Pi)在极客领域可谓大名鼎鼎,它的官网是: https://www.raspberrypi.org/ 从型号来看,它可以分为三大类型: 1) ...
- raspberry pi_许多Raspberry Pi项目-您怎么不爱小型计算机?
raspberry pi How can you not love a tiny computer? I posted about Top 10 Raspberry Pi Myths and Trut ...
- 我应该买Arduino还是Raspberry Pi?
我花了很多时间参加诸如Maker Faires之类的会议和活动,并且与人合着了有关Raspberry Pi的书 ,我花了很多时间与人们谈论小型电子产品和开放硬件等问题. 我可能最常听到的问题是:&qu ...
- Raspberry Pi 与Arduino SPI通信
本教程介绍了使用SPI(串行外围设备接口总线)进行Raspberry Pi与Arduino通讯和控制的基本框架. SPI代表了一种非常完善的芯片间通信方法,该方法在两种设备的硬件中均实现. 在这里,我 ...
- raspberry pi_PocketCHIP与Raspberry Pi相比如何?
raspberry pi 当Raspberry Pi进入技术界时,它产生了巨大的影响. 无论如何,它都不是第一台小型计算机-Chumby,PogoPlug以及其他可在芯片上进行黑客攻击的系统都在出现- ...
- 龙邱树莓派Raspberry Pi 扩展板电路及其相关实验
▲ 树莓派与其扩展板 文章目录 ▌01 树莓派车模扩展板 1.车模的整体配置 2.扩展板 3.树莓派IO口管脚功能 (1)树莓派接口定义 (2)扩展板上各功能接口定义 ▌02 扩展板子模块 1.树莓派 ...
- 如何在Raspberry Pi上安装Fedora 25
2016年10月,宣布了Fedora 25 Beta的发布,以及对Raspberry Pi 2和3的最初支持 . 一个月后发布了Fedora 25的最终"通用"版本,从那时起,我一 ...
- raspberry pi_如何使用Raspberry Pi测量颗粒物
raspberry pi 我们在东南亚的学校定期测量空气中的颗粒物. 这里的值非常高,尤其是在2月到5月之间,那时天气非常干燥和炎热,许多田野都燃烧着. 这些因素会对空气质量产生负面影响. 在本文中, ...
最新文章
- Flex Socket 跨域问题的解决办法
- skynet给集群中的一个节点配置多个通道
- MyEclipse的Git配置
- DFS和BFS总结和代码演示(详解)
- 跳一跳python刷分_【Python跳一跳刷分辅助】iPhone版_Python跳一跳刷分辅助Ios最新版下载_Python跳一跳刷分辅助v1.0.1苹果版免费下载 - 九酷苹果网...
- FZU2218 Simple String Problem(状压DP)
- 为什么叫C++而不叫++C ?
- angular 解决闪烁问题_AngularJS页面访问时出现页面闪烁问题的解决
- linux zmq编译pgm,czmq交叉编译
- 我的保研之路-哈工大计算机,中科院信工所,复旦大数据学院
- 谈一谈企业部署erp系统的三大时间段
- 安全删除硬件并弹出媒体的列表中出现内置硬盘的解决办法.
- Unity ShaderLab Stencil Comp 枚举的对应数值
- Text to image论文精读 NAAF:基于负感知注意力的图像-文本匹配框架 Negative-Aware Attention Framework for Image-Text Matching
- jQuery实现AJAX定时刷新局部页面实例
- oracle 3135,oracle的imp问题。
- TensorFlow练习6: 基于WiFi指纹的室内定位(autoencoder)
- Mysql的下载、安装
- 面试官:策略模式和代理模式有什么区别?
- “离婚”华为后,荣耀第一胎满身伤痕
热门文章
- 解决android中java.lang.RuntimeException: Unable to start activity ComponentInfo问题
- GlboalMapper20 如何一次性把上百个经纬度投影的影像转为国家2000或者其他投影的影像
- TextView的android:maxHeight,android:minHeight的正确设置
- 关于微信小程序form表单无法触发提交的解决方案
- 如何解决偶然Maven项目中导入依赖,却一直报错,unresolved dependency
- 尺取法 --算法竞赛专题解析(2)
- 2022年大连理工大学计算机考研复试时间与复试范围
- html 原生滚动条详解,看这一篇就够了!
- 检查xml格式的linux自带方便好用的工具
- linux cacti安装教程,cacti安装教程