Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The reason why 250000 baud is so problematic in Linux... #205

Closed
thantik opened this issue Jul 25, 2012 · 22 comments
Closed

The reason why 250000 baud is so problematic in Linux... #205

thantik opened this issue Jul 25, 2012 · 22 comments

Comments

@thantik
Copy link

thantik commented Jul 25, 2012

250000 baud is not a standard baud rate. Instead of having to recompile things, or go through these configuration changes trying to get a non-standard baud rate to work, the baud in marlin needs to be 230400. Setting it to that made all my linux machines work magically. This needs to be the default baud rate in marlin instead of 250000.

@daid
Copy link
Contributor

daid commented Jul 25, 2012

No it doesn't. There is a good reason why 250000 is used, as it has a much lower bit error rate then 230400. On 16Mhz Arduinos.

As you need you configure the firmware anyhow when you build it, so you can configure the baudrate yourself. Or use the Marlin builder: http://daid.mine.nu/~daid/marlin_build/

What really should be done is fixing PySerial so it uses "termios2" and TCSETS2, which is the new kernel interface to set custom baudrates and makes 250000 work under linux. Also, it depends on your distro if 250000 works, because in Fedora it seems to work fine, while Ubuntu fails to use 250000.

(A comment could be added at the baudrate setting that the 250000 default has some troubles under Linux)

@thantik
Copy link
Author

thantik commented Jul 25, 2012

The reason why it has a lower bit error rate and less jitter is purely because it's a faster speed. There are standards for a reason. 250,000 baud is not standard. Nowhere in any documentation anywhere does anyone mention 230400 vs 250000. Yet, 230400 works with current, unaltered software, 250000 does not.

@daid
Copy link
Contributor

daid commented Jul 25, 2012

The reason why it has a lower error rate is because the divider of the UART of the AVR used in the Arduino can create 250000 without an error, while 230400 has a 3.5% error in clock.

So how is a datasheet for documentation for you?

ATMega2560 datasheet page 231. Table 21-12: fosc = 16.0000 MHz
Baudrate - Error
230.4K: -3.5%
250.0K: 0.0%
(And this is assuming the Arduino software is smart enough to use the U2X bit, else the error increases to 8.5%)

Also, experiments on the Ultimaker have shown that 250000 gives less errors.

@ijackson
Copy link
Contributor

ijackson commented Aug 4, 2012

I think Linux systems are making this unnecessarily difficult TBH and I consider this a bug. The kernel seems to have supported nonstandard baud rates since 2006 or so but the libc is getting in the way.

I have filed a bug against the distro I use, Debian, here:
bugs.debian.org/683826
In practice I think it will be difficult to fix this in reprap host software that's not written in C/C++ until the underlying layers are fixed.

So in the meantime I would recommend that Linux users use a standard baud rate.

@daid
Copy link
Contributor

daid commented Aug 4, 2012

Not sure if you intended to reply to github, or directly to me. But you
replied to me.

Good to see that you filed a bug at debian. I'm simply too busy to pull
this bug to attention myself. If you do want to try to squish this bug in
all possible ways, I have some C code at work that can configure serial
ports on custom baudrates for different kernel versions. I can share this
code.

