Cross coupling Raspis using serial?


8 posts
by zardoz99 » Fri Jun 22, 2012 6:03 pm
Is it possible to cross connect a couple of Raspberry Pi boards using the serial links from the GPIO header?

What I would like to do is allow each board to read a serial console data stream from its partner.
This is useful in a "headless" configuration, where there is no video device connected to display system errors that lead to a crash.

Would it just be a case of the following, without the requirement for buffering or level converters?
PI-1 PI-2
GND <----> GND
TX -------> RX
RX <------- TX

Ideas anyone?

Z
Posts: 157
Joined: Fri Jan 13, 2012 2:25 pm
by hippy » Fri Jun 22, 2012 7:21 pm
That's about it. It might be recommended to put in-line resistors (100R?) on each TX -> RX line because the voltages on each R-Pi may not be exactly the same or in case RX is inadvertently made an output pin, and it might be a good idea to add pull-ups (10K?) so there aren't any problems when disconnected.

Code: Select all
        ___                         ___
3V3 ---|___|---.               .---|___|--- 3V3
        ___    |               |    ___
RX <---|___|---^---< <---. .---^---|___|---> RX
                          X
TX >---------------> >---' `---------------< TX

0V ----------------> >---------------------- 0V
Posts: 820
Joined: Fri Sep 09, 2011 10:34 pm
by AndrewS » Sat Jun 23, 2012 11:40 pm
And don't forget to edit /boot/cmdline.txt and /etc/inittab to turn off all the bootup messages, otherwise the Raspi's will end up getting very confused ;)
User avatar
Posts: 3626
Joined: Sun Apr 22, 2012 4:50 pm
Location: Cambridge, UK
by zardoz99 » Sun Jun 24, 2012 9:55 am
Actually, the boot messages would be very useful to have. I am used to using IPMI "Serial-over-Lan" connections that allow exactly that. This enables you to see exactly what stops a headless HPC node from booting properly, especially as they almost never have any graphics card interface.

Z.
Posts: 157
Joined: Fri Jan 13, 2012 2:25 pm
by AndrewS » Sun Jun 24, 2012 10:40 am
Well, at the very least you need to disable the serial getty in /etc/inittab - otherwise the bootlog output from one Rpi will be attempting to "log in" to the other Rpi's serial console.
User avatar
Posts: 3626
Joined: Sun Apr 22, 2012 4:50 pm
Location: Cambridge, UK
by speculatrix » Mon Jun 25, 2012 8:02 pm
I'm doing something very similar to this, connecting an RPi to a BeagleBone. I'm also connecting the BB to an Arduino this way and maybe the RPi to an Arduino. It's a festival of serial. And it's working fine.

I'm running Debian on the RPi. (And Ubuntu on the BB, since you asked).

On the RPi, I edited /boot/cmdline.txt to remove the two references to /dev/ttyAMA0, and I commented out the line also referring that port in /etc/inittab.

Because I use Python, I hacked together a quick class to handle serial. It's very basic and I am not a programmer, so treat with caution/fear/disdain. It's also a work in progress - plenty to do yet. No use of RTS/CTS, for example. And it's geared entirely to my needs - so, for example, all messages sent are terminated by a newline.

Code: Select all
from serial import *
import time

class CommPort:
   '''
   commPort class
   '''
   def __init__(self, baud=19200, sendInit=False, bytesize=EIGHTBITS):
      self.dev = '/dev/ttyAMA0'
      self.baudRate = baud         # default
      self.byteSize = bytesize
      self.parity   = PARITY_NONE      # this is pySerial default anyway
      self.stopBits = STOPBITS_ONE   # also pySerial default
      self.timeOut = 3
      self.message = ''
      try:
         self.serPort = Serial(self.dev,
               baudrate = self.baudRate,
               parity = self.parity,
               bytesize = self.byteSize,
               stopbits = self.stopBits,
               timeout=0.1,
               xonxoff=0,
               rtscts=0,
               interCharTimeout=None)
         self.serPort.flushOutput()
         self.serPort.flushInput()
      except serial.serialutil.SerialException as e:
         print(e)
         exit()

      if sendInit:
         # Opening a serial connection to an Arduino can cause it to
         # reset, so let's send it an init message then give it a moment
         # to get its act together
         self.send('++INIT++')
         time.sleep(2)
         self.serPort.flushOutput()
         self.serPort.flushInput()

   def send(self, sendStr):
      '''
      Send a message. A newline is appended, so don't need to include
      that in the string.
      '''
      sendStr = sendStr.strip()      # clean it up first
      sendStr = sendStr + '\n'
      self.serPort.write(sendStr.encode('utf-8', 'replace'))
      return

   def newMsgs(self):
      '''
      newMsgs() - obtain list of incoming messages. Assumes each message
      is terminated by newline & is utf-8 encoded.
      Dodgy bytes are treated using the .replace() method which does
      standard replacing according to codec. This avoids the program falling
      over should a bad byte appear that the utf-8 codec can't handle. But
      might be better to do some error handling here - maybe some basic
      flow control to request resending of message
      '''
      msgList = []
      while self.serPort.inWaiting() > 0:
         # using readline could create a problem where data has been sent
         # but isn't terminated by a newline. In this case, the while above
         # would cause this program to wait forever. For time being that's tolerable
         # because we'll be strict about always using a newline
         msgList.append(self.serPort.readline().decode('utf-8', 'replace').strip())
      return msgList

   def __str__(self):
      '''
      Print information about this port
      '''
      print('COMM PORT', self.dev,'-',
         str(self.baudRate) + ' baud', str(self.byteSize) + '-' + self.parity + '-' + str(self.stopBits))
      return ' '
User avatar
Posts: 48
Joined: Thu Apr 05, 2012 8:29 am
Location: France
by AndrewS » Tue Jun 26, 2012 8:31 am
speculatrix wrote:I'm doing something very similar to this, connecting an RPi to a BeagleBone. I'm also connecting the BB to an Arduino this way and maybe the RPi to an Arduino. It's a festival of serial. And it's working fine.

Of course it does - absolutely no reason it wouldn't as long as you get your voltages correct (using a converter where appropriate), get your RX and TX the right way round, and set matching baudrates.
Just for kicks, I've also had my RPi "talking to itself" by connecting a USB->3v3 UART adaptor to both the Pi's USB port and its GPIO UART pins. Using 'picocom -b 115200 /dev/ttyUSB0' I was able to then "log in again" on the RPi's serial console :D
User avatar
Posts: 3626
Joined: Sun Apr 22, 2012 4:50 pm
Location: Cambridge, UK
by speculatrix » Tue Jun 26, 2012 8:46 am
AndrewS wrote:as long as you get your voltages correct (using a converter where appropriate)


I'm using level shifters between the BeagleBone & the Arduino. Also using the same level shifters when using the BB to work with 5V I2C devices. The ones I'm using are Adafruit's (I love that company): http://www.adafruit.com/products/757.
User avatar
Posts: 48
Joined: Thu Apr 05, 2012 8:29 am
Location: France