arduino / Arduino

Arduino IDE 1.x
https://www.arduino.cc/en/software
Other
14.16k stars 7.01k forks source link

[Ubuntu?] Serial baud 250000 not opened properly #3351

Closed NicoHood closed 8 years ago

NicoHood commented 9 years ago

As documentated and discussed here: https://github.com/urjaman/fast-usbserial/issues/1

If you open the Serial at baud 250000 it will open the Serial at the last selected baud instead. And thatswhy it doesnt work. This was tested on Ubuntu 14.04 x64 with IDE 1.6.5 release. It might be an OS issue due to a non standard baud. Or it is an IDE problem. Otherwise 250k could work. The program minicom can open it properly under Ubuntu. This was not tested on Windows. See discussion there for more information.

BrentWilkins commented 9 years ago

I didn't throw an oscope on the serial port, but if I select 250K baud in Serial.begin() & in the serial monitor, data passes just fine on the current version of OSX.

NicoHood commented 9 years ago

No, we are talking about the USB CDC Serial, not the Hardware Serial. Please read the Problem fully. The OS passes wrong parameters to the USB device so the USB device sets the USART wrong. And the wrong baud is the last selected baud. This bug happens with 250k, 500k, 1m and 2m. Possibly with any other non standard baudrate.

matthijskooijman commented 9 years ago

WIth USB CDC serial on the Leonardo, the selected baud rate shouldn't matter at all, it is not used. So I presume you mean CDC serial on the 16u2 on e.g. a Uno, which connects to the HardwareSerial on the 328 side. Assuming that @BrentWilkins was using a Uno or similar, his test confirmed that the entire stack supports 250k, from Serial monitor to HardwareSerial.

IIRC reliably selecting non-standard baudrates is a bit tricky on Linux, so it's likely that his works on OSX, but breaks on Linux.

I quickly tested this sketch:

void setup() {
  Serial.begin(250000);
  Serial.println("Hello, world!");
}

void loop() {
}

Opening the serial monitor at 250000 shows a bit of garbage, suggesting that indeed the serial port wasn't opened at 250kbaud at the PC side. This is probaly something that needs to be fixed in the Java serial library used (Can't remember if that's rxtx or jssc).

matthijskooijman commented 9 years ago

As for selecting non-standard baudrates, see this post:

http://marc.info/?l=linux-serial&m=143049135615695&w=2

(conclusion is that it sucks to set non-standard baudrates, but I think 250000 might be "standard enough" to work with the right prodding)

NicoHood commented 9 years ago

Well I added a function to my core which lets you return the value of the CDC baud setting. Depending on this setting the HW Serial1 is set. And because the PC opens the CDc Serial not at those non standard values and switches to the last selection or 9600 250000 doesnt work properly with the UNO and other Arduinos. The bridge (16u2) get a wrong USART setting and though the data is not transferred correctly. Not with the IDE at least. minicom works perfectly.

matthijskooijman commented 9 years ago

Looking at the JSSC code for setting baudrates, this is not a standard baud rate that can be set normally.

JSSC also contains some code for setting arbitrary custom baudrates, based on the ASYNC_SPD_CUST flag. However, as the mailing lis post linked above states, this is no supported by all drivers. In particular, the cdc_acm driver used by most Arduino boards does not support it (the ftdi_sio driver used by older boards with an FTDI chip does support it).

The mailing list post suggests using BOTHER to set custom baudrates, but there are some unanswered portability questions with it. Also, this requires modifying JSSC to use this other API.

I think that, within Arduino, the best we can do here is disable the 250000 baudrates on Linux (and perhaps others which are not part of the standard baudrates listed in JSSC / the Linux kernel). This means it will also be disabled on the FTDI-based boards, where it is technically supported.

An alternative (or actually, a good idea in any case) is to check the return value of setParams here (and probably also here). AFAICS, this should return false when the baudrate could not be set, allowing an error to be shown to the user instead of silently using the previous settings. This might actually be the best approach going forward.

NicoHood commented 9 years ago

Too bad. 2M would be so nice X_x A note would be nice, so people are not confused like I was. But there must be a way, I mean minicom can open the serial properly with ACM.

matthijskooijman commented 9 years ago