(Small side note, my Cura software package installs a default baudrate
firmware on an Ultimaker if it's run for under Linux, to avoid this problem)

On Sat, Aug 4, 2012 at 3:55 PM, Ian Jackson <
reply@reply.github.com

wrote:

I think Linux systems are making this unnecessarily difficult TBH and I
consider this a bug. The kernel seems to have supported nonstandard baud
rates since 2006 or so but the libc is getting in the way.

I have filed a bug against the distro I use, Debian, here:
bugs.debian.org/683826
In practice I think it will be difficult to fix this in reprap host
software that's not written in C/C++ until the underlying layers are fixed.

So in the meantime I would recommend that Linux users use a standard baud
rate.


Reply to this email directly or view it on GitHub:
https://github.com/ErikZalm/Marlin/issues/205#issuecomment-7501930

@nothinman
Copy link
Contributor

A quick thought on the subject. Any reason why people aren't using say 1Mb/1.25Mb instead of 115k/250k? My atmega1284p supports it, and ft232 supports it...

@daid
Copy link
Contributor

daid commented Sep 17, 2012

The ArduinoMega2560 doesn't use the TFDI chip, but an ATMega8U, which most likely also support it. However, the higher the bitrates, the higher the chance some random EMI disrupts a bit. And you'll get the same software support issues as 250k, and you'll most likely run into the low speed USB limits.

@nothinman
Copy link
Contributor

@daid Well, not true. I've been happily using 1Mb serial since I posted (a month ago) and everything works fine. AVRs support it, and my FTDI chip supports it too. It's USB full speed, so it's 12Mb. Even if it was low speed, it would be 1.5Mb. There's no slower USB.
In regards to the EMI, etc -- 1Mb is not fast. I consider it very slow. There are no problems with EMI, etc. Chip is a UART to USB transceiver and it does all the filtering magic for you. It just works.
I'm also not sure why are people having trouble with "non-standard" baud rates on linux. It's working fine for me on Ubuntu and Windows. I would consider it a driver issue rather than a kernel bug. But I can be wrong on this one.

@thantik Standards were there for a reason. The reason was simple -- even clock division. And by having both devices using defined speed you could always guarantee communication.
But if you set UART on AVR to 1Mb and you transceiver to 1Mb, it will work nicely. If you set both sides to 219kbit it will also work nicely. FTDI chip does all the conversion, because USB, regardless of your UART speed, will always be running at 12Mbps.

Marcin

@daid
Copy link
Contributor

daid commented Oct 31, 2012

@nothinman: The ArduinoMega2560 R2 or R3 doesn't have an FTDI chip but an ATMega8U doing the USB-Serial.
Also, USB has considerable overhead when doing USB-Serial, so you cannot convert USB speeds directly to serial speeds.
1MBit is fast for boards and cables not designed for it. Especially in a noisy environment with the steppers in a RepRap.

The reason people have trouble with none-standard baudrates on Linux is because the kernel developers created 2 different interfaces to set none-standard baudrates and not all drivers/kernel version support both, and not all serial libraries support both. In this case, PySerial does not support Termios2.

@nothinman
Copy link
Contributor

@daid: I understand some don't use FTDI transceiver. For those it may not work indeed.
There's no cables. RXD and TXD from AVR is connected on PCB to FTDI chip. The only cable is the USB cable.
Overhead is meaningless here, because USB is much faster than the serial speeds AVR/FTDI support...

Appreciate the comment regarding the kernel. Wasn't aware of it. One could write a software-based serial driver based on timer interrupts and could therefore use any baud rate.
Well, I'm happy mine works. I suggest people get FTDI chips :-)

@toybuilder
Copy link

I'm not sure that I'd worry about the <4% error -- unless the UART state machine is poorly designed, it should be able to handle framing drifts by aligning to the Stop/Start bit transition.

Keep in mind that UART's are designed to drift. Oscillators on different machines can easily vary by several 100s of ppm, and since the machines aren't clock-sync'ed, You will eventually have a misalignment if that framing logic was not in place.

Reading a really old datasheet from the 1980's or before on the 8250 describing the state machine and how it oversamples the input to align the link to framing drift would probably be very instructive. IIRC, I think it was an 8x or 16x oversampling. So I would expect that a rate difference up to 6% wouldn't matter. I would expect other UART designs to be comparable.

In fact, a quick look at StackOverflow more-or-less confirms what I just said: http://electronics.stackexchange.com/questions/7610/what-is-the-maximum-acceptable-baud-rate-error-for-rs-232-serial-communication

@ErikZalm
Copy link
Contributor

@toybuilder You theory is ok. But with 250000 I get no communication errors. And with 115200 I get errors. The print will not stop. But you can see some artifacts in your printed object.

@toybuilder
Copy link

Do the errors appear as framing errors? Or is the problem caused by underruns from not feeding the controller fast enough with additional Gcode data? If there's actual line corruption from the rate mismatch, you would expect the print to come out plainly wrong, as swaths of gcode would get mangled.

I apologize that I haven't dug into the source code to see what's going on under the hood on the Arduino side of the equation.

230.4K seems to be a widely supported "standard" bit rate, and close to 250K, so that one expects less problems running at that speed. I guess the bigger question is how well the USB->Serial converter is honoring the speed selection.

What would be helpful is if there was a way to be able to select the comm speed through a manual switch of some kind -- I know, jumpers are so last century, but it could be a simple solution to this problem.

@whosawhatsis
Copy link
Contributor

It seems like auto-discovery should be possible. What if the firmware and host agreed to first attempt to connect at some very common bitrate, say 9600, sent a list of their acceptable baud rates, and then disconnected and reconnected at the highest rate on both lists.

To make the transition easier, you could add an M code to Marlin that would list acceptable baud rates and another that would cause it to disconnect and restart its serial at a specified baud rate, then host support would be optional. Since 115200 seems to be pretty universally supported (it's the highest rate allowed by the serial terminal in the Arduino IDE, and the highest rate aside from 250000 listed in pronterface's dropdown), that should probably be the default, but the addition of these M codes would allow the host to renegotiate the baud rate after connecting at 115200.

@daid
Copy link
Contributor

daid commented Feb 18, 2013

I've had baudrate discovery in Cura for more then half a year now. Didn't even require cooperation from the firmware. But a command to set the baudrate would be useful in any case.

@whosawhatsis
Copy link
Contributor

That's cool, but it doesn't help if the problem is that the host system isn't compatible with the baudrate set in the firmware. One side really has to be able to get a list of the other's acceptable baud rates and choose the highest one that matches its own list, then get the other to change baudrates with it.

Thinking about it a bit more, it could really be done with only one M code. With no arguments, the code causes the firmware to echo a list of its available baud rates, and the same code followed by S250000 would trigger a switch to that baudrate.

@daid
Copy link
Contributor

daid commented Feb 18, 2013

The firmware doesn't care much for which baudrate you use, it can set the baudrate to any value you want, but some will be more accurate then others. The whole baudrate issue is 2 fold. First, not every hardware design handles noise pretty well, and thus some baudrates cause issues on a hardware level. Secondly, Linux. The kernel developers added a nice interface for setting custom baudrates (with TCSET2), however, for some reason this is hardly anywhere exposed by the kernel-header packages in common distributions, so pyserial also didn't pick up on it. This interface is nothing new, and was introduced a few years ago.

@toybuilder
Copy link

Perhaps a better way to handshake in "fall back mode" is to use a combination of hardware handshake lines and a line break while turning on/resetting the controller...

@daid
Copy link
Contributor

daid commented Feb 18, 2013

The handshake lines do not reach the controller and are stopped at the USB interface. So no use there.

@hgroover
Copy link

Looks like the issue of using termios2 in PySerial for custom bitrates was recently addressed:
http://sourceforge.net/p/pyserial/patches/28/

On Ubuntu 12.04 I was able to just replace the distro's pyserial by building from source:
(apt-get install subversion, all the python setup prerequisites covered setting up printrun, skeinforge et al)
svn checkout svn://svn.code.sf.net/p/pyserial/code/trunk pyserial-code
cd pyserial-code
wget -O pyserial.patch http://sourceforge.net/p/pyserial/patches/_discuss/thread/ed3fb0de/f4fd/attachment/pyserial.patch
patch -p0 < pyserial.patch
cd pyserial
python setup.py build
sudo python setup.py install

I've verified this works with the pronterface gui.

@daid
Copy link
Contributor

daid commented Aug 22, 2013

Note that that pyserial patch breaks backwards compatibility and thus won't be accepted by the maintainer. Real shame.

I just added this patch to Cura, which I hope solves the issue for Cura:
daid/Cura@28efc5a
I would rather see it solved in pyserial. But after half a year I don't see the patch being included in pyserial any time soon.

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants