【问题标题】:Sending data from arduino through bluetooth serial通过蓝牙串口从 arduino 发送数据
【发布时间】:2014-02-06 21:32:13
【问题描述】:

我目前正在尝试设计一种通过蓝牙与安卓手机 (Galaxy Nexus) 进行通信的控制器。我面临着一些挑战。另外,我没有太多实际的编程经验。

控制器的核心是一个 Arduino 微控制器,它扫描 8 个数字引脚和 6 个模拟引脚(10 位)的状态,并通过串行将数据发送到 HC-05 蓝牙芯片。 然后,安卓手机应该读取通过蓝牙发送的串行信息,然后将数据包传输到另一部手机——这需要我一段时间来实现,因为我对互联网的工作原理知之甚少——或者分析和解释它以采取进一步的行动拍摄

我所要求的是关于执行此操作的最佳方法的见解。现在最好是什么意思? 我们希望它是实时的,所以当我按下按钮或底部组合时,Android 手机会以足够快的速度采取行动,人类不会察觉到延迟。

然后我希望能够将手机在串行缓冲区中读取的信息与相应的按钮或模拟引脚相关联。万一出现错误或避免它们不同步

这是我目前所拥有的。我还没有测试过这段代码,部分原因是我还在学习如何编写这个项目的android部分,部分原因是我想要一些关于我是否愚蠢的反馈,或者这实际上是一种有效的方式去做这个:

//Initialization
/*

This Program has three functions:
1) Scan 8 digital pins and compile their state in a single byte ( 8 bits)
2) Scans 6 Analogue inputs corresponding to the joysticks and triggers 
3) Send this info as packets through seril --> Bluetooth 

*/
#include <SoftwareSerial.h>// import the serial software library

#define A = 2
#define B = 3
#define X = 4
#define Y = 5
#define LB = 6
#define RB = 7
#define LJ = 8
#define RJ = 9
#define RX = 10
#define TX = 11
//Pin 12 and 13 are unused for now
SoftwareSerial Bluetooth(RX,TX); //Setup software serial using the defined constants
// declare other variables
byte state = B00000000

void setup() {
  //Setup code here, to run once:
  //Setup all digital pin inputs
  pinMode(A,INPUT);
  pinMode(B,INPUT);
  pinMode(X,INPUT);
  pinMode(Y,INPUT);
  pinMode(LB,INPUT);
  pinMode(RB,INPUT);
  pinMode(LJ,INPUT);
  pinMode(RJ,INPUT);
  //Setup all analogue pin inputs
  //setup serial bus and send validation message
  Bluetooth.begin(9600);
  Bluetooth.println("The controller has successfuly connected to the phone")
}

void loop() {
  //Main code here, to run repeatedly: 
  //Loop to sum digital inputs in a byte, left shift the byte every time by 1 and add that if the pin is high
  for(byte pin = 2, b = B00000001;  pin < 10; pin++, b = b << 1){ if (digitalRead(pin)== HIGH) state += b; }
  //Send digital state byte to serial
  Bluetooth.write(state);
  //Loop to read analgue pin 0 to 5 and send it to serial
  for( int pin = 0, testByte = 0x8000; pin < 6 ; pin++, testByte = testByte >> 1) { Bluetooth.write(analogRead(pin)+testByte); }
}

//Adding some validation would be wise. How would I go about doing that?
// Could add a binary value of 1000_0000_0000_0000,  0100_0000_0000_0000,  0010_0000_0000_0000 ... so on and then use a simple AND statement at the other end to veryfy what analogue reading the info came from
// so say the value for analgue is 1023 and came from analgue pin 1 I would have 0100_0011_1111_1111 now using an bitwise && I could check it against 0100_0000_0000_0000 if the result is 0100_0000_0000_0000 then I know this is the analogu reading from pin 1
//could easily implement a test loop with a shiting bit on the android side

我做这样的位移是没有意义的吗?最后,如果我没记错的话,所有数据都是以字节(8 位数据包)发送的,那么Bluetooth.write(analogRead(pin)+testByte) 会实际发送两个字节还是会截断int 数据?它将如何分解,我如何在 android 端恢复它?

您将如何实施?有什么见解或建议?

