Hi Everyone, I am working on a project where I have a raspberry pi 4B where I have a b4j app running which communicates with a 32 channel Analog to Digital Converter we designed and built at work, the communication is via I2C protocol, this part works very well as far as I have been able to test.
The B4J app running on the raspberry pi collects around 1000 samples per second on each device, so far I have been testing with only 4 channels. I thought about using MTTQ library so that I can send the collected data of every iteration to another B4J App running on my Laptop PC so that I can plot the data on a XY line chart, while this is all working great, I have noticed that the Sub client_MessageArrived (Topic As String, Payload() As Byte) function is not raised as fast as I would expect.
I have made some time measurements on the app running on the raspberry pi and how long it takes to read between 32 bytes and 40 bytes and so far I have seen that it takes anywhere between 2 to 8 milliseconds per read, the data of all 4 channels is included in the 32 byte array read every iteration. The data is then sent or published via the MTTQ client library on every iteration.
What I would expect is that this data should arrive just as fast as it is sent, but I am seeing a delay of between 2 to 4 seconds on the PC laptop.
I was wondering if anyone has done any work using the MQTT library, I realize that using this library is probably not ideal for what I am trying to accomplish, essentially I am trying to plot data almost LIVE so that we can visually see changes on power, current and voltage on devices we are testing.
As context, we have also created a python script which does pretty much the same thing, it reads data from the i2c devices, saves data to a large array, then plotting the data. I see a huge difference between the speed using python and Java, however I would really love to find a better solution using B4X since I am more familiar with it than any other programming language.
Below is the relevant code from both b4j apps, the first one which reads data via i2c on the raspberry pi and publishes the data to a certain topic, and the second one which is running on my laptop pc which receives the data published to the same topic.
This function is from the library I wrapped using the pi4j v2 java library, as you can see that's where I am taking the measurements of how long it takes to read 32 to 40 bytes of data and where I am seeing that it takes only between 2 to 8 milliseconds per read.
Here's where I collect data up to 1000 samples every iteration, then the data is sent via the MQTT library.
The following function is where the data published is received and sent to the XY charts to plot the data as is received.
If anyone has any experience using the MQTT library and can provide some assistance in figuring out why the data is received every 2 to 4 seconds rather than a few milliseconds please let me know.
The B4J app running on the raspberry pi collects around 1000 samples per second on each device, so far I have been testing with only 4 channels. I thought about using MTTQ library so that I can send the collected data of every iteration to another B4J App running on my Laptop PC so that I can plot the data on a XY line chart, while this is all working great, I have noticed that the Sub client_MessageArrived (Topic As String, Payload() As Byte) function is not raised as fast as I would expect.
I have made some time measurements on the app running on the raspberry pi and how long it takes to read between 32 bytes and 40 bytes and so far I have seen that it takes anywhere between 2 to 8 milliseconds per read, the data of all 4 channels is included in the 32 byte array read every iteration. The data is then sent or published via the MTTQ client library on every iteration.
What I would expect is that this data should arrive just as fast as it is sent, but I am seeing a delay of between 2 to 4 seconds on the PC laptop.
I was wondering if anyone has done any work using the MQTT library, I realize that using this library is probably not ideal for what I am trying to accomplish, essentially I am trying to plot data almost LIVE so that we can visually see changes on power, current and voltage on devices we are testing.
As context, we have also created a python script which does pretty much the same thing, it reads data from the i2c devices, saves data to a large array, then plotting the data. I see a huge difference between the speed using python and Java, however I would really love to find a better solution using B4X since I am more familiar with it than any other programming language.
Below is the relevant code from both b4j apps, the first one which reads data via i2c on the raspberry pi and publishes the data to a certain topic, and the second one which is running on my laptop pc which receives the data published to the same topic.
i2c_Read function:
Public Sub i2c1_read(register As Int, numofbytestoread As Int) As Byte()
Dim byte_array(numofbytestoread) As Byte
Dim successful As Boolean = False
Do While successful = False
Try
Dim start As Long = DateTime.Now
i2c1.ReadBytesI2C(register, byte_array)
Dim stop As Long = DateTime.Now
Log("time elapsed from i2c_read: " & ((stop - start)/1000))
successful = True
Catch
successful = False
End Try
Loop
Return byte_array
End Sub
read data from i2c devices:
For i = 0 To 999
Dim start1 As Long = DateTime.Now
Dim stop As Long = DateTime.Now
i2c.SendRefresh(0x2)
Dim vals() As Float = i2c.get_power_voltage_current
xdata(i) = (stop - start) / 1000
ydata(i) = vals(7)
ydata2(i) = vals(4)
ydata3(i) = vals(1)
ydata4(i) = vals(10)
Next
mylist.Initialize
mylist.Add(EncapsulateData(xdata, ydata))
mylist.Add(EncapsulateData(xdata, ydata2))
mylist.Add(EncapsulateData(xdata, ydata3))
mylist.Add(EncapsulateData(xdata, ydata4))
Dim b() As Byte = serializator.ConvertObjectToBytes(mylist)
Try
client.Publish2("datacollection", b, 2, False)
Sleep(10)
Catch
Log("Error sending data")
End Try
The following function is where the data published is received and sent to the XY charts to plot the data as is received.
message received function:
Sub client_MessageArrived (Topic As String, Payload() As Byte)
Log("topic: " & Topic)
Try
Dim receivedObject As Object = serializator.ConvertBytesToObject(Payload)
If Topic = "datacollection" Then
Dim start As Long = DateTime.Now
Dim m As mydata
Dim m2, m3, m4 As mydata
Dim l As List = receivedObject
m = l.Get(0)
m2 = l.Get(1)
m3 = l.Get(2)
m4 = l.Get(3)
Dim xdata() As Object
Dim ydata() As Object
Dim xdata2() As Object
Dim ydata2() As Object
Dim xdata3() As Object
Dim ydata3() As Object
Dim xdata4() As Object
Dim ydata4() As Object
xdata = m.xxdata
ydata = m.yydata
xdata2 = m2.xxdata
ydata2 = m2.yydata
xdata3 = m3.xxdata
ydata3 = m3.yydata
xdata4 = m4.xxdata
ydata4 = m4.yydata
Log("xdata lenght: " & xdata.Length)
Log("ydata lenght: " & ydata.Length)
liveLC.updateLC("Board_ID", castObjectToDoubleArray(xdata), castObjectToDoubleArray(ydata))
livelc2.updateLC("PPVUnreg_J10", castObjectToDoubleArray(xdata2), castObjectToDoubleArray(ydata2))
liveLC3.updateLC("PPVUnreg_J14", castObjectToDoubleArray(xdata3), castObjectToDoubleArray(ydata3))
liveLC4.updateLC("PPVUnreg_ProjRight", castObjectToDoubleArray(xdata4), castObjectToDoubleArray(ydata4))
For ii = 0 To xdata.Length - 1
Dim x As String = CastObjectToDouble(xdata(ii))
Dim y As String = CastObjectToDouble(ydata(ii))
Dim y2 As String = CastObjectToDouble(ydata2(ii))
Dim y3 As String = CastObjectToDouble(ydata3(ii))
Dim y4 As String = CastObjectToDouble(ydata4(ii))
csvTable.Add(Array As String(x, y3, y2, y, y4))
Next
Dim stop As Long = DateTime.Now
Log("time elapsed: " & (stop - start))
ended = DateTime.Now
Log("time elapsed betweem data received = " & (ended - begin))
Else if Topic = "all/disconnect" Then
Log("topic: " & Topic)
Dim su As StringUtils
su.SaveCSV(File.DirApp, "plot_data.csv", ",", csvTable)
End If
Catch
Log("Error while processing messages")
Dim su As StringUtils
su.SaveCSV(File.DirApp, "plot_data.csv", ",", csvTable)
End Try
End Sub
If anyone has any experience using the MQTT library and can provide some assistance in figuring out why the data is received every 2 to 4 seconds rather than a few milliseconds please let me know.