Android Question Strange problem with FelUsbSerial library and 3D Printer controller running Marlin @ 250000 bps

max123

Well-Known Member
Licensed User
Longtime User
Hi all,

I would like to write a B4A application capable of connecting to USB controllers for 3D Printers, in this regard I did some tests with the FelUsbSerial library, but I have a problem that I can not solve in any way.

My 3D Printer controller is equipped with a FTDI serial converter and Atmega2560 where the Marlin firmware runs, which by default is set with a baud rate of 250000 bps.

Connecting to the controller with OTG cable @ 250000 bps, I get strange characters, as if the baud rate was not correct, so I tried to reprogram Arduino with Marlin firmware setting 115200 bps and this works, I tried 230400 and it works too, but 250000 does not want to work and returns always strange characters.

Can anyone tell me why this happens? Is the 250000 baud rate missing in the library?

Since in the future I must also use the MIDI protocol to interface with digital musical instruments, this protocol uses 31250 bps, but it is not a standard baud rate, can you tell me if this will work?

I use B4A, B4J, B4R for many years, but I also use Jabaco to create applications that they run on Raspberry without JavaFX UI, just days ago I developed the same application for 3D printing on Jabaco, in this regard I created a class that use JSSC library and I added to the standard baudrates also 250000 (and others), this works very well and I can connect to the Atmega2560 and command the printer from my pc, even many other users have managed to make various prints.

Also I added 31250 and I can successfully connect and command various digital MIDI musical instruments.

I used JSSC because it's the one used in the B4J Serial library, so I like it because I love B4J.

The JSSC porting I wrote for Jabaco uses the following baud rates:

110, 150, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, 57600, 115200,
128000, 230400, 250000, 256000, 460800, 500000, 512000, 576000, 921600, 1000000, 1152000, 1500000,
2000000, 2500000, 3000000, 3500000, 4000000.

I have not tested all them, but all those tested work successfully, even non standard baud rates.

I would like to convert this printing application to B4A using FelUsbSerial library, but I'm stuck for this problem that I can't solve in any way.

I would like to ask if it is possible to add these specified above baud rates to the FelUsbSerial library.

Many thanks.
 
Last edited:

max123

Well-Known Member
Licensed User
Longtime User
Many thanks Erel for your reply.
So no way to add more baudrates? Require I compile myself the library?

Many thanks.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
FTDI supports all baudrates, is the library that miss some.

I can control from PC at any baudrate (with my application and all applications for 3D printers like Repetier Host and others).
Same for all Android apps found on GooglePlay for 3D printing and even simple Serial-USB app loggers.

I can control from B4J applications Serial library too, at any baudrate.

It is the same for CH34x serial converter. I'm sure, tried even with ESP8266 NodeMCU and even with B4J on PC.
I don't have others serial converters but I think works too.

The B4A library code is opensource? You can send me? If yes I will try to fix the question and recompile it on Eclipse.

Many thanks for your pecious time.
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Hi Erel,

I've found a formula to calculate the control command value for FTDI, in the library code I see that others serial conversters use the same way, but maybe need to adapt.

Can you show me how to change it with reflection library?

I think need to bypass some code because in the library there is an Override method that select baudrates intervals, these lines:

B4X:
@Override
    public void setBaudRate(int baudRate)
    {
        int value = 0;
        if(baudRate >= 0 && baudRate <= 300 )
            value = FTDI_BAUDRATE_300;
        else if(baudRate > 300 && baudRate <= 600)
            value = FTDI_BAUDRATE_600;
        else if(baudRate > 600 && baudRate <= 1200)
            value = FTDI_BAUDRATE_1200;
        else if(baudRate > 1200 && baudRate <= 2400)
            value = FTDI_BAUDRATE_2400;
        else if(baudRate > 2400 && baudRate <= 4800)
            value = FTDI_BAUDRATE_4800;
        else if(baudRate > 4800 && baudRate <= 9600)
            value = FTDI_BAUDRATE_9600;
        else if(baudRate > 9600 && baudRate <=19200)
            value = FTDI_BAUDRATE_19200;
        else if(baudRate > 19200 && baudRate <= 38400)
            value = FTDI_BAUDRATE_38400;
        else if(baudRate > 19200 && baudRate <= 57600)
            value = FTDI_BAUDRATE_57600;
        else if(baudRate > 57600 && baudRate <= 115200)
            value = FTDI_BAUDRATE_115200;
        else if(baudRate > 115200 && baudRate <= 230400)
            value = FTDI_BAUDRATE_230400;
        else if(baudRate > 230400 && baudRate <= 460800)
            value = FTDI_BAUDRATE_460800;
        else if(baudRate > 460800 && baudRate <= 921600)
            value = FTDI_BAUDRATE_921600;
        else if(baudRate > 921600)
            value = FTDI_BAUDRATE_921600;
        else
            value = FTDI_BAUDRATE_9600;
        setControlCommand(FTDI_SIO_SET_BAUD_RATE, value, 0, null);
    }
 
    private int setControlCommand(int request, int value, int index, byte[] data)
    {
        int dataLength = 0;
        if(data != null)
        {
            dataLength = data.length;
        }   
        int response = connection.controlTransfer(FTDI_REQTYPE_HOST2DEVICE, request, value, mInterface.getId() + 1 + index, data, dataLength, USB_TIMEOUT);
        Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
        return response;
    }


