Thursday, 16 November 2017

Small LED string power supply

Background:
Last year I purchased a small LED lighting strip as a Christmas decoration. It was powered by two 1.5v batteries and whilst the lighting strip gave an effective display I found that the batteries didn't last too long. This year I investigated an alternative 3 volt power source and I also wanted to make use of some spare components I had.

I had a 240 volts (AC) mains power block for providing 5v DC to charge Sony Ericsson mobile phones and using this as the primary power source I investigated a suitable 3 volt regulator. The LP2950-30 provided the solution. I put together the simple circuit below. LED D1 provides an indication that the 5v supply is available. Capacitors C1 and C2 provide stability of operation for the voltage regulator as recommended in the LP2950-30 datasheet.

Specifications:
Input voltage supply 5v @ 450mA Sony Ericsson power block.

Output voltage 3v @ 100mA (max), to supply 50mA for LED string.


5v to 3v voltage converter circuit

Construction :
The circuit components were mounted on a very small piece of veroboard, placed within a small plastic box - Hammond 1551GBK.

To maintain separation of input and output connections, a 2.5mm DC power socket was used for the 5v input supply with a 2.1mm DC power socket used for the 3v output supply. The LED was mounted next to the input socket to act as a reminder that the neighbouring socket is for 5v input.

Operation:
The LED strip connects to the output socket using a 2.1mm DC power plug. The 5v power block connects to the input socket using a 2.5mm DC power plug. A regulated and stable 3v was measured at the output, with current draw of 51mA. Initially running for an hour with the plastic box lid fitted, the regulator was cool to the touch - working well below its maximum current capability. No more batteries will be required! Images of the completed unit are below:


Circuit board mounted within small box

Lights are on, no more batteries!!

Components:
LP2950-30 (3v Regulator)
2.2uF 50v Electrolytic capacitor (2)
D1 - Red LED as main power supply indicator
LED panel mounting socket
R1 - 220 ohms 0.25w
Supply input socket 2.5mm DC socket
Supply input plug 2.5mm DC plug to connect 5v power block
Supply output socket 2.1mm DC socket
Supply output plug 2.1mm DC plug to connect to LED string cable
Plastic project box Hammond 1551GBK 50x35x20mm
Veroboard for circuit mounting

Thursday, 2 November 2017

Passive Infra-Red Controlled LED Strip Lighting

Introduction

In my house there is an inglenook fireplace which houses a wood burner.
Ordinarily the fireplace is quite a dark place being recessed and I wanted to provide some lighting to take the darkness away and to light up the natural stone.

After searching for lighting and considering the powering options I decided to install an LED lighting string. These strings come in various sizes and can be cut to length. Powered usually by 12 volt power supply I wanted to hide as much cable and components from view.

Looking at various switching options I decided to design a switching unit based on a Passive Infra-Red (PIR) detector and power transistor to switch the 12 volt LED string on and off.

The main challenges to address are that the PIR detector alone can only switch low power circuits and the PIR output is limited to a short 'on' time once activated. What was required is that the PIR detector should operate with a single hand gesture with circuitry to switch the LED string on, and with another hand gesture, the PIR switches the LED string off.  The PIR module will be mounted out of sight underneath the inside of the fireplace recess, so a single hand wave will be sufficient for the module to detect movement. One wave will switch the LED string on, with another wave switching the LED string off.


The circuit below achieves what I required.

Passive Infra-Red LED string switching controller
Circuit description

The PIR module detection sensitivity is set so that it is triggered when movement is as close as possible to avoid spurious activity. The 'on-time' is set to its shortest time, as all that is required is a single pulse output from detected movement.

The PIR module output is fed to a CMOS dual D-Type Flip-Flop. Only one Flip-Flop of the CD4013 is needed in this example. The Flip-Flop is configured so that when the PIR output changes from Low to High, the output of the CD4013 (Q) goes High. When the PIR output returns to Low condition, the Q output of the Flip-Flop remains High. Only when another transition from Low to High on the PIR output takes place will the Flip-Flop change its output from High to Low. In effect the CD4013 Flip-Flop is performing a divide by 2 operation, but in this case its output can be used effectively as a latch.

The output from the CD4013 is fed to Q1, MOSFET  RFP12N10L. The MOSFET is switching 12volts to the LED string, and with the length of string I needed, the total current draw was approximately 0.5 Amp. The MOSFET is working well within the operating specifications and does not experience any rise in temperature, which is important as I chose to mount the circuitry in a sealed aluminium box.

I included the LED (D1) as a switching indicator. Should the LED string fail to operate and D1 is on, this will indicate that the LED string has failed.

