I bought a Raspberry Pi to work together with my rooms moodlight. The current system uses an FTDI USB to RS485 converter cable with a full-blown linux PC pushing 1Mbps of data over that to drive the animations. I intended to replace that system with a Raspberry, seeing as it already has a UART on-board and would only need a small RS485 chip to drive the bus.
Unfortunately, out of the box the Raspberrys UART can only push 115200baud, and it spits out a shitload of debug data on the serial lines.
Here’s what I did to allow it to use the UART for other things, and to drive the UART at 1Mbps 🙂
The limiting factor on the UART speed is that UART Clock. It only allows baudrates of UART_CLK/16, and the clock is set to 3Mhz by default, limiting it to 187500baud. To drive 1Mbps, we need a UART-clock of at least 16Mhz. To do this we need to:
- Set configuration parameters in /boot/config.txt
init_uart_clock=16000000 - Update /boot/start.elf to the latest version. (The version shipped with Debian doesn’t support the init_uart_clock option)
- Compile a kernel that is aware of the new uart_clock.
Sources: https://github.com/raspberrypi/linux/
Line that needs changing: https://github.com/raspberrypi/linux/blob/rpi-patches/arch/arm/mach-bcm2708/bcm2708.c#L184
Recompiling: http://elinux.org/Rpi_kernel_compilation
This should then allow you to set the baudrate higher, to test run ‘sudo stty -F /dev/ttyAMA0 1000000’. If that runs without problems, it’s probably OK. You can test some more with ‘sudo bash’, and then ‘echo BOO > /dev/ttyAMA0’ and see if an attached FTDI device picks it up at 1Mbps.
Next up is making sure nothing else is using the serial line.
- Edit /boot/cmdline.txt and remove all options mentioning ttyAMA0.
- Edit /etc/inittab and comment out any lines mentioning ttyAMA0, especially the getty one. (source: http://baldwisdom.com/preparing-for-a-la-mode-raspberry-pi-and-arduino/)
Done! Now all that’s left is writing code to actually push something over that line and wire up a small rs485 chip 🙂
you talk about a line that needs to be changed:
https://github.com/raspberrypi/linux/blob/rpi-patches/arch/arm/mach-bcm2708/bcm2708.c#L184
How has this line to be changed? thank you very much in advance!
For those following… the link above points to the current version of bcm2708.c _NOT_ the version at time of posting. Code matching the post is here: https://github.com/raspberrypi/linux/blob/9efb470560c1507af609524f79b12fdf2b8ba30d/arch/arm/mach-bcm2708/bcm2708.c
As of _today_ the code in question is now at line 198
https://github.com/raspberrypi/linux/blob/822123d2cac563ce2f1e27ba7374ea4b43a621da/arch/arm/mach-bcm2708/bcm2708.c
and is now set to UART0_CLOCK
Thanks for the update!
Also, I’ve slightly modified your comment as the second link was broken up by a newline, the link should be properly clickable now 🙂
Have you tried the FTDI USB to RS485 with Raspberry and is it working OK? I need a way to drive RS485 from Raspberry Pi.
Thanks
I’m not 100% sure, I believe I did at some point test with the USB dongle and I believe it worked, but I do remember that in the end I opted for just a small 485 chip on the normal serial line instead, seeing as it was much(!!) cheaper and smaller 🙂
Follow-up:
I have been working with my RaspPi again with an FTDI dongle, and I’ve been experiencing some problems.
In general it works, but one of the three receivers I have malfunction when the “signal” is generated by the RPi over the FTDI dongle. I believe this might be caused by the RPi providing a too low USB voltage and the FTDI in turn not being able to properly sync to the baud-rate.
Seeing as the RPi features an on-board UART, I highly recommend using that one directly instead. Turning it to RS485 is as simple as putting something like an LTC485 inbetween, where you connect the TX pin to DI, RX to RO, and any other free GPIO pin to DE and RE to switch between sending and receiving (or hard-wire it to ground or 5V if you don’t need to switch).
Frans, are you ussing LTC485 5v ic directly with RPi 3v3 GPIOs?
Thanks
Yes, *BUT* I’m only using it to send data at this point, which works because 3.3v is higher than the on-threshold for the chip.
If you want to wire up the receiving end too you should either get a chip that works on 3.3v, or put a voltage divider between the RPi and the 485-transceiver.
FTDI adapter works ok, as long as you have latest kernel and usb set to 1.1 (dwc_otg.speed=1) , dont have my pi here.
Hey!
do you have an example code of the “code to actually push something over that line” ?
I have been banging my head on the keyboard after multiple tryouts to handle interrupts from the BCM2835 but I couldn’t get it to work … I could have used ‘echo … > /dev/ttyAMA0′ to send data but then how do you send the DMX break ? (I suppose you were doing DMX)
I have a FTDI chip over here but I would just really like to make it work any third-party hardware…
The protocol I’m using at this point to drive my LED-strips is one I made up myself, and doesn’t use any break signal.
However, I do think the normal Linux termios stuff should be able to handle DMX.
Have a look at this page about termios, specifically the tcsendbreak command.
Let me know if that helped you 🙂
EDIT:
Also this source code might help too. Search for “break_time_us” for the break stuff specifically, or just use that library to handle the DMX protocol for you 🙂
Some UARTS do not support break signals, or only breaks which are too short for DMX specs. If you’re having these troubles (don’t know much about the pi’s uart yet) you can always generate the break using a seperate GPIO pin, OR’d or ANDed with the TX line. Remember that the break will not get queued in the FIFO, so you have to make sure that all the buffered data has been sent out before generating the break. This probably must be observed even for a uart-generated break.
Thanks for this tutorial.
I have 2 questions :
– Today, is it still necessary to update start.elf ?
– Could you provide an 2Gb image with 1Mb serial link “ready to flash” ?
Thanks a lot.
I found that the rasperian wheezy image that I downloaded did not need a recompiled kernel or a new start.elf. I only needed to modify /boot/config.txt as shown above to run at 230.4 kbaud.
I downloaded the 2013-05-29-wheezy-armel.img image (it had the 3.6.11 kernel).
could you provide the image with 1Mb serial link “ready to flash” ?
mrshifo at libero.it
thanks
Do you know what is the maximum value for UART0_CLOCK?
I just spent an hour or so configuring my Macbook to compile the kernel and when I went to make the change to the file discovered that the file version was different and did not apply. I then thought: ‘maybe this change has already been rolled into the version of the kernel that I am running?’
I made the other changes including the start.elf file and now everything works. No need to make a new kernel.
Hello! I tried to do all that is described in this article. But it did not. Could you explain what I go wrong? I am new in Linux.
When i download kernel source:
git init
git clone –depth 1 git://github.com/raspberrypi/linux.git
I made these points.
When I tried to checkout:
git checkout rpi-3.2.27
I got an “error: pathpec ‘rpi-3.2.27’ did not match any file(s) known to git”
The next paragraphs i do without errors:
git init
git fetch git://github.com/raspberrypi/linux.git rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
git checkout rpi-3.6.y
git init
git fetch git://github.com/raspberrypi/linux.git rpi-3.8.y:refs/remotes/origin/rpi-3.8.y
git checkout rpi-3.8.y
KERNEL_SRC=/home/me/linux/
apt-get update
apt-get -y dist-upgrade
apt-get -y install gcc make
CCPREFIX=/home/me/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
Next i try to clean the kernel source from the kernel clone location with “make mrproper” and i get the error:
CLEAN .config
rm: cannot remove ‘.config’: Is a directory
( I do this command from /home/pi/ directory )
Where i am mistaken?
After that i do next paragraph, but i’m not sure what the correct item fulfilled:
“For those following… the link above points to the current version of bcm2708.c _NOT_ the version at time of posting. Code matching the post is here: https://github.com/raspberrypi/linux/blob/9efb470560c1507af609524f79b12fdf2b8ba30d/arch/arm/mach-bcm2708/bcm2708.c”
I download the bcm2708.c and repalce the file from directory:
/home/pi/arch/arm/mach-bcm2708/
Thanks for this – really essential information for using high rates, and I’ve not seen it anywhere else! The kernel change is no longer needed with the current (2014) raspbian kernel. As far as non-standard baud rates for DMX are concerned, it is possible but is tricky, see this post for some example code:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=72&t=33315&p=509730
Break signals are still to come!
Please ,
can someone help me via email ?
thanks
How all these configs could damage if I’m connecting other devices by serial (roboclaw 2xA: https://www.basicmicro.com/RoboClaw-2x15A-Motor-Controller_p_10.html) ?
“Set configuration parameters in /boot/config.txt:
init_uart_clock=16000000
sudo stty -F /dev/ttyAMA0 1000000
Edit /boot/cmdline.txt and remove all options mentioning ttyAMA0.
Edit /etc/inittab and comment out any lines mentioning ttyAMA0, especially the getty one.
Reboot”
So… writing this from the distant future… what speeds are supported out of the box in the year 2021?
+1 I am also interested what speeds are supported.