【问题讨论】:

    标签: android bluetooth arduino microcontroller arduino-ide


    【解决方案1】:

    很高兴你正在学习这个!一些建议:

    如果您将代码留出一点空间,特别是通过添加换行符,您的代码将更易于阅读、理解和维护...

    void loop() {
      //Main code here, to run repeatedly: 
      //Loop to sum digital inputs in a byte, 
      //left shift the byte every time by 1 and add that  if the pin is high
      for( byte pin = 2, b = B00000001;  pin < 10; pin++, b = b << 1) {
        if (digitalRead(pin)== HIGH)
          state += b;
      }
      //Send digital state byte to serial
      Bluetooth.write(state);
      //Loop to read analgue pin 0 to 5 and send it to serial
      for( int pin = 0, testByte = 0x8000; pin < 6 ; pin++, testByte = testByte >> 1) {
        Bluetooth.write(analogRead(pin)+testByte); 
      }
    }
    

    此外,您可以将移位运算符用于除一以外的值。因此,您无需保留然后添加的移位掩码,只需使用一个简单的变量。一个更经典的方式来做你在第一个循环中表达的内容是这样的:

    #define PIN_OFFSET 2
      for ( int i=0; i < 8; i++) {
        if (digitalRead( i+PIN_OFFSET)== HIGH)
          state += (1 << i);
      }
    

    第二个循环可以类似地完成:

      for( int pin = 0; pin < 6; pin++) {
        short testByte = 0x8000 >> pin;
        short result =  analogRead(pin) + testByte;
        Bluetooth.write( result >> 8); 
        Bluetooth.write( result & 0xFF); 
      }
    

    请注意,Bluetooth.write() 调用发送一个字节,因此此代码首先发送最高有效字节,然后是最低字节。

    最后,您可能希望在 loop() 开始时将状态变量归零——否则,一旦设置了某个位,它将永远不会被清除。

    您可能需要考虑发送到手机的内容。它将是二进制数据,这可能很难处理——你怎么知道开始和结束,而且通常一个值会被误解为一个控制字符,让你大吃一惊。考虑将其更改为格式化的、人类可读的字符串,并在末尾添加一个换行符。

    希望对你有帮助。

    【讨论】:

    • 感谢@bobwki 的提示和鼓励!我一定会记住这一点。好的,所以你建议我发送更多“格式化的人类可读字符串”。其计算仍然足够快以达到实时性吗?这真的是我唯一的问题,也是我试图真正有效地处理我发送和处理的数据量的原因。
    • 不确定效率问题——另一种方法是对结果进行编码,使其至少是可打印的字符,以避免控制代码问题。另外,请注意,您不能假设蓝牙能够以尽可能快的速度接收字符。它将缓冲字符并尽可能发送它们。根据界面的工作方式(我没有看过),它可能会丢弃它无法发送的字符,或者它会执行某种“流控制”——这两者都可能不适合你想要的做。
    【解决方案2】:

    这方面的 Arduino 速度足以完成您想做的事情,而且当您谈论此类时,您无需担心最小化从微型设备发送到手机的字节数少量的数据。我不太清楚你要向手机发送什么;您是否希望每个按钮都有不同的值,所以当按下按钮时,它会发出如下信息:

    按钮被按下,按钮编号(两个字节)

    如果是模拟值:

    Analogue Value Read, Analogue Value MSB, Analogue Value LSB(假设模拟值大于八位

    我不知道您正在使用的 Arduino 代码,但我怀疑这一行:

    Bluetooth.write(analogRead(pin)+testByte)

    将发送一个字节,该字节是模拟值与 testByte 的相加。

    您能否发布指向此 API 文档的链接?

    所有这一切的任何延迟都会在电话结束时出现。请不要担心尝试在 Arduino 端保存一两个字节! (我目前正在做一个项目,使用 Cortex M3 通过蓝牙模块向 Android 手机发送数据,我们正在发送数 k 数据。从这次经验中我知道,两个字节和 20 个字节之间的差异并不重要延迟。)

    【讨论】:

    • 好的,谢谢,很高兴知道我不必担心速度!然后,如果我之前发送了“按下按钮”,我就不需要测试字节了。 API 可以在 arduino 网站上找到。 arduino.cc/en/Reference/HomePage#.UxLULfldVjQ
    【解决方案3】:

    为您的安卓手机选择现成可用的蓝牙终端应用程序可能对您有好处。在 Google play 上,很少有应用程序是: 1)https://play.google.com/store/apps/details?id=arduino.bluetooth.terminal&hl=en 2)https://play.google.com/store/apps/details?id=com.sena.bterm&hl=en (Google play 上还有更多可用)。这将帮助您只专注于控制器端开发。

    【讨论】:

    • 感谢您的建议。我已经下载了一个终端来测试我的蓝牙模块是否工作。也就是说,终端应用程序毫无意义,因为它们所做的只是显示通过终端发送的数据。如果我想处理这些数据,我需要修改他们的代码或从头开始编写一个应用程序。在这两种情况下,我都需要学习 android 部分的东西。我完全同意!这个项目的全部目的是给我一个很好的借口,让我努力学习一些东西。 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多