The PIR module and CD4013 require a 5v supply. The power regulator 78L05 provides this and is capable of supplying up to 100mA.

Pins 8, 9, 10 & 11 of the CD4013 are taken to 0v. [not shown on the circuit diagram above]

Operating currents
In operation, this circuit draws a relatively small amount of power; indeed when inactive, current draw is almost zero.

The following total current measurements were taken:
PIR inactive: 51uA
PIR active: 0.375mA
CD4013 inactive: 0
CD4013 active: 41uA
LED strip off: 51uA
LED strip on (3 metre length): 400mA
LED1 on draws 1.6mA

References / data sheets

Saturday, 1 April 2017

Data Encoder/Decoder HT12E/HT12D

Data Encoder / Decoder
HT12E / HT12D

Introduction

I recently came across an old article I had kept from the Radio Society of Great Britain magazine (Radcomm) May 1998 by G6AWT, entitled 'A Versatile Remote Control System', in which a pair of encoding and decoding processors named the HT12E and HT12D had been used to provide remote control functions for radio equipment.

I wondered whether these processors were still available - they are! I began to think about how I could use this technology with the current range of micro-controllers such as the Arduino and the Raspberry Pi, together with other potential uses. I also thought it would be a great opportunity to fully investigate the operation of the two processors to help me better understand how I might use these in the future.


HT12E & HT12D description and operation
These devices are made by HOLTEK and have common applications in car and garage door controllers, smoke and fire alarms, burglar and car alarms, security systems etc .

The encoder (HT12E) is capable of encoding information comprising 12 bits in total; 8 address bits and 4 data bits. Each address/data bit can be set to either High or Low logic states. The output from the encoder can be used in various ways; for example to feed a Radio Frequency or infrared transmitter , or it could be directly connected to a decoding processor.  Eight address bits allows for one encoder / transmitter combination to use 1 of 256 addresses, each one capable of sending 1 of 16 different data values. This address/data combination allows the possibilities of using one encoder to control many remote receivers with HT12D decoders. The outputs from the HT12D decoder can be used to switch connected logic circuitry or other attached devices via suitable interfaces.

HT12E Encoder circuit

The basic circuit arrangements for the encoder:


The address to use is selected by connecting one or more pins A0 - A7 to 0 volts. If left 'open', that is, not connected to 0 volts, the address will be all '1's or logic HIGH on each pin. The same process is applied to the data bits. If left open, these data bits are at logic 1 or HIGH. OSC1 is the on board oscillator input pin, OSC2 is the oscillator output pin. These two pins are connected together via resistor R, in this case its value is 1Mohm. When the XMIT button is pressed to take pin 14 to 0 volts, the address and data bit stream appears at pin 17 DOUT. The data stream comprises one synchronising bit followed by 8 address bits and 4 data bits. The oscilloscope trace below shows one complete cycle comprising the synchronising bit, 8 address bits and 4 data bits. All address bits and data bits are at logic '1'. In this example the HT12E is powered at 3.3v.


If pin 14 (Transmit Enable) is permanently taken to ground (0v), the encoder continuously transmits the data stream. If a short enable pulse is applied to pin 14, in this case 5mS, one complete transmit cycle is produced comprising 4 cycles, see trace below:


Selecting data pin AD8 and taking this to ground (0v) produces the following data stream:



Selecting address pin A0 and taking this to ground (0v) while AD8 is also at 0v, produces the following data stream:



HT12D Decoder circuit

The basic circuit arrangements for the decoder:



The address to use is selected by connecting one or more pins A0 - A7 to 0 volts. If left 'open', that is, not connected to 0 volts, the address will be all '1's or logic HIGH on each pin. For correct operation between the HT12E and HT12D, the address values must be the same. OSC1 is the on board oscillator input pin, OSC2 is the oscillator output pin. These two pins are connected together via resistor R, in this case its value is 33kohm. The data sheets for both HT12D and HT12E provide details of suitable resistor values. When a data stream from the HT12E encoder is applied to pin 14, DIN, the decoder compares the input data three times with the locally selected address. If no errors are present the input data codes are decoded and latch transferred to the data output pins D8 - D11. The data levels remain 'latched' until a different data set is received. These output pins can be connected to other logic circuitry or external devices via suitable interfaces, as they are unable to provide high current drive. The VT (Valid Transmission pin) pin 17 goes high to indicate a valid transmission and in the circuit above, the LED is switched on. In this example the HT12D is powered at 3.3v.


Using simple 433Mhz Transmitter and Receiver for communications between HT12E & HT12D

Having proved correct operation between the HT12E and HT12D by directly connecting the DOUT to the DIN, I investigated using the basic 433Mhz transmitter and receiver combination in the image below. Transmitter on the left, receiver on the right.


I had little success with these units without any external antennas, so I investigated some options. I took the design for a simple wound coil antenna from an 'Instructables' article. http://www.instructables.com/id/433-MHz-Coil-loaded-antenna/

With these antennas attached during some experimentation I managed to get a reliable communications link of approximately 5 metres. I didn't spend any time trying to optimise the antennas, but early results were encouraging.

Connect the DOUT from the HT12E to the data input on the transmitter module, and apply +3.3v power and ground to the transmitter. The output from the 433Mhz receiver module is connected via an inverter. During inactive periods, the receiver output can be at +3.3v so when a data stream is received, the first positive going synchronising pulse does not get correctly presented to the HT12D and therefore the first cycle would be discounted leaving only 3 cycles (the minimum) for checking. Also, I noted that the output from the 433Mhz receiver is an inverse of the data stream. Using a BC337 NPN transistor as an emitter follower provides a simple inverting function drawing very small amounts of current. Basic circuits below:



Examining the output directly from the HT12E DOUT pin and the BC337 Emitter/R4 junction (HT12D input) confirms the data stream has been correctly received over the 433Mhz communications link. 




In the following trace, address bit A0 is set LOW. Note you can see a very small time lag between the top trace HT12E Data out and the BC337 inverter output (HT12D Data input)  due to the time taken to pass through the 433Mhz TX/RX link.


Using the Raspberry Pi to control

I further experimented with the Raspberry Pi to set the HT12E data pins (AD8 - AD11) using the GPIO pins. Additionally, I used another GPIO pin to act as the trigger for the HT12E. I haven't drawn any circuits for this as the interfacing is straight forward as both the Raspberry Pi and the HT12E operate at 3.3v.
The 4 Raspberry Pi GPIO pins needed to set the HT12E data bits can be directly connected to the HT12E. The GPIO pin acting as the trigger function needs connecting via an inverter circuit. This is to ensure that when the Raspberry Pi GPIO pin is taken 'HIGH' a corresponding 'LOW' is present at the HT12E trigger pin.

I have included a simple Python3 script below, which prompts the user to enter a number between 0 and 15, and using Binary Coded Decimal, sets the AD8 - AD11 pins to convey the user entered number correctly. I have experimented further with this, connecting LEDs to the HT12D decoder data pins to ensure the transmitted and received data is presented correctly. I also used the HT12D data output pins connected to a TTL IC 7447 (BCD to 7-Segment display driver) and a 7-segment display. I have referenced this before in an earlier blog and the direct link is: (http://www.electronics-tutorials.ws/counter/bcd-counter-circuit.html).

Using the Python script below (GPIO_HT12E.py), when a number is entered (0-9) the 7-Segment display shows the number. It could be said that this is a very convoluted way to use this technology but it was really useful to experiment and prove that it was possible.

I can see many uses for the HT12E/D combination, especially when used with either the Raspberry Pi or Arduino. The transmission of the data stream can be over an RF link or direct connection using 2-core cable. With the possibilities of using multiple decoders (HT12D) all 'listening' on their individually configured addresses it is possible for the Raspberry Pi or Arduino to control both the address values and control the use of the data pins. It would be possible to control literally hundreds of external devices this way. To break out the HT12D 4 data output pins further, it is possible to connect these to a 4 to 16 decoder such as the MC14514 / 74HC4514 to get 16 individual output pins. Just one HT12E/D combination could control up to 16 different devices, ideal for something like a model railway layout controlling signals, points, lights etc.


Python3 script:

# Python v3.4.2 console based script
# Set Raspberry Pi GPIO ports Low depending on user input
# User enters number between 0 and 15, GPIO ports 22, 23, 24 & 25
# are set as BCD representations of the decimal input.
# GPIO ports are weighted 0, 2, 4, 8 [GPIO 22, 23, 24, 25]
# Number 99 entered quits the script
# GPIO ports connect to AD8-11 ports on HT12E encoder chip
# user input is BCD coded & used to set AD8-11 ports
# GPIO port 17 is used to send trigger pulse to activate the HT12E for 1 complete cycle


import RPi.GPIO as GPIO # import GPIO module
import time

GPIO.setwarnings(False) # disable warning messages
GPIO.setmode(GPIO.BCM)  # use chip GPIO pin numbers

GPIO.setup(17, GPIO.OUT)
GPIO.output(17, GPIO.LOW)
GPIO.setup(22, GPIO.OUT)
GPIO.output(22, GPIO.HIGH)
GPIO.setup(23, GPIO.OUT)
GPIO.output(23, GPIO.HIGH)
GPIO.setup(24, GPIO.OUT)
GPIO.output(24, GPIO.HIGH)
GPIO.setup(25, GPIO.OUT)
GPIO.output(25, GPIO.HIGH)

def One():
    GPIO.output(22, GPIO.LOW)

def Two():
    GPIO.output(23, GPIO.LOW)

def Four():
    GPIO.output(24, GPIO.LOW)

def Eight():
    GPIO.output(25, GPIO.LOW)

def ClearAll():
    GPIO.output(22, GPIO.HIGH)
    GPIO.output(23, GPIO.HIGH)
    GPIO.output(24, GPIO.HIGH)
    GPIO.output(25, GPIO.HIGH)

def Trigger():
    GPIO.output(17, GPIO.HIGH)
    time.sleep(0.005)
    GPIO.output(17, GPIO.LOW)

try:
    while True:
        print ("Setting GPIO ports Decimal to BCD")
        print ("Enter number between 0 and 15 [99 quits]")
        print ("Warning! supplied parameters are not validated")
        decimal = input(">_ ") # get number as a string
        print
        dec_number = int(decimal) # convert string to integer
        if dec_number != 99:
            ClearAll() # set A8-11 ports to '0000'
            Trigger() # send trigger pulse
            time.sleep(0.1)
            if dec_number == 0:
                ClearAll()
                Trigger()
            if dec_number == 1:
                One()
                Trigger()
            if dec_number == 2:
                Two()
                Trigger()
            if dec_number == 3:
                One()
                Two()
                Trigger()
            if dec_number == 4:
                Four()
                Trigger()
            if dec_number == 5:
                One()
                Four()
                Trigger()
            if dec_number == 6:
                Two()
                Four()
                Trigger()
            if dec_number == 7:
                One()
                Two()
                Four()
                Trigger()
            if dec_number == 8:
                Eight()
                Trigger()
            if dec_number == 9:
                One()
                Eight()
                Trigger()
            if dec_number == 10:
                Two()
                Eight()
                Trigger()
            if dec_number == 11:
                One()
                Two()
                Eight()
                Trigger()
            if dec_number == 12:
                Four()
                Eight()
                Trigger()
            if dec_number == 13:
                One()
                Four()
                Eight()
                Trigger()
            if dec_number == 14:
                Two()
                Four()
                Eight()
                Trigger()
            if dec_number == 15:
                One()
                Two()
                Four()
                Eight()
                Trigger()
        else: # user exit
            print ("Exiting..")
            GPIO.cleanup()
            break

except KeyboardInterrupt: # catch the Ctrl-C
    print ("Exit..")
except: # catch other errors
    print ("Error..Exiting")
finally: # clean up on exit
    GPIO.cleanup()


Python3 script GPIO_HT12E.py (Google Drive)

Wednesday, 8 March 2017

MOSFET Switches - Experiments

Introduction

MOSFET = Metal Oxide Semiconductor Field Effect Transistor

I have been using a level converter circuit based on a MOSFET BS170 to connect Raspberry Pi and Arduino processors running at 3.3v to external 5v logic circuits.

I have a good understanding about bipolar transistors but I realised I needed a bit of a refresher on how MOSFETs work and how I might be able to use these in the future.

A good explanation of MOSFETs can be found at:

https://en.wikipedia.org/wiki/MOSFET

In essence the voltage applied to the Gate terminal of a MOSFET determines the conductivity of the device.



I put together 3 circuits below:

MOSFET Switch


This circuit is a demonstration of how to manually switch a MOSFET on and off with a Light Emitting Diode (LED) as an indicator. I used this to take measurements of voltage and current levels and to make observations for any issues that might arise.

Using an oscilloscope I detected a couple of issues which if left unaddressed could cause erratic operation of this circuit and anything else connected to it.

Firstly, when the switch is closed, switch bounce (which I have covered in an earlier article) creates a voltage spike drop of nearly 1 volt at the Gate of the MOSFET which also appears at the Drain. If this circuit was just switching the LED on and off this wouldn't be too serious, however, if this circuit connects to another logic circuit, then any random voltage spikes passing through logic circuitry are unwelcome and can cause unpredictable results.

To overcome this, C1 is placed across the switch and prevents the voltage spikes appearing.

Secondly, when power is applied to this circuit a voltage spike of nearly 2 volts was measured at the Gate of the MOSFET, which also appeared at the Drain. It was sufficient to briefly illuminate the LED. The combination of C1 and C2 absorbs this voltage spike.

Circuit operation:
With power applied and the switch open, the Gate of the MOSFET is taken to 0 volts via R1. The MOSFET is off and the LED is also off.
When the switch is closed +V is applied to the Gate and the MOSFET is turned on, the LED is also on. C2 is charged via the switch.
When the switch is opened C2 discharges via R1 and the voltage on the gate drops and the MOSFET is switched off. There is a small delay before the MOSFET is switched off due to the time taken for C2 to discharge. In this example the delay is 4mS.

Various measurements were taken as I was interested in the amount of power used.
With +V at 5V, with switch closed, current draw via R1 is 14.8uA, the MOSFET (BS170) draws 4.9uA, so total is 19.7uA. Current draw via R2, LED and BS170 is 3.06mA.
With +V at 3.3V, with switch closed, current draw via R1 is 10uA, the MOSFET draws 3.3uA, total 13.3uA. It can be seen that the amount of current used is very small which is a key improvement over using bipolar transistors.

Dual MOSFET Logic Interface



Running at 5v, the input can be either 0/+3.3v or 0/+5v.
Running at 3.3v, the input can be 0/+3.3v.

Circuit operation:
With the input at 0v, the Gate of Q1 is held at 0v, the MOSFET is off and the Drain is high at +V. This switches on Q2, and the Drain is effectively at 0v. Therefore, the ouput of this interface follows the input level.
With the input at +3.3 or +5v, the Gate of Q1 is high, and the MOSFET is on. The Drain is effectively at 0v therefore Q2 is turned off. The Drain of Q2 is at +V.

This circuit can provide an isolation function between two different logic circuits, or act as a +3.3v to +5v logic level converter.

With 0v at the input the total current draw is 50uA. With the input at either +3.3v or +5v total current draw is 0.5mA.


LED String Driver


I have a small string of LEDs, used as a small Christmas decoration. I gave some thought as to how I might provide control of these LEDs as normally they connect to a 3v power source and are either on or off. Testing this string of LEDs, 20 in total, current draw from a battery source was 59mA.

The circuit above has the string of LEDs wired to the Drain of Q2.

The BS170 can switch and provide a continuous operating current of 500mA, so it is operating well within its parameters.

Circuit Operation:
With 0v applied to the input, Q1 is off and Q2 is switched on and the LEDs are illuminated.
When +3.3v is applied to the input, Q1 is switched on which switches off Q2 and the LEDs are off.

I experimented using both a Raspberry Pi and Arduino to operate the circuit,
and using a GPIO port on either microprocessor the maximum GPIO current draw was 10uA. However, just switching the GPIO high or low to turn the LEDs off / on wasn't that interesting.

I found and modified a Python script to run on the Raspberry Pi to produce a Pulse Width Modulated (PWM) pulse stream to apply to the circuit. Various effects can be produced, such as a flickering candle effect which is quite realistic
with all 20 LEDs operating at once. The python script is provided below for the Raspberry Pi.

# Python3 script to run on RaspberryPi 2
# Use pwm to control switching of mosfets & a string of christmas LEDS.

import RPi.GPIO as GPIO
import time
import random

LED = 18 # gpio port

GPIO.setwarnings(False)
GPIO.cleanup()

def setup():
    global pwm
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LED, GPIO.OUT)
    pwm = GPIO.PWM(LED, 200)
    pwm.start(100)

def set_brightness(new_brightness):
    pwm.ChangeDutyCycle(new_brightness)

def flicker():
    set_brightness(random.randrange(0,70))
    time.sleep(random.randrange(1, 10) * 0.01)

def loop():
    try:
        while True:
            flicker()
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
setup()

loop()


Additionally, I used an ESP8266 Feather Huzzah running a MicroPython script to control the circuit. The script is below, with some slight variations in
random number generation to that used in the Python script.


# MicroPython script to run on ESP8266
# Use pwm to control switching of mosfets & string of christmas LEDS.

import time
import machine
import urandom

def setup():
    global pwm
    pwm = machine.PWM(machine.Pin(15))
    pwm.freq(60)

def set_brightness(new_brightness):
    pwm.duty(new_brightness)

def flicker():
    set_brightness(urandom.getrandbits(10))
    time.sleep(urandom.getrandbits(5) * 0.01)

def loop():
    try:
        while True:
            flicker()
    except KeyboardInterrupt:
        pass

setup()

loop()


Given the physical size of the ESP8266 Feather Huzzah combined with a small battery pack, a small self contained and discrete operating unit could be produced.


Thursday, 19 January 2017

Raspberry Pi - Serial interfacing with DACIO300 Input/Output Module


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()