B4J Question Slow Serial Connection issue

Gaver Powers

Member
Licensed User
Longtime User
is AsyncStreamsText available in B4J?

I have an Ansyncstreams serial connection fetching values from a weight scale.

Periodically - once an hour or so... the data being obtained from the scale and displayed in a label begins pulsing or flashing and appears out of sequence.

I've tried increasing the baud rate from 9600 to 19200 - with no change or improvement.
Would AsnycStreamsText mode alleviate this problem? (hope so)

B4X:
Sub AStream_NewData (Buffer() As Byte)
    Dim s As String = BytesToString(Buffer, 0, Buffer.Length, "ASCII")   
    LogMessage(s)
End Sub

Sub LogMessage(Msg As String)
   
    lblScale.Text = Msg.Trim
   
End Sub
 

Gaver Powers

Member
Licensed User
Longtime User
I added the AsyncStreamsText.bas file to my project and tried declaring the class in main process globals as

B4X:
Private ast As AsyncStreamsText

and I'm getting an error message that indicates I may be missing a library reference.

Are there any instructions available on how to define a class and add it to a project?
 
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
Ooops...

I figured it out.
The AsyncStreams.bas file was mis-named (that way @ download)
Named AsyncSteams.bas (missing "r") and should be AsyncStreams.bas

G

Parsing code. Error
Error parsing program.
Error description: Unknown type: asyncstreamstext
Are you missing a library reference?
Occurred on line: 11
Private ast As AsyncStreamsText

B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private sp As Serial
    'Private astream As AsyncStreams
    Private ast As AsyncStreamsText
    Dim oldMsg As String = ""
    Dim lblScale As Label
    Private lblLbs As Label
    Private txtHidden As TextField
    Private Timer1 As Timer
    Private Timer2 As Timer
    Private lblResponse As Label
    Private lblScanner As Label
    Private lblErrorResponse As Label
    Private lblWaiting As Label
End Sub
 
Last edited:
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
Problem still exists after using AsyncStreamsText method.

The value from the scale still begins pulsing and or is missing altogether.

anyone got any suggestions on how to get a steady stream / reading?

Here's a sample of the output to the log.
s = 5.58
s = 5.58
s = 5.58
s = 5.58
s = 5.58
s = 5.58
s = 5.58
s = 5.58
s = 5
s = 5.58
s = 5
s = 5.58
s = 5
s = 5.58
s = 5
s = 5.58
s =
s =
s = 5.58
s = 5
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s =
s = 5.58
s = 5
s = 5.58
s =
s =
s = 5.58
s =
s =
s = 5.58
s = 5
s = 5.58
s = 5.58
s = 5
s = 5.58
s = 5
s = 5.58
s =
s = 5.58
s =
s = 5.58
s = 5
s = 5.58

Here's the Subroutine for reading the value from the scale
B4X:
Private Sub astreams_NewData (Buffer() As Byte)
    Dim newDataStart As Int = sb.Length
    sb.Append(BytesToString(Buffer, 0, Buffer.Length, charset))
    Dim s As String = sb.ToString
    'Log("s = " & s)
    Dim start As Int = 0
    For i = newDataStart To s.Length - 1
        Dim c As Char = s.CharAt(i)
            If i = 0 AND c = Chr(10) Then '\n...
            start = 1 'might be a broken end of line character
            Continue
        End If
        If c = Chr(10) Then '\n
            CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
            start = i + 1
        Else If c = Chr(13) Then '\r
            CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
            If i < s.Length - 1 AND s.CharAt(i + 1) = Chr(10) Then '\r\n
                i = i + 1
            End If
            start = i + 1
        End If
    Next
    Main.LogMessage(s)
    Log("s = " & s)
    If start > 0 Then sb.Remove(0, start)
End Sub

Sub LogMessage(Msg As String)
   
    lblScale.Text = Msg.Trim
   
End Sub
 
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
Thanks positrom2,

I figured that out and renamed the file - and it worked - or at least I think its running.

The Breaks; Gaps and Missing data are not present when viewing the data stream in a terminal program (putty). I also noticed that the pulsing / missing data occurs at the start of the app immediately sometime when I start the app, other times after letting the app run for hours.

Relaunching the app - results in a better stream for a period of time, then it begins fluctuating again.

