如何正确地通过蓝牙从 Android 向 Arduino 连续发送消息

Posted

技术标签:

【中文标题】如何正确地通过蓝牙从 Android 向 Arduino 连续发送消息【英文标题】:How to proper send messages via bluetooth from Android to Arduino continuously 【发布时间】:2021-11-12 11:57:22 【问题描述】:

我的目标是借助我的 android 手机通过 BT 控制一些 arduino 设备。 当我触摸屏幕并四处移动手指时,Android 应用程序会根据我的手指位置生成一些数据,形成字符串消息,然后尝试通过 BT 发送。

问题在于,当应用程序尝试发送此命令的许多次迭代时。

例如命令为:String command = "[code]command(data)/";

当我只是在屏幕上点击一个时间时,应用程序会编写一次命令并通过 BT 发送它,它在另一边 (arduino) 上看起来不错。 但是当我握住并移动手指时,应用程序试图每“帧”重写命令,并且还试图每“帧”发送这个命令(我的意思是,每时每刻,很多次)。然后我看到类似:“[code]co[cod[co[c[mma(da]coode[c[co".

感觉是......它得到一个字符数组并将其与另一个混合,发送时......或在停止发送之前开始发送另一条消息。

下面是获取触摸事件值的代码:

@Override
    public boolean onTouchEvent(MotionEvent event) 

        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) 
            case MotionEvent.ACTION_DOWN:
                initPosX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                // some code that make counts and convert values...

                // prepare string as a command.
                String command = "[code]command(" + value + ")/";
                Log.d("command", command);
                // send data via BT
                sendData(command);
                break;
            case MotionEvent.ACTION_UP:
                //code
                break;
            default:
                break;
        

我还有BT设置代码,一切正常。

这是主要部分。发送字符串的代码:

protected void sendData(String message) 
        byte[] msgBuffer = message.getBytes();

        try 
            outStream.write(msgBuffer);
         catch (IOException e) 
            //some exception code
        

    

outStream = btSocket.getOutputStream();

所以...我真的不知道为什么会这样。我浪费了一整天的时间来搜索有关的东西。 如果有人能给我胶水,下一步该在哪里挖,将不胜感激。 谢谢。

更新: Arduino端代码:

if (Serial.available() > 0) 
    char c = Serial.read(); // read char from BT
    serialMessage.concat(c); // add this char to string.
    delay(5);

    if (c == '/') 
      lcd.setCursor(0,0);
      lcd.print(serialMessage); // print message on a display.
      command = serialMessage;
      serialMessage = "";
    
  
  else 
    if (serialMessage != "") 
      lcd.setCursor(0,0);
      lcd.print(serialMessage); // print message on a display.
      serialMessage = "";
    
    //command = serialMessage;
    
  

更新 2: 这是一个真正的串行输入,当我点击一次时

[code]command(0.0)/

当我左右移动手指时

[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.23)/
[code]cm()dm()[c]a.[em1[(/
em1[em1[]a.cca.[e)[dm(/
dm(/
em1[em1[co0ood)dmd4ood8oon2ccn0cca0/
ccn.[]a-)dm(6oon.[]a1[]od0o0[c]a1[]a1[em-/
em-)dm()dm(0odcn.cca0a.[]a.[em0/
em0)dm()dm()dm(/
em1/
em1[]a1[]a.ccn0oon7ccn4c]a.ccn.[em-)dm()oodod0ccn.ccn.[]m-/
d0ooood0ccn.ccn.[]a1[]a-/
em-/
em(5ood7c]a0/
em-)ood0[em0)dm()dm(3od)dm(/
dm(/
em1[em1[]a.c]a)dodm()ood2ccn./
ed9[]a1[]a-/
em-/
em()dm()dmd0od0ooood0oon.codecn1[]a0/
[dm(5ccn.cd0ccn1ccn.[]d4ooood7ocn3

更新 3: 毫不拖延地点击:

[
code]c
ommand(0.0)/
[code]command(0.0)/
[
code]c
ommand(0.0)/
[code]command(0.0)/
[
code]c
ommand(0.0)/
[code]command(0.0)/

更新 4:

[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.01)/
[code]command(0.07)/
[code]command(0.15)/
[code]command(0.23)/
[code]command(0.29)/
[code]command(0.33)/
[code]command(0.37)/
[code]command(0.41)/
[co(0.44)/
[code]commandmmand(0.51)/
[code]code]command(0.6)/
[cod0.63)/
[cod0.65)/
[code]command(0.66)67)/
[code]command(0.68)/
2)/

【问题讨论】:

“然后我看到类似的东西:” - 这是在接收端看到的吗?如果是这样,则包括 Arduino 接收端代码。 onTouchEvent 在 UI 线程上,而 BT 输出流是阻塞写入,让我相信它不在发送端 - 所以我会对接收端感兴趣。 (请注意,由于输出流写入阻塞,您最终可能会在 Android UI 端遇到问题 - 但我假设现在这不是问题。) 嘿。我不认为接收端的问题。接收方只接收我发送给它的任何字符/字节,并制作一条消息/字符串。当输入为空或符号为“/”时,它会在显示器上打印一条消息并清除此字符串。无论如何,我将代码放在原始消息下。你可以看看。谢谢。 Buuut...也许你是对的。也许是接收方。由于某种原因,我把这个延迟(5)。 现在我觉得我需要……匹配一个传输和接收的速度……也许吧。但不知道具体是什么。 else 部分中的逻辑(我将其解释为“没有可用的,所以打印我目前所拥有的”)是错误的。它会打印您到目前为止所拥有的内容,但随后会清除该消息。更多的字符进来(还不是'/'),然后打印它(从 (0,0) 开始)并显示它 - 这只是最后收到的字符。我建议在“else”部分中注释掉serialMessage = "";,以保留累积的信息。 (可能不是唯一的问题,但请尝试一下)。 【参考方案1】:

是的。它溢出了串行。 我分两步解决这个问题。 首先,我将 arduino 端的字符读取延迟从 5 减少到 1。 其次,我每秒只发送 10 次消息/命令。 有一个代码可以做到这一点:

public void send(String string) 
            if ((System.currentTimeMillis() - lastTimeSend) > 100) 
                byte[] bytes = string.getBytes();
                try 
                    mmOutStream.write(bytes);
                 catch (IOException e)  

                lastTimeSend = System.currentTimeMillis();
            
        

【讨论】:

以上是关于如何正确地通过蓝牙从 Android 向 Arduino 连续发送消息的主要内容,如果未能解决你的问题,请参考以下文章

如何在后台的两个 android 活动之间交换数据以通过蓝牙发送数据?

如何使用android蓝牙接收串行数据

向远程蓝牙设备发送数据

Android + ESP32 通过蓝牙 (BLE) 发送数据

如何让蓝牙 RFCOMM 始终如一地工作?

Android:如何通过蓝牙连接传输视频和音频?