Thursday, April 10, 2014

DMX driver for Raspberry Pi - Getting Baud.


DMX on a Raspberry Pi - Getting Baud.

Note the main article is here:

Note that the modifications below are based on the 3.10 version of rapsbian (wheezy).
There are some NOTES for 3.12.

cat /proc/version

Linux version 3.10.25+ (dc4@dc4-arm-01) (gcc version 4.7.2 20120731 (prerelease) (crosstool-NG linaro-1.13.1+bzr2458 - Linaro GCC 2012.08) ) #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014

Baud Rate

The first thing to do is to modify the driver to support the DMX baud rate, which is 250,000 baud. Typically the easiest way to do this is to download the source to the driver and build it. As the standard raspbian image doesn’t contain the files to do this, this can be tricky and you can take up quite a bit of time attempting to set up your environment and even more time attempting to build. (One post states to “go and make some coffee” while waiting. For me it should have said “go build a house”)  The good news is that this inspired me to cheat a bit and patch the driver by hand. This really isn’t recommended, so feel some guilty pleasure when you’re doing this.

A look at the source for the pl2303 driver shows the bauds that are supported.

const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
                                 4800, 7200, 9600, 14400, 19200, 28800, 38400,
                                 57600, 115200, 230400, 460800, 614400,
                                 921600, 1228800, 2457600, 3000000, 6000000 };


You’ll see that 250000 isn’t one of them. But there is 230400. That’s pretty close. (But not close enough).  The logical thing to do would be to patch that to 250000 and use ‘stty –F /dev/ttyUSB0 250000’ to set the baud. The problem is that Linux (to some extent) has some pre-conceived notions about what allowable baud rates are.

stty -F /dev/ttyUSB0 250000

stty: invalid argument `250000'

 The driver has a section where is will “Set baud rate to nearest supported value”. If we change the “230400” baud to 2500000 and try and set 230400 baud, we actually end up with 115200 baud, which means that the driver is rounding down when it comes to the nearest speed. This means that we need to find a valid baud rate above 250000 that the driver can round down to.

NOTE: The driver for 3.12.22+ has changed/fixed the "nearest supported" algorithm. In order for this patch to work, multiple speed values need to be changed. This is called out below.

The driver is here:
/lib/modules/3.10.25+/kernel/drivers/usb/serial

(or here for 3.12.22+: /lib/modules/3.12.22+/kernel/drivers/usb/serial)

First unload the driver (which will be loaded if you have a pl2303 device installed, such as the USB-RS485 device.)

                rmmod  pl2303

Then make a backup:

                cp  pl2303.ko  pl2303.ko.orig

convert the driver to hex – so you can edit it:

                xxd  pl2303.ko  >pl2303.hex

Now we need to grep for the baud rates. The baud rates that we are looking for are the 230400, 460800 ones (These are from the driver source shown above, I’m not just making numbers up). 230400 = 38400 hex and 460800 = 70800 hex. Let’s grep for that

                cat pl2303.hex |grep 03|grep 84|grep 00|grep 07|grep 08|grep 00

                0001380: 0084 0300 0008 0700 0060 0900 0010 0e00  .........`......

The nice thing is that they’re all on the same line so the grep finds them – if some of the bytes were on the line above/below, then we’d have to grep a bit more cunningly (grep -A1, -B1)

Because of the endian ness of the processor, everything is slightly backwards, but that’s OK. You can see the 00038400 followed by 00070800. You can also see 0096000, which you can see is the 614400 baud rate in the driver.

                echo $(( 0x0096000 ))

So, now we need to edit the driver.

                vi pl2303.hex

                /0001380: (this finds the “0001380” in the hex file – this is from the first part of the grep results above) (NOTE: For 3.12.22+, the location is /00013d0)

Now we need to carefully edit the values. We want to edit the baud rate for 460800  to be 250000.  (that is we need to change the hex  07 08 00 to the hex for 250000 which is 03 D0 90.

Before: 0001380: 0084 0300 0008 0700 0060 0900 0010 0e00  .........`......

The results of your efforts should look like this (based on the line above. If your grep results were different, then your results will differ)

After:    0001380: 0084 0300 90d0 0300 0060 0900 0010 0e00  .........`.....
NOTE: for the 3.12.22+ version, the line needs to look like this:

After: 00013d0: 0084 0300 90d0 0300 90d0 0300 90d0 0300

Now, we need to create the new driver from the hex file.

                xxd -r pl2303.hex >pl2303.ko

load the new module:

                insmod pl2303.ko

                If your system dies spectacularly at this time, then you’ve probably gone astray. You should remove the serial device and reboot your system. Copy the original driver back into place and try again.

                Set the baud rate to 500000, note that the driver doesn’t support this, and will set it to 250000. As 250000 is not understood by linux, you’ll still get an error message:

stty -F /dev/ttyUSB0 500000

stty: /dev/ttyUSB0: unable to perform all requested operations

And even trying to check the speed will not clear things up:

                stty -F /dev/ttyUSB0

speed 0 baud; line = 0;

You’ll have to trust that the baud rate is correct at this time. (or, if you’ve bought two RS485 convertors (and why would you not, these things need friends too) then you can connect it to a Windows laptop and use Putty to connect at 250000, you should be able to “echo HELLO >/dev/ttyUSB0” and see “HELLO” appear on putty.)

So, now you’re able to get to the correct baud, you’re now going to need to send DMX packets to your DMX devices. That’s in the next post.

No comments:

Post a Comment