首页 > 解决方案 > 由 Arduino 信号驱动的线程中运行的计数器会跳过前几个数字

问题描述

我已经在 Arduino(HC-05 蓝牙模块)和我的 Android 应用程序之间建立了蓝牙连接。

每次 Arduino 发送信号(信号只是数字 72)时,我的 Android 应用程序都会读取此信号(作为 an 中的字节InputStream)并将“计数器”变量设置为counter = counter - 1

我创建了一个执行此操作的线程。

问题是

例如,如果我将计数器设置为 30 并启动线程,则 30 的前 3-4 次减法以毫秒为单位发生(它们不与 Arduino 信号同步)。但是从 26 开始,一切都完美同步并按预期工作。

我尝试了不同的Thread.sleep()时间。更长的睡眠时间会使问题变得更糟(更多的减法在毫秒内发生)。睡眠时间越短越好,但仍然不能解决我的问题。

为什么前 3-6 个减法的线程不同步,而其他所有减法的线程都同步?

一些(也许)有用的信息:

有 4 个按钮。“连接”、“断开”、“开始”和“停止”。

  1. “连接”:通过 BluetoothSocket 与 HC-05 建立连接。
  2. “断开连接”:关闭此连接。
  3. “开始”:启动InputStream从 HC-05 监听数据的线程。
  4. “停止”:停止该线程。

我的代码(线程代码)。如果有人需要代码的任何其他部分,请索取:

//CONNECT
arduinoSocket?.connect()
Toast.makeText(this, "Επιχειρείται σύνδεση με τον Mετρητή...", Toast.LENGTH_LONG).show()
if (!arduinoSocket!!.isConnected) {
    startbutton.isEnabled = false
    stopbutton.isEnabled = false
        Toast.makeText(this, "Σύνδεση απέτυχε.", Toast.LENGTH_SHORT).show()

    }
else {
    val t = Thread(Runnable {
        while(t_control == 1) {
            if (arduinoSocket.inputStream.read() == 72) {
                counter -= 1
                runOnUiThread {
                    ant_met.text = counter.toString()

                }
            }
        }
        Thread.sleep(50)
    })

标签: androidmultithreadingbluetoothinputstream

解决方案


我认为问题出在Arduino方面。OutputStream我相信在 Arduino 方面也有一个类型设置。根据我的经验,在 Arduino 中编码时,我必须保留一个用作OutputStream. 建立连接时,Arduino 端的缓冲区充满了一些存储在缓冲区中的脉冲。建立连接后,Arduino 端缓冲区会立即发送存储在缓冲区中的所有元素,因此您将在毫秒内获得前 3-6 个信号。

在任一侧使用一些解决方法可以很容易地避免这种情况。建立连接后,Arduino 可能已经清除存储在缓冲区中的数据。

如果您不想更改 Arduino 端代码,请在 Android 端执行类似的操作。只需从初始读取所有元素,然后在清除 Arduino 中的初始缓冲区InputStream时启动您的原始元素。Thread

// Clear the initial buffer
val t_init_control = 1
val t = Thread(Runnable {
    while(t_init_control == 1) {
        arduinoSocket.inputStream.read()
    }
})

Timer().schedule(object : TimerTask() {
    override fun run() {
        // Stop the init thread
        t_init_control = 0 
        startNewThreadHere()
    }
}, 2000)

// This is the original thread where you want to keep the track of the pulse from Arduino
fun startNewThreadHere() {
    val t = Thread(Runnable {
        while(t_control == 1) {
            if (arduinoSocket.inputStream.read() == 72) {
                counter -= 1
                runOnUiThread {
                    ant_met.text = counter.toString()

                }
            }
        }
    })
}

这只是解释这个想法的伪代码。希望有帮助!

更新

这是后来解决问题的方法。我引用了这个答案的评论部分。

Boolean向 Arduino 发送了一个,以确定何时开始发送数据包。这样,ArduinoInputStream在 Android 中打开后立即开始发送数据。因此,没有“未传输”字节的泛滥。


推荐阅读