Android Question 3 channel Bluetooth "oscilloscope" TOO slow

Hi everyone - I am very new to B4A (competent in VB) and am struggling to implement a 3 channel scope (to display ECGs) from a Buetooth data stream from an Arduino with HC-06 and an Analog front end. I know my Arduino side it working well and sends each channel as text with a header "P1 " then a number/reading and a \r terminator (chr(13), (ie: Data "P1/2/3 number\r" ) I have successfully implemented it in RoboRemo and it is smooth and fast. - I am now trying to implement it in B4A and the trace works fine but is very erratic and slow and freezes often then catches up later - as one could expect for an asynchronous stream. I am of course using AsyncStreamsText. How can I make it smooth and fast? Where have I gone wrong?
 

Attachments

  • PD_ECG.zip
    11.8 KB · Views: 58
Like a dog at a bone, I have discovered a bit more - I was conscious that I had not asked a good question, just a general appeal for help: Further investigation, ie. rewriting the program leaving out the trace display revealed that the Aync receive was NOT the problem, as I had assumed, as when just logging the text arriving, it was completely up to time. Therefore I deduce that my ignorance of how to diplay the trace on the canvas must be causing the delays. Here are the relevant passages:
B4X:
Sub Globals
    Private pnlP1, pnlP2, pnlP3 As Panel
    Private rctP1, rctP2, rctP3 As Rect
    Private cvsActivity, cvsGraph As Canvas
 End Sub

Sub Activity_Create(FirstTime As Boolean)
...
    cvsActivity.Initialize(Activity)    ' initialize the Canvas for the activity
...
    pnlP1.Initialize("pnlP1")
    Activity.AddView(pnlP1, 0, 14%y, 100%x, 28%y)
    cvsGraph.Initialize(pnlP1)
    rctP1.Initialize(0, 0, pnlP1.Width, pnlP1.Height)
    cvsGraph.drawRect(rctP1, Colors.Transparent, True, 0)
    pnlP1.Invalidate
...
End Sub

Public Sub MessageFromDevice(msg As String)
...
'Data held in three arrays P1data etc and position pointed to by P1x etc
            cvsGraph.Initialize(pnlP1)    ' initialize the Canvas for the panel
            cvsGraph.DrawLine(P1x-1, 150+P1data(P1x-1)/10, P1x, 150+P1data(P1x)/10, Colors.black, 1dip)
            pnlP1.Invalidate
            P1x = P1x+1
            If P1x > 1000 Then   'Clear screen
                cvsGraph.drawRect(rctP1, Colors.LightGray, True, 0)
                pnlP1.Invalidate
                P1x = 1
            End If
...
End Sub

I am sure I am not doing it correctly - how should I display the readings on three oscilloscope traces?
 
Upvote 0
Thank you so much for this helpful response, without saying I am an idiot (which I am) and without giving me the solution but making me work it out for myself! Now working as expected (and to time) . I hadnt appreciated the difference between canvas and panel and needed:
B4X:
Sub Globals
    Private pnlP1, pnlP2, pnlP3 As Panel
    Private rctP1, rctP2, rctP3 As Rect
    Private cvsActivity, cvsP1, cvsP2, cvsP3 As Canvas
...
End Sub

Sub Activity_Create(FirstTime As Boolean)
    ' Load the layout file
    Activity.LoadLayout("main")
    ' Initialize the Canvas for the activity
    cvsActivity.Initialize(Activity)

    ' Initialise the panel
    pnlP1.Initialize("")
    ' Add it to the Activity
    Activity.AddView(pnlP1, 0, 14%y, 100%x, 28%y)
    ' Initialise the panel on the canvas
    cvsP1.Initialize(pnlP1)
    rctP1.Initialize(0, 0, pnlP1.Width, pnlP1.Height)
... same again for P2 and P3
End Sub

Public Sub MessageFromDevice(msg As String)
...
        If hmsg ="P1 " Then
            P1data(P1x)=fmsg
            cvsP1.DrawLine(P1x-1, MP-P1data(P1x-1)/SF, P1x, MP-P1data(P1x)/SF, Colors.black, 1dip)
            P1x = P1x+1
            If P1x > pWidth-5 Then
                cvsP1.drawRect(rctP1, Colors.Transparent, True, 0)
                P1x = 1
            End If
        End If
... etc for P2 and P3
... not forgetting:
        Activity.Invalidate

End Sub

It seems one Activity.Invalidate covers the refresh of all the panels - I hope this is correct?
 
Upvote 0

DonManfred

Expert
Licensed User
Upvote 0
Top