Configuring UART
Verify physical UART is enabled in /boot/config.txt
enable_uart=1
Configure clock and speed where necessary in /boot/config.txt
init_uart_clock=1627604 init_uart_baud=460800
Serial Aliases On the Raspberry Pi 3 the second serial port is called /dev/ttyS0 and is by default mapped to the GPIO pins 14 and 15. So immediately, if you have code that references /dev/ttyAMA0 you’re going to have problems and things aren’t going to work.
You could go through your code and replace ttyAMA0 with ttyS0 and that should work. However, if you find yourself use the same SD card on a Raspberry Pi other than a rpi3 your code won’t work again.
In order to try and get around this the Foundation have introduced a serial port alias (as of May 2016 – 2016-05-10). Thus you have serial ports: serial0 and serial1 (rpi3). The Raspberry Pi kernel sorts out where these point to depending on which Raspberry Pi you are on. Thus on a Raspberry Pi 3 serial0 will point to GPIO pins 14 and 15 and use the “mini-uart” aka /dev/ttyS0. On other Raspberry Pi’s it will point to the hardware UART and /dev/ttyAMA0.
Default Raspberry PI 3 serial port aliases
Serial0 -> ttyS0 Serial1 -> ttyAMA0
Default Raspberry PI 2 serial port aliases
Serial0 -> ttyAMA0
So where possible refer to the serial port via it’s alias of “serial0” and your code should work on both Raspberry Pi 3 and other Raspberry Pi’s.
Disabling the Console
If you are using the serial port for anything other than the console you need to disable it. This will be slightly different depending on whether you are running a Raspberry Pi 3 or not.
For non Raspberry Pi 3 machines, remember it’s /dev/ttyAMA0 that is linked to the getty (console) service. So you need to perform this command from a terminal window:
sudo systemctl stop serial-getty@ttyAMA0 service sudo systemctl disable serial-getty@ttyAMA0 service
The “disable” will stop it loading in the future.
For Raspberry Pi 3’s the command is similar but referencing /dev/ttyS0:
sudo systemctl stop serial-getty@ttyS0 service sudo systemctl disable serial-getty@ttyS0 service
You also need to remove the console from the cmdline.txt. If you edit this with:
Remove the line: console=serial0,115200 and save and reboot for changes to take effect.
Swapping the Serial Ports on Raspberry Pi 3
What if you don’t want to use the Bluetooth and you want that high performance /dev/ttyAMA0 back on the GPIO? Well you can do this and the way you do this is via a device overlay called “pi3-miniuart-bt” i.e. use the mini-uart (/dev/ttyS0) for Bluetooth (you may get some loss of performance on your Bluetooth though).
You can also just disable the Bluetooth all together by using another overlay “pi3-disable-bt”. In both cases if you can find out more of what they do here: /boot/overlays/README
To use add the following line to the /boot/config.txt
dtoverlay=pi3-miniuart-bt
RPI UART Speeds
/boot/config.txt init_uart_clock=64000000 (up to 16 x 4.000.000)
The standard baud rates double in speed, from 115200 to 230400, then 460800, then 921600.
After that, it follows subdivisions of 3,000,000, so the next would be 1,000,000, then 1,500,000, 2,000,000, etc.
460800 (57.6 kB/s):
Average frequency 229.7 kHz, 1 MB would take 17 seconds.
921600 (115.2 kB/s):
Average frequency 459.3 kHz, 1 MB would take 8.6 seconds.
1,000,000 (125 kB/s):
Average frequency 500 kHz, 1 MB would take 8.0 seconds.
1,500,000 (187.5 kB/s):
Average frequency 750 kHz, 1 MB would take 5.3 seconds.
2,000,000 (250 kB/s):
Average frequency 1 MHz, 1 MB would take 4 seconds. Getting faster with 222.2 thousand characters sent per second!
2,500,000 (312.5 kB/s):
Average frequency 1.263 MHz, 1 MB would take 3.2 seconds. Nearly 300k characters per second!
3,000,000 (375 kB/s):
Flippin heck, average frequency 1.5 MHz, 1MB would take 2.6 seconds.
3,500,000 (437.5 kB/s):
Jeeeeez, average frequency 1.745 MHz, 1MB would take 2.3 seconds. Just shy of 400k characters per second!
4,000,000 (500 kB/s):
Okay, 2 MHz average frequency, 1MB would take 2 seconds, and over 444k characters per second!
However, there’s a snag at these speeds:
As you can see, the UART stutters and causes gaps to appear. This may be an issue if you have equipment sensitive to this effect. This was the highest I was able to set the UART speed to, anything higher refused to work.
Looking back, I found that 2,000,000 baud was quite stable, but I could trigger off gaps above 1 microsecond once every so often, so it still exhibits some instability. 1,500,000 proved to be almost rock-solid, taking a really long time until a gap 100 nanoseconds longer than the waveform period. 1,000,000 was perfect though, with no gaps seen at all!
So for pure data transfer, crank it all the way up to 4,000,000. If you need stability though, don’t go above 1,000,000!
pySerial: how to check the current baud rate
bash
stty < /dev/ttyAMA0 speed 57600 bud; line = 0
python
ser = serial.Serial('/dev/ttyAMA0') ser.timeout = 0.5 for baudrate in ser.BAUDRATES: if 9600 <= baudrate <= 115200: ser.baudrate = baudrate ser.write(packet) resp = ser.read() if resp != '': break if ser.baudrate > 115200: raise RuntimeError("Couldn't find appropriate baud rate!")
How to set non standard serial port speed
The clock speed of the serial port is 3000000Hz (3MHz).
We can UNDERclock this (as low as 1MHz), but we cannot OVERclock it (with any confidence).
So we will pick the Baud Rate one-above the speed you want and slow it down...
The next speed up from 250000 is 460800
Now a bit of maths:
(NormalClockSpeed / NormalBaud) * DesiredBaud => NewClockSpeed ...where NormalBaud > DesiredBaud (3000000 / 460800) * 250000 = 1627604
Quick maths sanity-check: 250,000 is a bit more than half of 460,800 ...and 1,627,604 is a bit more than half of 3,000,000 ...yep that looks right :)
So if we reduce the serial clock speed to 1627604 and then specify a serial port speed of 460800, the upshot will be a serial port that runs at 250000.
You can even do the maths backwards to double check things:
(NewClockSpeed * NormalBaud) / NormalClockSpeed => ResultantBaud (1627604 * 460800) / 3000000 = 249,999.97
249,999.97 is uncommonly accurate, you can get away with a lot more deviation than that! [citation required]
So we edit /boot/config.txt; Set the serial clock speed to 1627604; And the Baud Rate to 460800
init_uart_clock=1627604 init_uart_baud=460800
Bingo. /dev/ttyS0 is running at 250KBaud