In # 8 above - what is this line of code doing? I'm having trouble figuring out what variable is storing the string of input data from the scale in that routine... ref:
B4X:
CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
This line raises the NewText event. The text is stored in 's' variable.

In order to check the communication issues you should use AsyncStreams in regular mode and call Log(BytesToString(Buffer, 0, Buffer.Length, "ASCII"))

Now see whether there are any gaps or slowdowns. In this mode AsyncStreams will not buffer anything.
 
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
Erel,

I did as you suggested.

B4X:
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
 
  5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.3
0
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
    5.30
 
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
In the interim - I decided that I'd trap for empty or malformed values - and restart the serial / asycstreams connection(s) - essentially rebooting the app.

When it reboots - it generates the following error message in the log.
B4X:
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:122)
    at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:116)
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:184)
    at java.lang.Thread.run(Thread.java:722)
Restarting Serial Connection 02/06/2014 12:33:20

Anyway to avoid the error - or is it inconsequential ?
 
Upvote 0

Tom Christman

Active Member
Licensed User
Longtime User
What about using B4a and a usb/serial connection?
Please see Erels
[class] AsyncStreamsText - Useful when working with streams of text
Also see the below code listing below to replace the server example code from the above tutorial with code for usb/serial.

Also add the aStreams.bas as a class module in your project (note this class is originally titled "aSteams.bas" (missingR)
Main code
B4X:
Sub Process_Globals
    Private ast As AsyncStreamsText
    Private usb As UsbSerial
End Sub
Sub Globals
    "YOUR GLOBALS DATA"
    Dim d As double
    Dim pw As PhoneWakeState' keep alive (add Phone Lib and RandomAccessFile library( for asyncstreams lib))
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Actiivity.LoadLayout("1")
If usb.UsbPresent = usb.USB_NONE Then
    Log("Msgbox - no device")
    Msgbox("No USB device or accessory detected!")
    Log("Msgbox - returned")
    Return
End If
Log("Checking permission")
If (usb.HasPermission) Then
    usb.SetParameters(9600,8,1,0)
    usb.UsbTimeout = 1000
Dim dev As Int
dev = usb.Open(9600)

If dev<> usb.USB_NONE Then
    Log("Connected Successfully")
If ast.IsInitialized Then ast.Close
    ast.Initialize(Me,"astreams",usb.GetInputStream,usb.GetOutStream)
Else
    Log("Error opening USB port")
End If
Else
    usb.RequestPermission
    Flush.Enabled=True
    Flush.Visible=True
End If
End Sub

Sub astreams_NewText(Text As String)
    Log(Text)
    Dim msg As String
    d = NumberFormat2((msg),0,0,0,False)
End Sub

Sub ast_Terminated
    Log("Terminated")
    ast.Close
End Sub

Sub Activity_Resume
pw_KeepAlive(True)
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub
 
Last edited:
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
@tom - thanks for the input - I'm using a serial connection and tried using AsyncStreamsText - that's what generated the stream in post #8 above.

The stream in # 13 above was generated with AsyncStreams Standard mode (no prefix)

Gaps in the stream reflect a break in the reading of the stream of data from the scale - in some instances the break is reflecting a missing space character or other numerical text data.

A serial terminal connected to the scale does not reflect the same breaks in transmission / reception.

I put a test for the length of the string being read in the screen update process - and if it's less than 3 (eg x.yz) - then I write "WAIT" to the screen and close the serial connection & asyncstreams and then re-start them, sort of a soft re-boot. This prevents someone from transmitting the data back to the server without having a valid weight value. This seems to be working at the moment.

It may be that the only way to really figure out where the break in data is occurring is to hook an oscilloscope up to the unit and sniff each packet / byte and see what's actually being sent. Based on the "look" of the stream in the log - it looks to me like the buffer is being chopped up and getting out of sync somehow.

Because it's an intermittent problem - it's really difficult to reproduce in real time.

Thanks for all the suggestions and help...

Here's the log results after letting it run in release mode overnight.
B4X:
Program started.

Restarting Serial Connection 02/06/2014 12:33:20
Restarting Serial Connection 02/06/2014 12:33:20
Restarting Serial Connection 02/06/2014 13:00:35
Restarting Serial Connection 02/06/2014 13:51:33
Restarting Serial Connection 02/06/2014 14:10:24
Restarting Serial Connection 02/06/2014 14:41:05
Restarting Serial Connection 02/06/2014 15:23:58
Restarting Serial Connection 02/06/2014 15:54:08
Restarting Serial Connection 02/06/2014 17:44:56
Restarting Serial Connection 02/06/2014 18:24:53
Restarting Serial Connection 02/06/2014 19:12:45
Restarting Serial Connection 02/06/2014 19:12:45
Restarting Serial Connection 02/06/2014 19:17:55
Restarting Serial Connection 02/06/2014 19:44:49
Restarting Serial Connection 02/06/2014 20:20:34
Restarting Serial Connection 02/06/2014 20:39:23
Restarting Serial Connection 02/06/2014 21:20:10
Restarting Serial Connection 02/06/2014 21:41:01
Restarting Serial Connection 02/06/2014 22:20:48
Restarting Serial Connection 02/06/2014 23:00:14
Restarting Serial Connection 02/06/2014 23:20:54
Restarting Serial Connection 02/06/2014 23:57:21
Restarting Serial Connection 02/07/2014 00:30:36
Restarting Serial Connection 02/07/2014 00:50:12
Restarting Serial Connection 02/07/2014 01:09:52
Restarting Serial Connection 02/07/2014 01:28:28
Restarting Serial Connection 02/07/2014 01:42:53
Restarting Serial Connection 02/07/2014 02:07:38
Restarting Serial Connection 02/07/2014 02:26:33
Restarting Serial Connection 02/07/2014 03:23:24
Restarting Serial Connection 02/07/2014 03:43:49
Restarting Serial Connection 02/07/2014 04:01:49
Restarting Serial Connection 02/07/2014 04:25:26
Restarting Serial Connection 02/07/2014 04:53:42
Restarting Serial Connection 02/07/2014 05:09:11
Restarting Serial Connection 02/07/2014 05:34:12
Restarting Serial Connection 02/07/2014 06:20:17
Restarting Serial Connection 02/07/2014 07:08:25
Restarting Serial Connection 02/07/2014 07:55:40
Restarting Serial Connection 02/07/2014 08:40:39
Restarting Serial Connection 02/07/2014 09:11:22
 
Upvote 0

KitCarlson

Active Member
Licensed User
Longtime User
Gaver,

Following Erel's advise will solve your problem. The AsyncStreamsText concatenates Newdata bytes as necessary, when end terminator is reached, then log or process. Not all data always arrives, in one Newdata. Take a look at Erel's code, you will understand the difference, and problems in your code.
 
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
Kit,

I thought I was using AsyncStreamsText in my application - maybe I'm not using it correctly?
I added the AsyncStreamsText.bas file to my project and declared
Private ast As AsyncStreamsText in the Main Sub Process Globals

The AsyncStreamsText.bas module has the following subroutine in it:
B4X:
Private Sub astreams_NewData (Buffer() As Byte)
    Dim newDataStart As Int = sb.Length
    'Log ("newdatastart = " & newDataStart)
    sb.Append(BytesToString(Buffer, 0, Buffer.Length, charset))
    Dim s As String = sb.ToString
    'Log("length of s =  " & s.Length)
    Dim start As Int = 0
    For i = newDataStart To s.Length - 1
        Dim c As Char = s.CharAt(i)
            If i = 0 AND c = Chr(10) Then '\n...
            start = 1 'might be a broken end of line character
            Continue
        End If
        If c = Chr(10) Then '\n
            CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
            start = i + 1
        Else If c = Chr(13) Then '\r
            CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
            If i < s.Length - 1 AND s.CharAt(i + 1) = Chr(10) Then '\r\n
                i = i + 1
            End If
            start = i + 1
        End If
    Next
    Main.LogMessage(s)
    'Log("scl = " & sb)
    If start > 0 Then sb.Remove(0, start)
End Sub

Is this not the correct subroutine for AsyncStreamsText ?

I just noticed I left the ast_NewText(Text As String) function out of the Main program... added it and running a test now.
 
Last edited:
Upvote 0

Gaver Powers

Member
Licensed User
Longtime User
I let the program run overnight.

Good news!

Problem solved

Thanks to everyone for your assistance - much appreciated.

G
 
Upvote 0
Top