PS: If you need to change felUsbLibrary and add more baudrates, I've attached an explanation and If you want
I've a PDF file that show it and all explanation related to set any baudrate.

Many thanks.

-------------------------------

Baud Rate Calculation
A Baud rate for the FT232R, FT2232 (UART mode) or FT232B is generated using the chips
internal 48MHz clock. This is input to Baud rate generator circuitry where it is then divided by 16
and fed into a prescaler as a 3MHz reference clock. This 3MHz reference clock is then divided
down to provide the required Baud rate for the device's on chip UART. The value of the Baud rate
divisor is an integer plus a sub-integer prescaler. The original FT8U232AM only allowed 3 sub-
integer prescalers - 0.125, 0.25 or 0.5. The FT232R, FT2232 (UART mode) and FT232B support
a further 4 additional sub-integer prescalers - 0.375, 0.625, 0.75, and 0.875. Thus, allowed values
for the Baud rate divisor are:
Divisor = n + 0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875; where n is an integer between 2 and
16384 (2 14 ).
Note: Divisor = 1 and Divisor = 0 are special cases. A divisor of 0 will give 3 MBaud, and a divisor
of 1 will give 2 MBaud. Sub-integer divisors between 0 and 2 are not allowed.
Therefore the value of the divisor needed for a given Baud rate is found by dividing 3000000 by the
required Baud rate.
The exact Baud rate may not be achievable - however as long as the actual Baud rate used is
within +/-3% of the required Baud rate then the link should function without errors. When a Baud
rate is passed to the driver where the exact divisor required is not achievable the closest possible
Baud rate divisor will be used as long as that divisor gives a Baud rate which is within +/- 3% of the
Baud rate originally set.
For example:
A non-standard Baud rate of 490000 Baud is required.
Required divisor = 3000000 / 490000 = 6.122
The closest achievable divisor is 6.125, which gives a baud rate of 489795.9, which is well within
the allowed +/- 3% margin of error. Therefore 490000 can be passed to the driver and the device
will communicate without errors.

Aliasing Baud Rates
The file FTDIPORT.INF contains entries that are used as the divisors for standard Baud rates. By
changing these it is possible to alias standard Baud rates with non-standard values - for instance
replacing 115kBaud with 512kBaud. Users would then set up the FT232R, FT2232 (UART mode)
or FT232B to operate at 512kBaud by selecting 115kBaud for the appropriate serial port.
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Many thanks Erel.

I need to do this before or after I connect?

If you or any user need reference to set more baudrates, I've attached the FTDI Application Note PDF file that explain how to calculate the "value" of internal clock divisor.

As explained in the Application Note reference the FTDI driver has a function to pass just a baudrate and set automatically the divisor for any baudrate:
When using FTDI's D2XX direct driver the function FT_SetBaudRate can be used to set both standard and non-standard baudrates.

There is a possibility you change the library in future by adding this function (you can find on FTDI driver D2XX) so don't need to use Reflection?

Many thanks another time for your great support.
 

Attachments

  • AN232B-05_BaudRates.pdf
    168.8 KB · Views: 280
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I need to do this before or after I connect?
You need to call this code instead of setting the BaudRate property. After you initialize the object.

There is a possibility you change the library in future by adding this function (you can find on FTDI driver D2XX) so don't need to use Reflection?
There is nothing bad with this solution. It might be added in the future.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
I need to do this before or after I connect?

You need to call this code instead of setting the BaudRate property. After you initialize the object.

Ok, very good. As I supposed.

There is a possibility you change the library in future by adding this function (you can find on FTDI driver D2XX) so don't need to use Reflection?

There is nothing bad with this solution. It might be added in the future.

This is a great notice! I awaiting this!

Many thanks Erel
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Hi Erel,

I've tried it and works well on FTDI USB converter.;)

My calculation for 250000 bps is 3000000/250000 = 12

Now the problem is that only works on FTDI and no on others serial converters supported by the library.:(

Tried with CH340 using the NodeMCU for test, but as I supposed the CH340 class do not have the setControlCommand
method, the calculation for baud rate is not same, it has 2 divisors and because no setControlCommand return an error
while I try to connect.

This is a big problem because my app this way only support FTDI devices, no CH340, CP21xx etc...

There is a solution to do this and work on any serial converter supported by the felUsbSerial library?

Many thanks
 
Last edited:
Upvote 0
Top