@NicoHood, 2M should be possible, since that is a standard baudrate in JSSC (and I think also supported by the kernel). Though there might be a different problem with such high speeds, I recall reading a mailing list thread or another bug report about that.

And indeed, minicom can do it, so I suppose that uses the BOTHER API, as I mentioned in my comment, which is not (currently) supported by JSSC.

NicoHood commented 9 years ago

I recently had a problem with another linux application. Maybe that can help a bit. It seems that only root users can open non standard baud rates. Meaning the dialout group is not enough maybe.

I do not know if the root user could open the port with that baud rate, but it had at least the privileges to do that. Meaning it wont work with a normal user and no special rights. Idk, maybe this helps a bit.

https://github.com/tvdzwan/hyperion/issues/351

matthijskooijman commented 9 years ago

Weird, I can't think of any reason why running as root would enable more custom baudrate options... Also, the report you link says that even though you didn't get an error as root, you also didn't get the requested baudrate, so I don't hink this is any help to us.

NicoHood commented 9 years ago

I dont know if I got the requested baud rate. I could not test it because the requested baud rate was wrong and out of sync with my Arduino. Even if it would set the rate correct I would not had a chance to check if its working correctly.

NicoHood commented 9 years ago

So I tested a few things...

I managed to get a 500k and 2M optiboot working on my Arduino Uno. This requires:

stty -F /dev/ttyACM1 2000000
AVRDUDECMD=avrdude -p m328p -P $(SERIAL_DEV) -b 2000000 -c arduino

This worked with 500k and 2M. These are baud rates I can also open with minicom. I cannot open 250k with minicom or use it as bootloader speed. So 250k needs some more stuff to implement. But maybe >500k, 1M and 2M can be patched. If a non standard baud rate is detected it could try the stty command. This way we could use faster bootloaders and also faster Serial Monitor rates. You should add a note that everything >115200 could cause problems on some systems.

NicoHood commented 9 years ago

Same problem for 74880 and maybe others as well. I was confused again. Totally kept me off from work. Not that this is a problem, its more that beginners will be confused as hell.

https://gist.github.com/NicoHood/7f2958b8d59cdc00ac4e

NicoHood commented 9 years ago

I tried this blindly myself now: https://github.com/NicoHood/Arduino/commit/3d418671eaf2b79dd1b231612d9aaeddf3f86a0f

The command cannot be executed for some reason. Manually entering the command works.

Uploading using selected port: /dev/ttyACM0
Test
stty -F /dev/ttyACM0 2000000 
java.io.IOException: Cannot run program "stty -F /dev/ttyACM0 2000000": error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    at java.lang.Runtime.exec(Runtime.java:620)
    at java.lang.Runtime.exec(Runtime.java:485)
    at processing.app.helpers.ProcessUtils.exec(ProcessUtils.java:11)
    at cc.arduino.packages.Uploader.executeUploadCommand(Uploader.java:115)
    at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:156)
    at processing.app.debug.Compiler.upload(Compiler.java:168)
    at processing.app.Sketch.upload(Sketch.java:1174)
    at processing.app.Sketch.exportApplet(Sketch.java:1148)
    at processing.app.Sketch.exportApplet(Sketch.java:1120)
    at processing.app.Editor$DefaultExportHandler.run(Editor.java:2421)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:248)
    at java.lang.ProcessImpl.start(ProcessImpl.java:134)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
    ... 11 more

Edit:

Runtime.getRuntime().exec("stty -F " + userSelectedUploadPort + " 2000000");

instead works. I can upload at 2M! I am not that java pro and I also compiled the IDE for the first time, but there should be a way to implement this better on linux. Should not be too hard.

Edit2: uploading 27kb program to the arduino takes about 1sec less with 2M compared to 115200. This had nothing to do with the issue directly, but a faster bootloader wont save much here since programming the flash cells itself takes too long.

matthijskooijman commented 9 years ago

I think in your original attempt, you should specify each part of the command (the command name and each argument) as a separate array element. This part is normally handled by a shell (which translates from a single string to a list of arguments by splitting on whitespace), which I suspect what the exec method you're using in the latter attempt also does.

matthijskooijman commented 8 years ago

I'm closing this issue as a duplicate of arduino/serial-monitor#33, which addresses this issue a bit more generically.