Android Question USB Flow control

Cesaral

Member
I am writing a program to interface with a serial to USB chip with reference CP2102N.

I am using the USBserial library (2.40) and it works well 95% of the time.....but not 100%

The code I use is quite simple <code>
B4X:
Public usb1 As UsbSerial
…

Dim dev As Int
dev = usb1.Open(460800, 1)
If dev <> usb1.USB_NONE Then
    Log("Connected!")
    astreams1.Initialize(usb1.GetInputStream, usb1.GetOutputStream, "astreams1")
End If

The problem is that sometimes I get extra bytes in the interface and taking into account that what I get are communications frames, I am in trouble.

1) How does this library manage an accurate work-flow with the CP2102N chip?
2) How can I get reliable data all the time?


Thanks!
 

Cesaral

Member
I have tried a FellUSB example that I took from this forum:

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
  
    Private usbserial As felUsbSerial
    Private manager As UsbManager
    Private bc As ByteConverter

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")

    If FirstTime Then
        manager.Initialize
    End If
  
    Dim btnConnect As Button
    btnConnect.Initialize("btnConnect")
    btnConnect.Text = "Connect"
    Activity.AddView(btnConnect, 10dip, 10dip, 100dip, 100dip)

End Sub
'
'
Sub Activity_Resume

End Sub
'
'
Sub Activity_Pause (UserClosed As Boolean)

End Sub
'
'
Sub Button1_Click
    xui.MsgboxAsync("Hello world!", "B4X")
  
    If manager.GetDevices.Length = 0 Then
        Log("No connected usb devices.")
    Else
        Dim device As UsbDevice = manager.GetDevices(0) 'assuming that there is exactly one device
        Log ("Device=" & device)
        If manager.HasPermission(device) = False Then
            ToastMessageShow("Please allow connection and click again.", True)
            manager.RequestPermission(device)
        Else
            usbserial.Initialize("serial", device, -1)
            usbserial.BaudRate = 460800 ' 115200
            usbserial.DataBits = usbserial.DATA_BITS_8
            usbserial.StartReading
        End If
    End If

End Sub
'
'
Private Sub serial_DataAvailable (Buffer() As Byte)
    Log("New data: " & bc.HexFromBytes(Buffer))
End Sub

The LOG that I get running it is:

B4X:
Registro conectado a:  samsung SM-A525F
--------- beginning of main
Copying updated assets files (1)
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Device=(UsbDevice) UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=4292,mProductId=60000,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=Silicon Labs,mProductName=CP2102N USB to UART Bridge Controller,mVersion=1.00,mSerialNumberReader=android.hardware.usb.IUsbSerialReader$Stub$Proxy@c9241ef, mHasAudioPlayback=false, mHasAudioCapture=false, mHasMidi=false, mHasVideoCapture=false, mHasVideoPlayback=false, mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=50,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=255,mSubclass=0,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=2,mAttributes=2,mMaxPacketSize=64,mInterval=0]
UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=64,mInterval=0]]]]
** Activity (main) Pause, UserClosed = false **
** Service (starter) Destroy (ignored)**

It happens the same....

Here is and example of what I get:

B4X:
...
New data: AB0602019B5D0E0C00BC
New data: AB0602019C5D0E0C00BC
New data: AB0602019D5D0E0C00BC
New data: AB0602019E5D0E0C00BC
New data: AB0602019F5D0E0C00BC
New data: AB060201A05D0E0C00BC
New data: AB060201A15D0E0C00BC
New data: AB060201A25D0E0C00BC
New data: AB060201A35D0E0C00BC
New data: AB060201A45D0E0C00BC
New data: AB060201A55D0E0C00BC
New data: AB060201A65D0E0C00BC
New data: AB060201A75D0E0C00BC
New data: AB060201A85D0E0C00BC
New data: AB060201A95D0E0C00BC
New data: AB060201AA5D0E0C00BC
New data: AB060201CDAC5D0E0C00BC
New data: AB060201AC5D0E0C00BC
New data: AB060201AD5D0E0C00BC
New data: AB060201AE5D0E0C00BC
New data: AB060201AF5D0E0C00BC
New data: AB060201B05D0E0C00BC
New data: AB060201B15D0E0C00BC
New data: AB060201B25D0E0C00BC
New data: AB060201B35D0E0C00BC
New data: AB060201B45D0E0C00BC
New data: AB060201B55D0E0C00BC
...

