0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

怎样通过蓝牙将ArduinoUno连接到Android

454398 来源:wv 2019-10-05 17:30 次阅读

第1步:电路

怎样通过蓝牙将ArduinoUno连接到Android

组件:

1 x Arduino Uno

3 x 220欧姆电阻器

1 x绿色LED

1 x黄色LED

1 x红色LED

1 x TMP36温度传感器

1 x JY-MCU蓝牙从模块(请参阅介绍)

1 x面包板

电线

连接:

步骤1):将Arduino的地线和5V连接到面包板。

步骤2):将LED放在面包板上,并将其阴极接地。将它们的阳极分别通过220欧姆电阻连接到数字引脚:黄色到引脚3,绿色到引脚4,红色到引脚5。

步骤3):将TMP36传感器放在面包板上,将其引脚连接到5V,接地和A0 Arduino引脚。

步骤4):将提供的电缆的一侧连接到JY-MCU蓝牙模块,另一侧连接到面包板;连接如下:

VCC 《-》 5V

GND 《-》 GND TXD 《-》引脚0(Rx)

RXD 《-》引脚1(Tx)

该草图还将使用数字引脚13上的Arduino内置LED。

由于TXD转到Rx,而RXD转到,蓝牙模块的连接可能会有些混乱。 Tx:这是一个解释。发送和接收是针对每个设备的,因此,蓝牙模块的TXD引脚发出的传输必须由Arduino在Rx引脚0上接收;同样,从Arduino Tx引脚1发出的传输也必须到达其RXD引脚上的JY-MCU蓝牙模块。

警告:蓝牙模块可能会干扰PC与Arduino的通信:对电路板进行编程时,请断开VCC。 (在我的测试中,情况并非如此,但请确保它不会造成任何伤害)。

步骤2:Arduino代码-简介

Arduino监听命令以点亮某些LED或显示其状态。另外,定时器中断使它可以通过TMP36传感器检查温度:如果温度大于阈值,则LED点亮;否则,指示灯熄灭。每n秒(其中n是通过应用设置的参数)会向该应用发送状态报告。简单的命令结构使应用程序可以将参数和值发送到Arduino,反之亦然。

程序中定义的命令结构为:

CMD RED | GREEN | YELLOW =开|关

CMD TMAX | SECONDS =值

CMD SECONDS =值

CMD状态

状态消息结构为:

状态红色|绿色|黄色| TMAX | SECONDS | TEMP | THIGH = value

Arduino将以完整状态回答STATUS命令,而在中断时它将报告较短的版本。

示例:

CMD RED = ON将红色LED点亮

CMD GREEN = OFF将绿色LED熄灭

您可以通过在Arduino IDE的串行监视器中发出命令并查看响应来测试草图:确保在底部的下拉选项中选择“回车”。

您可以从附件中下载草图代码。下一步将对此进行详细说明。

步骤3:Arduino代码-详细信息

上一步中所述的命令和消息结构

//串行参数:COM11 9600 8 N 1

// r或 n结束命令行

//蓝牙处于针脚0和1,速度为9600

//命令结构//CMD RED | GREEN | YELLOW = ON | OFF

//CMD TMAX | SECONDS = value

//CMD SECONDS = value

//CMD STATUS

//状态消息结构

//STATUS RED | GREEN | YELLOW | TMIN | TMAX | SECONDS | TEMP | THIGH = value

温度控制所需变量的初始化

float maxTemp = 30.0;//当温度》 maxTemp

int maxTempSensor =(int)((maxTemp/100 + .5)* 204.8);

浮点温度= 0.0;

以后可以更改maxTemp,但是程序需要使用默认值开始。 maxTempSensor是将maxTemp转换为Arduino ADC转换器提供的0-1023范围;温度比较将通过我们希望尽快执行的中断例程执行:直接比较整数Pin输出值而不是浮点温度更为有效。我们仍然要报告温度,程序会将其以相同的名称存储在变量中。

如果您不熟悉温度转换公式,可以在这里查看。

maxSeconds也可以使用命令进行更改,但再次需要默认值

int maxSeconds = 10;//每maxSeconds

Pin常量声明发送状态消息

const int ledPin = 13;//温度指示灯

const int tempPin = A0;//T36温度传感器模拟输入引脚

const int led1Pin = 3;//黄色

const int led2Pin = 4;//Green

const int led3Pin = 5;//红色

中断例程中使用并从其外部访问的变量

volatile int tempVal;

volatile int seconds = 0;

volatile boolean tempHigh = false;

