线程中的计数器运行,由Arduino信号驱动,跳过前几个数字
Counter running in thread, driven by Arduino signals, skips the first several numbers
我已经在 Arduino(HC-05 蓝牙模块)和我的 Android 应用程序之间建立了蓝牙连接。
每次 Arduino 发送一个信号(信号就是数字 72),然后我的 Android 应用程序读取这个信号(作为 InputStream
中的字节)并设置一个 "counter"变量为 counter = counter - 1.
我创建了一个执行此操作的线程。
问题是:
例如,如果我将计数器设置为 30 并启动线程,则 30 的前 3-4 次减法以毫秒为单位发生(它们与 Arduino 信号不同步)。但是从 26 开始,一切都完美同步并按预期工作。
我尝试了不同的 Thread.sleep()
次。更长的睡眠时间使问题变得更糟(更多的减法在毫秒内发生)。睡眠时间越短越好,但还是解决不了我的问题
为什么前 3-6 个减法线程不同步而其他所有减法线程同步?
一些(可能)有用的信息:
有 4 个按钮。 "Connect"、"Disconnect"、"Start" 和 "Stop".
- "Connect": 通过BluetoothSocket与HC-05建立连接
- "Disconnect": 关闭此连接。
- "Start": 启动监听来自 HC-05 的
InputStream
数据的线程。
- "Stop": 停止
这个线程。
我的代码(线程代码)。如果有人需要代码的任何其他部分,请提出要求:
//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)
})
我认为问题出在Arduino这边。我相信 Arduino 方面也有一个 OutputStream
类型的设置。根据我的经验,在使用 Arduino 编写代码时,我必须保留一个用作 OutputStream
的缓冲区。建立连接时,Arduino 端的缓冲区会填满一些存储在缓冲区中的脉冲。建立连接后,Arduino 端缓冲区会立即发送缓冲区中存储的所有元素,因此您会在几毫秒内收到前 3-6 个信号。
这可以通过在任何一方使用一些变通方法轻松避免。 Arduino 可能会在建立连接后清除缓冲区中存储的数据。
如果您不想更改 Arduino 端代码,请在您的 Android 端执行类似的操作。只需读取初始 InputStream
中的所有元素,一段时间后,当 Arduino 中的初始缓冲区被清除时,开始您的原始 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()
}
}
}
})
}
这只是一个解释这个想法的伪代码。希望对您有所帮助!
更新
这是后来解决问题的方法。我是从这个答案的评论部分引用的。
I sent a Boolean
to Arduino in order to determine when to start
sending packets of data. In that way, Arduino starts sending data
right after opening the InputStream
in Android. Hence, there is no
flood of "non-transmitted" bytes.
我已经在 Arduino(HC-05 蓝牙模块)和我的 Android 应用程序之间建立了蓝牙连接。
每次 Arduino 发送一个信号(信号就是数字 72),然后我的 Android 应用程序读取这个信号(作为 InputStream
中的字节)并设置一个 "counter"变量为 counter = counter - 1.
我创建了一个执行此操作的线程。
问题是:
例如,如果我将计数器设置为 30 并启动线程,则 30 的前 3-4 次减法以毫秒为单位发生(它们与 Arduino 信号不同步)。但是从 26 开始,一切都完美同步并按预期工作。
我尝试了不同的 Thread.sleep()
次。更长的睡眠时间使问题变得更糟(更多的减法在毫秒内发生)。睡眠时间越短越好,但还是解决不了我的问题
为什么前 3-6 个减法线程不同步而其他所有减法线程同步?
一些(可能)有用的信息:
有 4 个按钮。 "Connect"、"Disconnect"、"Start" 和 "Stop".
- "Connect": 通过BluetoothSocket与HC-05建立连接
- "Disconnect": 关闭此连接。
- "Start": 启动监听来自 HC-05 的
InputStream
数据的线程。 - "Stop": 停止 这个线程。
我的代码(线程代码)。如果有人需要代码的任何其他部分,请提出要求:
//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)
})
我认为问题出在Arduino这边。我相信 Arduino 方面也有一个 OutputStream
类型的设置。根据我的经验,在使用 Arduino 编写代码时,我必须保留一个用作 OutputStream
的缓冲区。建立连接时,Arduino 端的缓冲区会填满一些存储在缓冲区中的脉冲。建立连接后,Arduino 端缓冲区会立即发送缓冲区中存储的所有元素,因此您会在几毫秒内收到前 3-6 个信号。
这可以通过在任何一方使用一些变通方法轻松避免。 Arduino 可能会在建立连接后清除缓冲区中存储的数据。
如果您不想更改 Arduino 端代码,请在您的 Android 端执行类似的操作。只需读取初始 InputStream
中的所有元素,一段时间后,当 Arduino 中的初始缓冲区被清除时,开始您的原始 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()
}
}
}
})
}
这只是一个解释这个想法的伪代码。希望对您有所帮助!
更新
这是后来解决问题的方法。我是从这个答案的评论部分引用的。
I sent a
Boolean
to Arduino in order to determine when to start sending packets of data. In that way, Arduino starts sending data right after opening theInputStream
in Android. Hence, there is no flood of "non-transmitted" bytes.