Al the lines should be like this one:

New data: AB060201B15D0E0C00BC

, and suddenly I get this one with a change (B1 is changed by a CDAC) that does not really happen:

New data: AB060201CDAC5D0E0C00BC

It seems to me that the receiving thread looses priority at some point and it misses something...I say this because the transmitter send this frames at the same rate...but the LOG shows suddenly that it stops showing the data received, and one or two seconds later it resumes and then I find this sort of problems.

Thanks!
 
Last edited:
Upvote 0

Cesaral

Member
What I meant in my previous post is this:

All the lines should be like this one in length:

New data: AB060201B15D0E0C00BC

, and suddenly I get this one with a change in its length (that does not really happen):

New data: AB060201CDAC5D0E0C00BC

Thanks!
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Longtime User
In general, the higher the baud rate, the more prone to timing errors and random disturbances by chance. What strikes me is that when initializing you set the baud rate to a non-standard rate of 460,800 instead of say 57,600 or 115,200 while the datasheet reports timing issues above a rate of 230,400. In addition, the stop bits are not set to 1 and the parity bit is not set to none. My advice also set the missing stop bit to 1, do not use a parity check (save time) and start slowly with a baud rate of 57,600 and increase the speed in steps after a test shows no error.
 
Upvote 0

Cesaral

Member
In general, the higher the baud rate, the more prone to timing errors and random disturbances by chance. What strikes me is that when initializing you set the baud rate to a non-standard rate of 460,800 instead of say 57,600 or 115,200 while the datasheet reports timing issues above a rate of 230,400. In addition, the stop bits are not set to 1 and the parity bit is not set to none. My advice also set the missing stop bit to 1, do not use a parity check (save time) and start slowly with a baud rate of 57,600 and increase the speed in steps after a test shows no error.
Thanks! The result has been the same doing this:

B4X:
    ...
    dev = usb1.Open(460800, 1)
    ...

Than doing this:

B4X:
    ...
    dev = usb1.Open(460800, 1)
    usb1.SetParameters(460800, usb1.DATABITS_8, usb1.STOPBITS_1, usb1.PARITY_NONE)
    ...

I also tried to change the baud rate to different standard values....I got the best result with this 460800 value....I don´t know why...
 
Upvote 0

teddybear

Well-Known Member
Licensed User
Use serial port debugging tool on PC to check whether the data received is correct.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Longtime User
I also tried to change the baud rate to different standard values....I got the best result with this 460800 value....I don´t know why...
Perhaps because the clock frequency of the chip is 48.000.000 and a Baudrate of 460.800?
mmmm........ Let looks further. Remember it is important to always change one thing, and test the impact and after you find an acceptable solution, removed one by one the added measures to find the needed one or more measures to fix the problem with the optimized only needed measures.
  1. Synchronizing clocking between different serial devices in some way in serial transmission is always critical. Can you see a random "time" problem or is it always at the same received data block number with different baudrates and with the same interval range?

  2. Other points of attention are I don't see a "paring" to the specific Vendor ID (VID) of 0x10C4, Product ID (PID) of 0xEA60 nor to the DRIVER_SILABS int for the Silicon Labs CP2102 driver of the library is indeed used in this case. So we cannot rule out the possibility that something else is disturbing the serial communication or we using the wrong driver.

  3. Furthermore I don't see how the handshake is solved and how it is configured. The software solution must be in line with the implemented hardware solution for RTS/CTS or XON/XOFF handshake. What I always did is create a overflow situation to see what happens and bring the solution in line with this behavior.

  4. I don't think that that is the problem but the example program use a 60 msec delay after sending the configuration parameters to give the device time to process the configuration.

  5. Then there is the way how the solution recovers from the error. Is it always use the same time to restart the communication? Or is it depending on some way to other activities at the same time in the both sending and receiving environment?

  6. Can you create some kind of mechanism that communication is done with a counter value in it so that you can see if and how much of the counting is lost? It could that the B1 is changed by a CDAC as a some flow control and nothing is lost or the B1 is changed by a CDAC as an error recovering warning.
 
Upvote 0
Top