volatile boolean statusReport = false;

Volatile是一个特殊的关键字,可防止编译器执行某些优化:在中断内修改的所有变量例程,并且必须在例程之外进行访问,必须将其声明为volatile,以表明其值可以随时更改,并确保在需要时从内存中读取最新的正确值。

命令字符串变量(稍后将对此进行说明)

字符串inputString =“”;

String command =“”;

字符串值=“”;

布尔stringComplete = false;

setup()函数

void setup(){

//开始串行连接

Serial.begin(9600);

Serial.print(“ Max T:”);

Serial.print(maxTemp);

Serial.print(“ Sensor:”);

Serial.println(maxTempSensor);

inputString.reserve(50);

command.reserve(50) ;

value.reserve(50);

pinMode(ledPin,OUTPUT);

digitalWrite(ledPin,LOW);

pinMode(led1Pin,OUTPUT);

pinMode(led2Pin,OUTPUT) ;

pinMode(led3Pin,OUTPUT);

digitalWrite(led1Pin,LOW);

digitalWrite(led2Pin,LOW);

digitalWrite(led3Pin,LOW);

字符串的reserve方法分配作为参数提供的字节数。

需要以下代码来初始化计时器中断并将其设置为每秒触发一次,这是Arduino可以完成的最慢的时间。有关详细信息,请参见此处。

cli();//禁用全局中断

//初始化Timer1以中断@ 1000毫秒

TCCR1A = 0;//将整个TCCR1A寄存器设置为0

TCCR1B = 0;//与TCCR1B

相同//将比较匹配寄存器设置为所需的计时器计数:

OCR1A = 15624;//打开CTC模式:

TCCR1B | =(1 《//为1024个预分频器设置CS10和CS12位:

TCCR1B | =(1 《 TCCR1B | =(1 《//启用计时器比较中断:

TIMSK1 | =(1 《 sei();//启用全局中断

}

定时器中断例程:我们无法更改其名称,但内容是完全可定制的。/p》

ISR(TIMER1_COMPA_vect)

{

tempVal = AnalogRead(tempPin);

if(tempVal》 maxTempSensor){

digitalWrite(ledPin,HIGH);

tempHigh = true;

}

else {

digitalWrite(ledPin,LOW);

tempHigh = false;

}

温度值-或如上文所述,从传感器读取其0-1023整数表示形式,并将其与阈值进行比较:当上面的内置LED点亮并且tempHigh设置为true时,否则关闭LED并 tempHigh设置为false。

如果(秒++》 = maxSeconds){

statusReport = true;

秒= 0;

}

}

请记住,每秒触发一次中断,但是我们希望报告系统状态的频率降低:秒变量在每次迭代时递增,直到达到s报告到期时的值;稍后将在主循环中通过检查statusReport标志来完成此操作。通常,永远不要执行太慢的操作,例如从中断例程中将数据写入串行。

loop()函数在接收到指令后便会解释并执行命令,然后如果计时器发出标志,则会报告状态打断。为了从串行缓冲区读取字符串,loop()依赖于将在最后定义的serialEvent()函数:该例程在每次loop()运行之间运行。它没有得到广泛的记录,并且可能不适用于所有的Arduino模型。无论如何,将其内容嵌套在主循环中并不难(请参见本步骤的结尾)。

void loop(){

int intValue = 0;

if(stringComplete){ boolean stringOK = false;

if(inputString.startsWith(“ CMD”)){

inputString = inputString.substring(4);

首先,我们检查接收到的字符串是否以“ CMD”开头:如果是这样,我们可以丢弃前四个字符,否则稍后会出现错误。

int pos = inputString.indexOf(‘=’);

if(pos》 -1){

command = inputString.substring(0,pos);

value = inputString。 substring(pos + 1,inputString.length()-1);//提取最多 n个被排除的命令

有两种类型的命令:设置值的命令,在其中找到分隔空格的“ =”值对,以及该命令是单个指令(STATUS)。如果pos处出现“ =”,则字符串将分为命令(左部分)和值(右部分),并将“ =”插入中间,并在行尾添加末尾字符。

如果(command.equals(“ RED”)){//RED = ON | OFF

value.equals(“ ON”)? digitalWrite(led3Pin,HIGH):digitalWrite(led3Pin,LOW);

stringOK = true;

}

否则if(command.equals(“ GREEN”)){//GREEN = ON | OFF

value.equals(“ ON”)吗? digitalWrite(led2Pin,HIGH):digitalWrite(led2Pin,LOW);

stringOK = true;

}

否则if(command.equals(“ YELLOW”)){//YELLOW = ON | OFF

value.equals(“ ON”)吗? digitalWrite(led1Pin,HIGH):digitalWrite(led1Pin,LOW);

stringOK = true;

}

我们检查并执行LED命令;请注意,代码仅检查值ON:如果您写入GREEN = ASD,它将被解释为GREEN = OFF。它不是完美的,但是它使事情变得简单得多。每次识别并执行命令时都会设置stringOK = true,以便以后标记错误的命令。

否则,如果(command.equals(“ TMAX”)){//TMAX =值

intValue = value.toInt();

如果(intValue》 0){

maxTemp = (float)intValue;

maxTempSensor =(int)((maxTemp/100 + .5)* 204.8);

stringOK = true;

}

}

否则,如果(command.equals(“ SECONDS”)){//SECONDS = value

intValue = value.toInt();

如果(intValue》 0){

maxSeconds = intValue;

stringOK = true;

}

}

当值应为数字时,我们需要将其转换并测试它确实是一个数字。对于MaxTemp,我们还按照变量定义部分中的说明计算传感器值

}//pos》 -1

else if(inputString.startsWith(“ STATUS”)){

Serial.print(“ STATUS RED =”);

Serial.println(digitalRead(led3Pin ));

Serial.print(“ STATUS GREEN =”);

Serial.println(digitalRead(led2Pin));

Serial.print(“ STATUS YELLOW =”);

Serial.println(digitalRead(led1Pin));

Serial.print(“ STATUS TMAX =“);

Serial.println(maxTemp);

Serial.print(” STATUS SECONDS =“);

Serial.println(maxSeconds);

Serial.print(“ STATUS TEMP =”);

Serial.println(temperature);

Serial.print(“ STATUS THIGH =”);

Serial.println(tempHigh);

stringOK = true ;

}//inputString.starts With(“ STATUS”)

如果命令是STATUS,则程序仅将所有信息输出到串行。

}//inputString.startsWith (“ CMD”)

stringOK吗? Serial.println(“ Command Executed”):Serial.println(“ Invalid Command”);

指示是否已收到有效或无效命令。

//清除字符串以进行下一次迭代

inputString =“”;

stringComplete = false;

}//stringComplete

下一次命令迭代的变量内务处理。

if(statusReport){

temperature =(tempVal * 0.0048828125-.5)* 100;

Serial.print(“ STATUS TEMP =”);

Serial.println(temperature);

Serial.print(“ STATUS THIGH =”);

Serial.println(tempHigh);

statusReport = false;

}

}

如果中断例程已引发statusReport标志,则将打印一些信息请注意,此时要计算当前温度值:因此,如果在statusReport时间间隔之间发出STATUS命令,则会得到旧的温度值。

如前所述,只要新数据进入硬件串行RX,就会发生serialEvent()。该例程在每次loop()运行之间运行,因此在循环内部使用delay可以延迟响应。可能有多个字节的数据。

无效的serialEvent(){

而(Serial.available()){

//获得新的字节:

char inChar =(char)Serial.read();

//将其添加到inputString:

inputString + = inChar;

//如果传入字符是换行符或回车符,则设置标志

//,因此主循环可以对此做一些事情:

if(inChar ==‘ n’|| inChar ==‘ r’){

stringComplete = true;

}

}

}

从串行读取每个字节并将其添加到输入字符串,直到遇到“ n”或“ r”表示字符串结尾:在这种情况下,设置由loop()检查的stringComplete标志。同时使用回车符 r和换行符 n确保代码能够从各种输入(包括Arduino IDE串行监视器以外的其他串行终端)检测字符串结尾。

关于蓝牙和串行的注意事项

在许多示例中,包括JY-MCU卖方的示例,您可以找到连接在不同Arduino数字引脚(例如10和11)上的蓝牙模块,以及通过SoftwareSerial库访问。根据我的测试结果,当该模块仅用于发送信息时,SoftwareSerial可以完美运行,但是在接收命令时Arduino Uno不够快。我没有尝试降低SoftwareSerial连接的速度(在示例中通常设置为2400bps),因为MIT AppInventor应用似乎不支持蓝牙连接速度设置。

使用SoftwareSerial,serialEvent()不会工作:需要重命名它(例如mySerialEvent())并在loop()的开头显式调用它。

步骤4:App Inventor代码-简介

在使用Android应用之前,您需要将Bluetooth模块与智能手机配对。

给Arduino开发板通电,打开在Android手机上的蓝牙上并搜索附近的蓝牙设备:JY-MCU模块将显示为HC-06,配对密码为1234。

蓝牙Arduino连接的关键组件应用程序是蓝牙客户端,而Arduino板将充当服务器:这意味着应用程序将始终启动连接。给Arduino开发板供电时,蓝牙模块红色LED开始闪烁;按下应用程序的“连接到设备”按钮,然后从列表中选择模块:红色LED指示灯将变为稳定,连接状态将变为“已连接”。

同样,这与蓝牙无关Master/Slave,但仍可能令人困惑:您的Bluetooth模块需要为Slave,但它(或Arduino草图)在客户端中将充当Server-与Android应用程序进行服务器通信。

您可以直接从Android Play商店安装Bluetooth Arduino Connection App,或者您可以通过下载附件将完整的应用程序代码导入到MIT App Inventor项目中。

蓝牙Arduino连接应用程序是使用MIT App Inventor 2开发的;以下步骤将提供详细说明。

步骤5:App Inventor代码-详细信息

Arduino蓝牙连接应用程序的关键组件是:

用于蓝牙配对设备的ListPicker(ListPicker1)

3个按钮,每个按钮控制相应的配色板LED(RedLedBtn,GreenLedBtn,YellowLedBtn)

发送状态命令(GetStatusBtn)的按钮

带有关联按钮的按钮文本框以设置状态报告间隔(SecondsBtn和SecondsTxBx)

巨大的多行状态标签,显示从Arduino板(状态)接收的信息

上一步(BluetoothClient1)

一个时钟组件,该时钟组件在客户端连接时每秒触发一次中断(Clock1)

以下是基于以下内容的应用代码说明:上面的图片。

图1

Variabl当打开应用程序屏幕时,将设置并初始化LED的状态和间隔。

图2

连接ListPicker对象ListPicker1使用两种方法:

已准备好可用(配对)的蓝牙设备的列表,并显示给用户

当用户选择设备时,将调用Bluetooth Client对象的Connect方法为了开始连接:如果成功,它将显示在适当的标签中,并激活Clock中断,以便可以接收来自设备的消息。

图3

在这里,我们演示如何向Arduino板发送命令。

按下GetStatusBtn时,将调用Bluetooth Client对象的SendText方法并执行文本命令发出:注意,在“ CMD STATUS”字符串的末尾添加了“ n”,以便Arduino草图中的serialEvent()函数能够知道消息何时结束。

代码打开或关闭LED稍微复杂一点:

我们使用相应的变量来跟踪其当前状态:如果打开,我们想将其关闭,反之亦然;因此,首先,我们将变量更改为布尔值

,然后使用新状态更新按钮标签

最后,调用BluetoothClient1.SendText来传输命令。

其他命令的代码非常相似,因此未显示。

图4

每次Clock1计时器触发,该例程被执行:它等效于Arduino的serialEvent();。如果BluetoothClient1接收到字节,则将它们复制到状态标签中。请注意,Bluetooth客户端对象具有一种返回所接收消息长度的方法。

步骤6:结论

在此指导中,我演示了一个通过蓝牙连接Arduino开发板和Android智能手机的有用方法。通信是双向的,因此开发板不仅向应用程序报告其状态,而且还从应用程序接收命令。

此外,一个简单的扩展程序允许将Arduino的命令发送给应用程序。电话:例如:按下板上的按钮即可拍照或发送短信。

Arduino草图可以作为远程命令处理的基础,它使用中断来执行一些操作-检查温度并打开LED警报-并发送状态心跳信号:该技术不仅可以通过蓝牙通信应用,还可以通过以太网等其他方式应用。

MIT App Inventor应用程序使用中断同样:它等效于Arduino的loop()+ serialEvent()函数的重复,并且类似地用于接收消息。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Android
    +关注

    关注

    12

    文章

    3851

    浏览量

    125637
  • 蓝牙
    +关注

    关注

    112

    文章

    5428

    浏览量

    165648
  • Arduino
    +关注

    关注

    184

    文章

    6427

    浏览量

    184832
收藏 人收藏

    评论

    相关推荐

    如何在安卓系统上通过蓝牙控制Cypress CYW20730?

    嗨,我想开发一个 CAN 连接到赛普拉斯CYW20730芯片的Android应用程序。 实际上,一些主动快门 3D 眼镜使用了这个芯片,我想建立蓝牙连接来打开和关闭眼镜镜片。 我下载了
    发表于 03-01 11:58

    如何通过RGMII接口TC397连接到Marvell 88Q5152?

    我们的计划是通过 RGMII 接口 TC397 连接到 Marvell 88Q5152,以满足我们的应用要求。 过去,在Linux系统上,我们设置了一个固定链接来直接指定速度和双工模式。 我们想
    发表于 01-26 06:05

    当一个电源的正接到另一个电源的负会怎样?为什么?

    当一个电源的正接到另一个电源的负会怎样?为什么? 当一个电源的正极连接到另一个电源的负极时,会发生短路现象。这是因为在电路中,电源的正极提供电子,而负极接收电子,并将其送回电源。 当两个电源直接
    的头像 发表于 01-16 11:06 689次阅读

    怎样把navicat连接到eclipse

    将Navicat连接到Eclipse是一个简单的过程,只需要按照以下步骤完成即可。 第一步:下载和安装Navicat 首先,你需要从Navicat官方网站(http://www.navicat.cn
    的头像 发表于 12-06 11:08 784次阅读

    从Web浏览器连接到蓝牙设备

    电子发烧友网站提供《从Web浏览器连接到蓝牙设备.zip》资料免费下载
    发表于 06-28 11:26 0次下载
    从Web浏览器<b class='flag-5'>连接到</b><b class='flag-5'>蓝牙</b>设备

    通过蓝牙将消息发送到连接到STM32板的LCD显示器

    电子发烧友网站提供《通过蓝牙将消息发送到连接到STM32板的LCD显示器.zip》资料免费下载
    发表于 06-14 10:52 0次下载
    <b class='flag-5'>通过</b><b class='flag-5'>蓝牙</b>将消息发送到<b class='flag-5'>连接到</b>STM32板的LCD显示器

    SDK更新到1.4.0后无法连接到ESP SoftAP怎么解决?

    SDK 从 1.2.0 更新到 1.4.0 后,一切看起来都运行良好,但对于某些设备,例如 Android 5.0、Android 4.4,我无法连接到 AP。例如,从 iPhon
    发表于 06-12 08:31

    Android自动连接但未检测到互联网是怎么回事?

    我花了很多时间寻找答案,但我似乎找不到解决此问题的方法。 基本上,我正在尝试让我的 Android 智能手机 (v8.1) 自动将其 wifi 连接到设置为 AP 的 ESP8266。问题是,即使
    发表于 06-07 08:17

    求助,(Wemos) 蓝牙可以连接到任何蓝牙设备吗?

    我有一个太阳能逆变器,我的手机可以通过蓝牙连接。但是逆变器没有wifi功能。 我想知道,是否可以使用 Wemos D1 mini pro 作为我的网络和太阳能逆变器之间的“桥梁”?我只想读取一些值
    发表于 06-07 07:02

    如何避免esp8266连接到wifi?

    所以我喜欢在家里玩一些轻便的东西,因为我想避免将我的 esp8266 连接到我家的 wifi,所以我想使用一些射频。遗憾的是,您无法从智能手机发出所有射频,所以我想知道我是否可以执行以下操作: 将我
    发表于 06-06 11:52

    无法通过USB OpenSDA连接到S32K148怎么解决?

    我无法 S32K148 连接到闪存或调试它。连接 evb 后,设备会显示在设备管理器和资源管理器中。但是当我尝试使用 S32DS for Arm v2.2 连接到开发板时,程序无法
    发表于 06-06 07:59

    如何NodeMCU连接到XBOX 360控制器?

    我想将 GPIO 从 NodeMCU ESP8266 板连接到 XBOX 360 控制器上的按钮垫。 我已经尝试跳线从 D0 引脚连接到 360 控制器上的“X”按钮板。 我试过
    发表于 05-24 06:44

    如何ESP连接到微控制器?

    你好! 我有一个问题:这是 ESP 的最小电路。 我想用微控制器驱动它。我的问题是: 1) RST 和 EN 引脚通过电阻连接到 Vcc。如果我想将它连接到 STM32(连接到 STM
    发表于 05-15 08:30

    使用android手机时,wifi连接到模块但是浏览器说页面不可用的原因?

    我有一个在 ESP 上运行的脚本,模块没有连接到路由器并且处于 AP 模式,通过 PC WIfi 我可以连接到 192.168.4.1 当我尝试使用 android 手机时,wifi
    发表于 05-10 08:36

    如何ESP8266连接到Google表格?

    我正在尝试通过 ESP8266 模块数据从 arduino 连接到 google 表格。我没有使用节点 mcu,这是大多数教程的基础。我有一个连接到 arduino mega
    发表于 05-08 08:13