Some years ago (back in the early 1990's !) I
bought a serial to digital input/output converter module to experiment with
connecting things to my computer(s). This module was sold by Maplin, made by
R.M.Electronics and was named the
RM9011. As with many things I've tried in the past, I can't recall having much
success using it with a range of computers I owned, these being the Dragon 32,
Atari ST, finally migrating to the PC running Windows 95. So it was put away
for a future project...
With the arrival of the Raspberry Pi my interest
in interfacing with technology and sensors has been rekindled. So digging out
the RM9011 I have spent a happy few hours figuring out how to interface this
with the Raspberry Pi using some discreet logic circuitry and using a serial
console (minicom) to configure and test different scenarios with sensors and
LEDs. Using Python I've also coded some
scripts to run various monitoring and output scenarios. As this module is way
out of date, considered legacy and I've not been able to find spares or
originals I have decided not to use it for any serious projects. However, for
completeness for this article I've included a description of the module, an
image of the board together with the circuit diagram (courtesy of Maplin
magazine - January 1992).
RM9011 -
description
RS232 to 8-bit digital I/O converter module -
introduced in 1992 by Maplin Electronics, made by R.M.Electronics.
Features:
Each input/output line individually configurable
as input or output.
Bit or byte read and write.
Configuration changes made via RS232 / Serial
interface maximum speed 1200bps.
5V DC supply.
I/O Lines TTL / CMOS compatible.
On-board CMOS controller (pre-programmed).
An image of the board and circuit diagram is below:
RM9011 board by R.M.Electronics |
RM9011 circuit diagram |
While searching on-line for information on serial
to digital converters to take the place of the RM9011 I found this device - the
DACIO300.
The DACIO300 by Tronisoft in many ways has some similarities to the RM9011, though much more advanced and more importantly
still available to purchase. The way it is controlled is also similar to the
RM9011, in that ASCII characters are sent to the interface board via
RS232/Serial. This method of operating lends itself to being controlled
directly from a serial console, such as minicom on the Raspberry Pi, or from
the Raspberry Pi using Python serial commands or Arduino using serial print
commands.
This board is fully populated but it is possible
to buy this unpopulated and exclude many of the components from the board
depending on how it might be used. It is also possible to buy just the
pre-programmed chip to build your own project(s).
DACIO300 - Specification
The DACIO 300 series modules are powerful, ultra low power consumption, microcontroller (MCU) based PC interfacing RS232 IO boards.
A single RS232 IO board provides two 8-bit digital input/output ports and up to 8 analogue input channels to computers equipped with a spare RS232 COM port or via a USB to serial converter such as item 2455 or 2327.
Each I/O is individually configurable.
The DACIO 300 features 8 10-bit A/D and a high speed 115.2kbps serial interface.
Easy to use communication and control open protocol.
Details about the RS-232 standard are available and provides useful information about remote operating distances.
Raspberry Pi
- DACIO300 interface
Connecting the Raspberry Pi to the DACIO300 is
relatively straightforward. The serial transmit output from the RPi
is connected to the serial receive input on the DACIO300, and the serial
transmit from the DACIO300 is connected to the serial receive input on the RPi. There should be no direct connections between the two devices as the RPi
operates at 3.3v while the DACIO300 operates at 5v. It is necessary to provide
an interfacing circuit between the two as shown below.
This simple interface allows the Raspberry Pi
serial transmit port operating at 3.3v to connect via one hex buffer of the
HCF4050 IC and connect to the DACIO300 serial receive port operating at 5v. In
the reverse direction, the 5v serial transmit from the DACIO300 is stepped down
to 3.3v (though not absolutely necessary) via R1 & R2 to drive another hex buffer whose output connects to
the Raspberry Pi serial receive port. The HCF4050 is powered at 3.3v with pin
1 +Vdd and pin 8 Ov or Vss. I have also used an Arduino clone (RasPi.TV Duino) in the same way to successfully interface with the DACIO300.
Simple 3.3v to 5v interface (Raspberry Pi to DACIO300) |
Example input / outputs
Here are a few simple examples of how the DACIO300 inputs and
outputs could be used.
Port A comprises 8 bits, channels 0 - 7 and is by
default an analogue input port.
Ports B and C are both 8 bits, channels 0 - 7
digital ports, Port B by default is set as inputs and Port C as outputs. Both
Ports B and C are configurable at bit/channel level and can be either inputs or
outputs.
Simple input and outputs |
The commands to interact with the DACIO300 are
straightforward and comprise a string of ascii characters forming a command.
Each command has a start character either ! or #
Characters to issue a command; typically comprising
the Port name, an operator (e.g. '=' to write, '?' to read), a character if needed to provide an input
parameter and an end character ';'
If a valid command is received, the module returns
a '!' followed by any data requested.
Examples:
!C=255;
This command is instructing the module that Port C
has a decimal byte value of 255 written to it.
!Bx?;
This command reads bit x (0-7) from Port B, where
the reply is !x<0D> where x is 1 or 0 and 0D is a carriage return
character.
!B?;
This command reads the whole of Port B and returns
a decimal byte value.
!Ax?;
This command reads Port A, bit x and returns a
reply !xxxx<0D> where xxxx is 0000-1023
Further details are provided in the DACIO300 manual to
translate the numeric reading to a voltage level.
Many other commands can be sent to the module to
set Ports as inputs or outputs, to read ports at a bit or byte level, to write
out data to the digital ports at bit or byte levels, and to read the analogue
port values.
Full details and instructions are detailed in the
DACIO300 manual which is a very clear useful guide.
I have experimented with this module running
various scenarios of reading digital values at both bit and byte levels and
setting digital values again both at bit and byte levels. Using a minicom
terminal running at 9600 enables some simple experimentation to confirm the
principles of what I've thought is possible. I've then followed this with using
Python3 scripts to send and receive serial messages to configure, read and write
date to and from the module. I can see this module has many practical uses
where a simple and reliable serial connection is preferred over alternative I2C
and SPI interfaces.
A Python3 script is listed below that queries the
byte level values present on Port B and sets Port C outputs to match them. This
script could be used so that Port B is monitoring various input lines and Port
C writes out the 'state' of the input lines to light LEDs to provide a visual
indication. A download of this script is available: DACIO300-auto-portb-byte-read-portc-byte-set.py
# DACIO300-auto-portb-byte-read-portc-byte-set.py
# Python3 script to run on RaspberryPi to
continuously send serial messages to the DACIO 300
# only when GPIO port 17 is set high.
# RS232 interface board to query the logic levels
on the digital Port B at 'byte' level
# and set Port C to the same value at byte level
in order to mirror the values at Port B
# These levels can be used to drive LEDs, relays
etc to reflect Port B status.
# Hardware interfacing with RPi:
# GPIO serial o/p connected to hex i/p of IC4050
running at 3.3v with
# hex output directly connected to TTL interface
pin 4 (tx i/p) on the DACIO 300
# the DACIO300 TTL interface pin 5 (rx o/p) is
connected to a potential divider
# to drop the TTL 5v to 3.3v, which is then
connected to hex input on IC4050.
# the corresponding hex o/p at 3.3v is connected
to RPi GPIO serial input.
# GPIO port 17 connected to a switch or set/reset
latch circuit to control
# when the script sends/receives serial
commands/data
import serial
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
x=1
latch_state=0
# set serial parameters
ser = serial.Serial("/dev/ttyAMA0",
baudrate=9600,
bytesize=8,
parity='N',
stopbits=1,
timeout=1,
xonxoff=False,
rtscts=False,
dsrdtr=False)
ser.close()
def queryByte():
ser.open()
ser.write(bytes('!'+port+'?;','utf_8'))
global
byteQuery # make variable available outside function
byteQuery =
ser.readline(4).decode("utf_8","ignore").strip()[-3:]
print
('\tPort ', port, '\tstate = ', byteQuery)
ser.close()
def setByte(PortC):
ser.open()
ser.write(bytes('!C='+PortC+';','utf_8'))
print
('\tPort C', '\tstate = ', PortC)
bitQuery
= ser.readline(1).decode("utf_8","ignore").strip()[-1:]
if
bitQuery == '!':
print ("Command received by DACIO300 ok:")
else:
print
("Error:")
ser.close()
try:
while x:
#print reminder of DACIO 300 default conditions
print ("Waiting to activate..")
if
latch_state == 0:
if GPIO.input(17):
print ("Monitoring starts..")
print ("This script queries DACIO300 Port B logic levels on each
input channel")
print ("The result displayed is in decimal byte value")
print ("Port C 'bits' are set to the same values as read on Port
B")
port = 'B'
latch_state = 1
queryByte()
setByte(byteQuery) # pass value obtained from queryByte function to
setByte function
time.sleep(5)
if
latch_state == 1:
if GPIO.input(17):
port = 'B'
queryByte()
setByte(byteQuery)
time.sleep(5)
if
latch_state == 1:
if not GPIO.input(17):
latch_state = 0
print ("Monitoring ends..")
time.sleep(5)
time.sleep(5)
except KeyboardInterrupt:
GPIO.cleanup()