B4J Question B4J and serial problem

Discussion in 'B4J Questions' started by hakha4, Feb 11, 2015.

  1. hakha4

    hakha4 Member Licensed User

    Newbie to B4J. I made a small program receiving data from an arduino on serial port. Code below works for a while and then crashes:

    Code:
    Sub AStream_NewData (Buffer() As Byte)
        
    '***********************************************
        Dim inputdata As String = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
        
    Dim node_id As String
        
    Dim node_location As String
        
    Dim data_1 As String
        
    Dim data_2 As String
        
    'Dim OutList As List
        Dim NL As String
        NL = 
    Chr(13)& Chr(10)
        
    '**************************



      
    If inputdata.EndsWith(NL) Then
        
    Log("data OK")

    Dim OutList() As String = (Regex.Split(",", inputdata))

        node_id  = OutList(
    0)
        
    Log(node_id)
        node_location  = OutList(
    1)
        
    Log(node_location)
        data_1 = OutList(
    2)
        
    Log(data_1)
        data_2 =  OutList(
    3)
        
    Log(data_2)


        
    Else
        
    Log("data ERROR")
        
    End If
        
    'Log(OutList)

    End Sub
    LOG :
    Program started.
    data ERROR
    data OK
    GRUND
    36.00
    21.00
    data OK
    Sensor 1
    GRUND
    36.00
    21.00
    data ERROR
    data OK
    GRUND
    36.00
    21.00
    Error occurred on line: 60 (main).
    java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at anywheresoftware.b4a.shell.Shell.runGoodChain(Shell.java:334)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:166)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:156)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:82)
    at anywheresoftware.b4a.BA$3.run(BA.java:178)
    at com.sun.javafx.application.PlatformImpl$4$1.run(Unknown Source)
    at com.sun.javafx.application.PlatformIm
    pl$4$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl$4.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(Unknown Source)
    at com.sun.glass.ui.win.WinApplication$3$1.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.ArrayIndexOutOfBoundsException: 3
    at b4j.example.main._astream_newdata(main.java:183)
    ... 23 more

    Can someone give a hint how to catch serial data in a robust way.


    BTW awesome software when you get the hang of it ! Thank's

    Regards Håkan
     
    Last edited: Feb 11, 2015
  2. Erel

    Erel Administrator Staff Member Licensed User

    Please use [code]code here...[/code] tags when posting code.

    The actual error message is missing. Please right click on the logs and copy the full error message.
     
  3. hakha4

    hakha4 Member Licensed User

    Thanks Erel for pointing out how to post properly. Anyone that can tell what's wrong and give an idea how to code ?
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    As I wrote it seems that the important error message is missing. Run your code in debug mode and make sure to post the full error message.
     
  5. hakha4

    hakha4 Member Licensed User

    Above is all output in log window after copy to clipboard.
     
  6. raphaelcno

    raphaelcno Active Member Licensed User

    It seems like the 'inputdata' variable only contains the last bytes received in AStream_NewData. Unfortunately you cannot have control about how many bytes have arrived when Sub AStream_NewData is executed. The Sub does not wait until it receives NL before it starts its execution.

    As I understand from your code, you send 4 fields separated by "," from your Arduino.

    Most of the time you are lucky to receive all bytes before Sub AStream_NewData is executed.

    But sometimes you receive first 1 field
    => Sub AStream_NewData is executed
    => inputdata.EndsWith(NL) = False
    => Log("data ERROR"),
    then you receive the last 3 fields and NL
    => Sub AStream_NewData is executed
    => inputdata.EndsWith(NL) = True
    => OutList() = Regex.Split(",", inputdata) is executed, but OutList() contains only 3 elements (not 4)
    => data_2 = OutList(3) is executed and crashes.
    That's why you get error message "Caused by: java.lang.ArrayIndexOutOfBoundsException: 3".

    You need to store the received data in a global variable until you receive NL, something like this:

    Code:
    Sub Globals
       
    Dim inputdata As String = ""
    End Sub
    Sub AStream_NewData (Buffer() As Byte)
       inputdata = inputdata & 
    BytesToString(Buffer, 0, Buffer.Length, "UTF8")
       
    '...
       If inputdata.EndsWith(NL) Then
          
    Dim OutList() AsString = (Regex.Split(",", inputdata))
          inputdata = 
    ""
          
    '...
       End If
    End Sub
    This code will probably work as long as Arduino doesn't send a new message immediately after the previous one, otherwise you could get bytes from the new message just after NL from the previous message => inputdata.EndsWith(NL) = False .
    You can use AsyncStreamsText class if necessary (http://www.b4x.com/android/forum/th...eful-when-working-with-streams-of-text.27002/).

    Edit: I don't know if AsyncStreamsText class can be used in B4J or if it's only for B4A.
     
    Last edited: Feb 12, 2015
  7. Erel

    Erel Administrator Staff Member Licensed User

    You should use AsyncStreamsText. It will work with B4J as well. Do not assume that a message sent will arrive as a single "packet". This is true only in prefix mode.
     
  8. hakha4

    hakha4 Member Licensed User

    Thank's for help. Making inputdata global improved things and indata is more reliable now. I lookup AsyncStreamsText and try to implement this
     
  9. hakha4

    hakha4 Member Licensed User

    I'veimplemented AsyncStreamsText and it works 100% with no serial errors!:)
     
    raphaelcno likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice