I have established a Bluetooth connection between Arduino (HC-05 Bluetooth module) and my Android application.
Every time Arduino sends a signal (the signal is just the number 72) then my Android app reads this signal (as bytes in an InputStream
) and sets a "counter" variable to counter = counter - 1.
I created a thread that does this.
The problem is:
If for example I set the counter to 30 and start the Thread, the first 3-4 subtractions from 30 happen in milliseconds (they are not synced with the Arduino signals). But from 26 and on everything is perfectly synced and works as expected.
I tried a different Thread.sleep()
times. Bigger sleep times make the problem worse (more subtractions happen in milliseconds). Lower sleep times are better, but still, don't solve my problem.
Why thread is out of sync for the first 3-6 subtractions and synced for all the others?
Some (maybe) useful infos:
There are 4 buttons. "Connect", "Disconnect", "Start" and "Stop".
InputStream
data from HC-05.My code (the Thread code). If someone needs any other part of code please ask for it:
//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)
})
I think the problem is on the Arduino side. There is an OutputStream
type setup in the Arduino side as well I believe. From my experience, while coding in Arduino, I had to keep a buffer which works as an OutputStream
. When the connection is being established, the buffer in the Arduino side is filling up with some pulses which are being stored in the buffer. Once the connection is getting established, the Arduino side buffer is sending out all the elements stored in the buffer at once and hence you are getting the first 3-6 signals in milliseconds.
This can be easily avoided using some workaround on either side. The Arduino may clear the data stored in the buffer already after a connection has been established.
If you do not want to change the Arduino side code, then do a similar thing in your Android side. Just read all the elements from the initial InputStream
and after some time start your original Thread
when the initial buffer in the Arduino is cleared.
// 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()
}
}
}
})
}
This is just a pseudo code to explain the idea. Hope that helps!
Update
Here's how the problem was solved later. I am quoting from the comment section of this answer.
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.