Wednesday 15 June 2016

RaspberryPi GPIO Pulse Generator - Windows Based

Background

In one of my previous posts - RaspberryPi Pulse Generator Console Based, I put together a simple Python3 script to take user input supplied parameters to have the RaspberryPi generate pulses from a GPIO port.

Whilst this was adequate for simple applications it had the drawback of having to supply the parameters via keyboard every time. This method of use was also prone to errors due to the entry of incorrect port numbers.

I decided to experiment with the idea of creating a Windows interface to capture user supplied input with the use of a mouse click to start the pulse generator.

I re-used some of the Pulse Generator code and Windows code from the GPIO Ports Set & Toggle application. Some new code was required in order to allow the capture of user input into entry boxes.

Some screen shots are provided below that illustrate the 4 user input areas:
1. GPIO port number
2. Pulse length (the 'on' or 'high' time)
3. Pulse inter-space length (the 'off' or 'low' time)
4. Number of pulses

A button to 'Generate' the pulse(s) and a Quit button to exit the application.

The advantage of providing the 'Generate' button is the ability to create the pulse stream by one click of the mouse. Once the pulse stream has been completed, the generate button can be used again. If the pulse parameters need modifying it is a simple case of changing the value in the relevant input box.

One additional piece of code I included was to check the port number supplied was valid to be used as an output port.


Start-up Window


Parameters entered - pulses generated - and previous values shown



Incorrect Port number with error message when 'Generate' selected

It is possible to run more than one instance of this application using the format:

python3 <filename.py> &

This allows multiple GPIO ports to be used to generate separate pulse streams.

It is important when connecting GPIO ports to external circuits that appropriate interfacing is provided. In the case of connecting +3.3v RaspberryPi GPIO ports to external +5v TTL or CMOS components I prefer to use the CMOS 4050 Hex buffer as detailed in my other blog posts (see the GPIO Set & Toggle example).


Python3 code:

Here is the Python3 code listing for this application. The file can be downloaded from here.

# Python3 script to run on RaspberryPi B to enter pulse parameters within a Window
# Apply the parameters to a RaspberryPi B GPIO port in order to generate a pulse stream
# Port numbers are validated as those available to use as outputs:
# numbers 0,1,4,7,8,9,10,11,14,15,17,18,21,22,23,24,25
# Entered parameters are displayed next to the input areas
# Error message provided if invalid port number entered

from tkinter import *
import RPi.GPIO as GPIO
import time

GPIO.setwarnings(False)
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)

def pulse_gen():
    portlist = ['0','1','4','7','8','9','10','11','14','15','17','18','21','22','23','24','25'] # string list of valid ports available
    ps=(portstr.get()) # get the entered value as a string
    if ps not in portlist: # check if entered value not in list              
        label6=Label(myGUI, text='Invalid port', fg='red').grid(row=1,column=2)
        return # if invalid do not proceed    
    port=int(portstr.get())
    label10=Label(myGUI, text="                  ").grid(row=1,column=2)
    label6=Label(myGUI, text=ps, fg='red').grid(row=1,column=2)
    length=float(lengthstr.get()) # get pulse duration
    label7a=Label(myGUI, text="                  ").grid(row=2,column=2)
    label7=Label(myGUI, text=length, fg='red').grid(row=2,column=2)
    space=float(spacestr.get()) # get intra pulse duration
    label8a=Label(myGUI, text="                  ").grid(row=3,column=2)
    label8=Label(myGUI, text=space, fg='red').grid(row=3,column=2)
    number=int(numberstr.get()) # get number of pulses
    label9a=Label(myGUI, text="                  ").grid(row=4,column=2)
    label9=Label(myGUI, text=number, fg='red').grid(row=4,column=2)

    GPIO.setup(port,GPIO.OUT)
    GPIO.output(port,GPIO.LOW)
    loop = 0
    while loop < number:
        GPIO.output(port,GPIO.HIGH)
        time.sleep(length)
        GPIO.output(port,GPIO.LOW)
        time.sleep(space)
        loop += 1
    return

def finish():
    myGUI.destroy()
    GPIO.cleanup()

myGUI = Tk()
myGUI.geometry('500x170')
myGUI.title('RPi B GPIO Pulse Generator')
myGUI.resizable(0,0)

portstr=StringVar()
lengthstr=StringVar()
spacestr=StringVar()
numberstr=StringVar()

label1=Label(myGUI, text='RaspberryPi Pulse Generator', fg='black').grid(row=0,column=0)
label1a=Label(myGUI, text='Enter values', fg='black').grid(row=0,column=1)
label1b=Label(myGUI, text='Last values', fg='black').grid(row=0,column=2)
label2=Label(myGUI, text='Enter valid GPIO port number').grid(row=1,column=0)
label3=Label(myGUI, text='Enter pulse length (secs)').grid(row=2,column=0)
label4=Label(myGUI, text='Enter pulse inter-space (secs)').grid(row=3,column=0)
label5=Label(myGUI, text='Enter number of pulses').grid(row=4,column=0)

portgpio=Entry(myGUI, textvariable=portstr).grid(row=1,column=1)
lengthgpio=Entry(myGUI, textvariable=lengthstr).grid(row=2,column=1)
spacegpio=Entry(myGUI, textvariable=spacestr).grid(row=3,column=1)
numbergpio=Entry(myGUI, textvariable=numberstr).grid(row=4,column=1)

button1=Button(myGUI,text='Generate', fg='blue', command=pulse_gen).grid(row=5,column=0)
button2=Button(myGUI,text='Quit', fg='red', command=finish).grid(row=6,column=0)

myGUI.mainloop()

Wednesday 1 June 2016

RaspberryPi GPIO Ports Set & Toggle

Background

With my renewed interest in digital circuits I recently sorted out all my old TTL and CMOS integrated circuits I obtained many years ago. I had no idea whether any or all of these devices had survived the best part of 25 years! What I needed to do before purchasing any more integrated circuits was to check my existing stock.

Giving some thought as to how I might go about all of this testing, the first idea was to use physical push buttons or switches to interface with the digital circuits either to set or reset logic levels, or to physically switch on and off to simulate clock pulses. As you will have read previously, the dreaded switch bounce problem put paid to this approach, as physical switching produces erratic and unreliable results in sensitive logic circuits.


Solution

As I had used the Raspberry Pi to produce pulses [see previous article], I thought about producing a simple application to do the following:

1. Set a GPIO port as an output.
2. Toggle the level of that GPIO output either High or Low.

As I wanted to be able to set more than one GPIO port and potentially toggle each output port High or Low, I decided to try to produce a Graphical User Interface (GUI) or Window interface, using a mouse button to both set and toggle the GPIO ports. Additionally, the benefit of using software to control the GPIO ports would mean clean switching of the logic levels.

Searching the many useful sources of Python code on-line proved very helpful. Having little experience of coding in Python and none in GUI/Window building, I knew this project was going to be challenging.

The resultant code is listed below. Now I confess, it's likely to be considered clumsy and probably poorly coded, but as my first attempt I was pleased as it actually works and it does what I needed it to do. What I particularly enjoyed about this little project was the ability to code and play around with the results; making changes to the various parameters to set window sizes, labels, check buttons and text formatting. Sometimes it left me scratching my head wondering what some of the code was actually doing, but again, the wealth of Python resources on-line provided most of the answers.


The Python3 code

The Python listing is below. A copy of the file is available here.

=================================================



# Python v3 script 'Toggle_Model_B.py' to Run on RaspberryPi B.
# A windows interface to provide 4 checkboxes to set 4 GPIO ports as Outputs
# Uses the checkbox function to set GPIO ports either HIGH or LOW.
# Display the Port state and a count of how many times the checkbox is
# selected/toggled.
# GPIO ports to use 17, 21, 23 & 24 for RPi Model B

from tkinter import *
import RPi.GPIO as GPIO

cc17 = 0 # variables will be global
cc21 = 0
cc23 = 0
cc24 = 0
state17 = 0 # variables will be global
state21 = 0
state23 = 0
state24 = 0
port17 = 17 # GPIO port to use as outputs
port21 = 21
port23 = 23
port24 = 24
GPIO.setmode(GPIO.BCM)
# disable warning messages
GPIO.setwarnings(False)
# set 'ports' as outputs
GPIO.setup(port17,GPIO.OUT) 
GPIO.setup(port21,GPIO.OUT)
GPIO.setup(port23,GPIO.OUT)
GPIO.setup(port24,GPIO.OUT)
# set all ports to LOW
GPIO.output(port17,GPIO.LOW)
GPIO.output(port21,GPIO.LOW)
GPIO.output(port23,GPIO.LOW)
GPIO.output(port24,GPIO.LOW)

class Welcome(): # functions menu class
    
    def __init__(self,master):
        
        self.master=master
        self.master.geometry('380x150')
        self.master.title('RaspberryPi B Toggle GPIO')
        
        self.label1=Label(self.master,text='Select port to toggle output & increment', fg='black').grid(row=2,column=0)
        self.label1a=Label(self.master,text='GPIO port 17', fg='black').grid(row=3,column=0)
        self.label1b=Label(self.master,text='GPIO port 21', fg='black').grid(row=4,column=0)
        self.label1c=Label(self.master,text='GPIO port 23', fg='black').grid(row=5,column=0)
        self.label1d=Label(self.master,text='GPIO port 24', fg='black').grid(row=6,column=0)        
        self.label2=Label(self.master,text='State', fg='black').grid(row=2, column=2)
        self.label3=Label(self.master,text='Count', fg='black').grid(row=2, column=4)
        self.button2=Button(self.master,text='Quit',fg='red',command=self.finish).grid(row=7,column=0)
        
        self.var0s=IntVar() # Each port can be set high or low once set as an output   
        self.Checkbutton=Checkbutton(self.master, variable=self.var0s, command=self.p0s).grid(row=3,column=1)
        self.var1s=IntVar()
        self.Checkbutton=Checkbutton(self.master, variable=self.var1s, command=self.p1s).grid(row=4,column=1)
        self.var2s=IntVar()
        self.Checkbutton=Checkbutton(self.master, variable=self.var2s, command=self.p2s).grid(row=5,column=1)
        self.var3s=IntVar()
        self.Checkbutton=Checkbutton(self.master, variable=self.var3s, command=self.p3s).grid(row=6,column=1)

    def p0s(self): # toggle port 17 high or low & display state & count
        GPIO.setwarnings(False)
        global cc17
        global state17
        p0=self.var0s.get()
        if p0 == 1:
            state17 = 1
            cc17 +=1
            self.label4=Label(self.master,text=str(state17), fg='black').grid(row=3,column=2)
            self.label5=Label(self.master,text=str(cc17), fg='red').grid(row=3,column=4)
            GPIO.output(port17,GPIO.HIGH)
        else:
            state17 = 0
            self.label6=Label(self.master,text=str(state17), fg='black').grid(row=3,column=2)
            GPIO.output(port17,GPIO.LOW)

    def p1s(self): # toggle port 21 high or low & display state & count
        GPIO.setwarnings(False)
        global cc21
        global state21
        p1=self.var1s.get()
        if p1 == 1:
            state21 = 1
            cc21 +=1
            self.label7=Label(self.master,text=str(state21), fg='black').grid(row=4,column=2)
            self.label8=Label(self.master,text=str(cc21), fg='red').grid(row=4,column=4)
            GPIO.output(port21,GPIO.HIGH)
        else:
            state21 = 0
            self.label7=Label(self.master,text=str(state21), fg='black').grid(row=4,column=2)
            GPIO.output(port21,GPIO.LOW)
            
    def p2s(self): # toggle port 23 high or low & display state & count
        GPIO.setwarnings(False)
        global cc23
        global state23
        p1=self.var2s.get()
        if p1 == 1:
            state23 = 1
            cc23 +=1
            self.label9=Label(self.master,text=str(state23), fg='black').grid(row=5,column=2)
            self.label10=Label(self.master,text=str(cc23), fg='red').grid(row=5,column=4)
            GPIO.output(port23,GPIO.HIGH)
        else:
            state23 = 0
            self.label9=Label(self.master,text=str(state23), fg='black').grid(row=5,column=2)
            GPIO.output(port23,GPIO.LOW)

    def p3s(self): # toggle port 24 high or low & display state & count
        GPIO.setwarnings(False)
        global cc24
        global state24
        p1=self.var3s.get()
        if p1 == 1:
            state24 = 1
            cc24 +=1
            self.label11=Label(self.master,text=str(state24), fg='black').grid(row=6,column=2)
            self.label12=Label(self.master,text=str(cc24), fg='red').grid(row=6,column=4)
            GPIO.output(port24,GPIO.HIGH)
        else:
            state24 = 0
            self.label11=Label(self.master,text=str(state24), fg='black').grid(row=6,column=2)
            GPIO.output(port24,GPIO.LOW)

    def finish(self): # exit
        GPIO.cleanup()
        self.master.destroy()

def main(): # main function
    
    root=Tk()
    myGUIWelcome=Welcome(root)
    root.resizable(0,0)
    root.mainloop()

if __name__ == '__main__': # start and run the script
    main()
    
=================================================

Application Output

When you first run the Python script above on the Raspberry Pi, the GUI below appears:


What this shows is that I have coded in Python3 to use 4 GPIO ports;
17, 21, 23 and 24.

These 4 ports can be connected to appropriate circuitry - some suggestions are shown below. Selecting the Checkbutton against each port entry will Set the port as an output and Toggle the output level on that port to High (or 3.3v). Selecting the Checkbutton again will Toggle the port Low (0v) and the Check mark will disappear. What I also coded was a 'State' and 'Count' display. The 'State' column shows what level each port is set to. The 'Count' column shows how many times you have selected the port. Further examples are shown below:


In the example above GPIO port 17 has been selected, and it's output is High (3.3v), the Count is 1 to show the port has been selected and set High once.


In the examples above GPIO 17 has been 'deselected' so it's output is set Low (0v), the Count remains at 1 even though the port has been set Low. It indicates that just one complete 'cycle' of setting High then Low has occurred.
GPIO 21 has been taken through 2 complete cycles of setting and toggling High and Low.
GPIO 23 and 24 have been selected and both set High.

Some examples of how I used this application was to confirm the correct operation of logic circuits, testing of binary counters, flip-flops and bistable latches. I also used the Raspberry Pi and this application to interface with some Arduino circuits too; mostly to simulate that logic changes were correctly detected on Arduino inputs, to help with code debugging.

Benefits

The benefits of using this relatively simple application were:
1. Logic levels being set were reliable - if the 'State' showed 1, then I knew the relevant port was High.
2. Reliable switching - no switch bounce.
3. Status display - when testing it's useful to know how many 'cycles' of switching has occurred.
4. Slow switching - sometimes being able to single step one logic level to another is very helpful, and sometimes it's possible to simulate a slow clock pulse by just using the mouse button.

Circuits

The following circuits are very simple illustrations which could also be used to teach simple logic circuit behaviours:

The example above uses 2 GPIO ports to test that a dual input AND gate works correctly. In each testing scenario when using either TTL or CMOS integrated circuits running at +5v, you must use a 4050 Hex Buffer running at +3.3v to provide a correct interface between the Raspberry Pi GPIO ports and the external circuits. In the example above, both GPIO ports will need to be High to switch the Led on.


The example above tests a dual input NOR gate. The Led is on only when both GPIO ports are Low.

The circuit above was put together to test the Binary Counter (4020).

GPIO 17 was set High to enable the AND gate, whilst GPIO 21 was set alternately High and Low by mouse button clicks, to act as a slow clock pulse stream.
Another method of testing I employed was using my Python clock pulse generator script to generate a number of pulses instead of using GPIO 21. That way, the clock pulse stream input to the 4020 was controlled by GPIO 17 by either enabling or disabling the AND gate.
To reset the counter I connected GPIO 23 via the 4050 to the Reset pin on the 4020 so that after testing, whatever the state of the counter I could reset the counter. In practice I connected each counter output to an Led to provide a visual counter output.

* Note: for clarity, the circuit diagrams do not show power or earthing arrangements - the datasheets for the TTL and CMOS devices are readily available on-line.




Thursday 26 May 2016

Raspberry Pi Pulse Generator - Console Based

Background

I have a number of older digital integrated circuit components (both TTL and CMOS), and as part of my on-going experiments I wanted to create a simple counter and single 7-segment display. I needed to confirm that the counter could take in a number of pulses and provide a digital display readout. The pulses to be counted could come from a number of sources such as clocks or sensors providing a pulsed output. I ended up putting together a simple Python script on the Raspberry Pi to use as a pulse generator.

Research


Initially I put together the circuit below comprising a counter, with a binary to decimal coded LED driver feeding a 7-segment display.  There are many similar circuits available on-line, the operation and configuration of which is well documented, so I don't intend fully describing the operation. Suffice to say for each single complete pulse on the input to the counter, the output count is coded in order to drive, or light up, a series of LEDs arranged in the 7-segment display format to display digits 0 to 9.
For a detailed explanation and examples see the Digital Counter reference below.


To test the circuit I initially provided clock input to the counter using the simple push button pulse generator described in a previous article. This worked very well but was limited to single pulse operation, generated by hand.

To provide a more realistic input I decided to produce a simple Python script to run on a Raspberry Pi computer. This script would enable me to input pulse characteristics such as pulse length, the time between pulses and the number of pulses. Each pulse or set of pulses would appear on a General Purpose Input Output port (GPIO) and be connected to the digital counter input. The benefits of this would allow me to reliably generate noise free, repeatable pulses.

Operation

The diagram below shows the Raspberry Pi 26-way GPIO connector, with a connection from GPIO port 17, (pin 11) to an IC4050 hex buffer, which in turn connects to the input of the divide by 10 counter IC7490. The 4050 operates at 3.3v whilst interfacing to a 5v circuit, which is well within its operating parameters. It  is required to provide an interface between the Raspberry Pi GPIO output which operates at 0/3.3v, and the 7490 operating at 0/5v. Power for the 4050 can be taken from the Raspberry Pi as there is only one hex buffer in use. There are other configuration connections that need to be put in place associated with the 7490 and 7447; see http://www.electronics-tutorials.ws/counter/bcd-counter-circuit.html



The Python script below runs in a console / terminal display and takes in user supplied parameters to generate pulses - a series of High and Low level changes. The script is commented which should make it reasonably straight forward to understand what's going on. The script isn't entirely error proof - this was one of my first Python coding attempts using the Raspberry Pi GPIO ports, but if you are careful in selecting the input parameters all should be well.

In operation I have found this script to be very useful, not only with this simple counter application but with experimenting with other shift register and counter combinations where larger numbers of pulses are required. The advantage of using such a script on the Raspberry Pi is the ability to craft an exact pulse stream. Where the circuit under test could produce unknown results it's most important to have confidence in the input pulse source.

# Python v3.4.2 console based script
# Set an individual Raspberry Pi GPIO port as an output
# Generate pulses by setting the port High & Low [amount of pulses user supplied]
# Pulse duration/length & inter-pulse duration/length is user supplied
# *** NOTE no check is made whether the port number entered is valid to use as an output ***
# Selected port is set Low prior to 'pulse' generation
# Tested on RPi Model B & 2

import RPi.GPIO as GPIO # import GPIO module, use local name GPIO to reference
import time


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

try:
    while True:
        print ("Set Raspberry Pi GPIO port as output & generate pulses")
        print ("Warning! supplied parameters are not validated")
        print ("Enter a valid Raspberry Pi GPIO number to set as an output [99 quits]")
        portstr = input(">_ ") # get port number as a string
        print
        port = int(portstr) # convert string to integer
        if port != 99:
            GPIO.setup(port,GPIO.OUT) # set port as output
            GPIO.output(port,GPIO.LOW) # set port low to start
            print ("Enter length of pulse in seconds") # get pulse length
            lengthstr = input(">_ ") 
            length = float(lengthstr)
            print ("Enter inter-pulse time in seconds") # get pulse off time
            spacestr = input(">_ ") 
            space = float(spacestr)
            print ("Enter number of pulses") # get number of pulses to generate
            pulsesstr = input(">_ ") 
            pulses = int(pulsesstr)
            loop = 0
            while loop < pulses: # set port High & Low, generate pulses
                GPIO.output(port,GPIO.HIGH)
                time.sleep(length)
                GPIO.output(port,GPIO.LOW)
                time.sleep(space)
                loop += 1
        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()


Python script in operation


The screen shot below shows the parameters provided to generate a series of pulses. In this case each pulse comprises an on/High period of 100mS and an off/Low period of 900mS. Total pulse length being 1 Second.


Pulse outputs - examples

To illustrate a number of pulse outputs I have included some annotated oscilloscope traces with various user input values:

First trace: pulse on/High period 100mS, off/Low period 900mS.




Second trace: 50 pulses, each having pulse on 1mS, pulse off 9mS.



Third trace: an expansion of the 50 pulses train to show the pulse quality and timing accuracy. There is a slight increase in time between pulse periods - this seems to be more apparent as the pulse lengths decrease, with frequency increasing. Never the less, for experimenting purposes where absolute timing accuracy isn't the primary requirement, I've found this to be more than adequate to drive counter circuits.





Components
IC 4050 Hex buffer
IC 7490 Divide by 10 counter
IC 7447 7-segment display driver
7-segment display LED, common anode
7 resistors; 220Ω 1/4w

References:
IC 4050 Hex buffer datasheet

Digital Counter

IC 7490 Decade and Binary Counter

IC 7447 BCD to 7-Segment Decode/Driver

7-Segment Display - Common Anode

Thursday 19 May 2016

Pulse Generator

Background

Sometimes when experimenting with or testing digital logic circuits a manual switching function is needed to momentarily take an input 'high' and then return to 'low' state. This could be to simulate a logic change on a digital input, or to act as a switch on one input of a dual gate device to enable another input to pass through the gate. See below for examples:


Manual input toggle high/low to simulate logic level change:



Manual gating to enable another input through the circuit:


However, using manual switches can produce unreliable and unpredictable results due to switch bounce.

Research

Using the example of the manual switch de-bounce circuit at labbookpages I experimented with various component values to produce a push switch circuit capable of generating a single pulse approximately 0.275 seconds (approximately 250mS). This time period was sufficient for a number of experiments I wanted to try involving detecting logic level changes. This time period was also useful when I was testing the use of a clock signal to pass through counting circuitry at a relatively slow speed.

The circuit below comprises a switching and timing function, and in combination with a Schmitt Trigger device (IC4584) produces reliable, repeatable and good quality pulses. In essence a Schmitt Trigger is used to 'square up' slowly changing waveforms or inputs, and is ideally suited to providing a clean and sharp switched output in response to the relatively slowly changing input conditions in the circuit below.

Switch & Timer


Operation

In the circuit above, when power is applied capacitor C1 charges via R1 and D1. When sufficient voltage is present on the inverting Schmitt Trigger IC1 input, the output will be 0V (logic 0).

When switch SW1 is pressed C1 discharges via R2, the voltage on IC1 input will be near to 0V, therefore IC1 output will be +V (logic 1).  The output remains at +V until SW1 is released and C1 charges to the voltage needed for the Schmitt Trigger to switch it's output to 0V.

With a momentary press of SW1 and using the combination of R1, R2 and C1 above, the generated pulse length is 275mS.

Using some alternative values of C1 produces pulse lengths:
4.7uF = pulse duration 860mS
9.4uF = pulse duration 1300ms

For more information on the operation of this circuit see labbookpages.co.uk

For clarity purposes in all circuit examples I have not included the positive or negative connections from each integrated circuit to +V and 0V. Each IC datasheet provides pin-out descriptions and numbering.


Switch & Timer with external interface and indicator


With additional components I modified the original circuit above to provide buffered outputs to drive external logic circuits and a visual pulse indicator. The 4584 Schmitt Trigger (IC1) can supply up to 10mA on each output which maybe inadequate to directly drive external logic circuitry and an LED. I used the non-inverting hex buffer 4050 (IC2) to provide two outputs as shown below. I prefer to provide buffering when interfacing to potentially unknown logic inputs and LEDs to help prevent damage occurring. R3 prevents unnecessarily high current flow. C1 provides power supply decoupling to prevent power supply 'noise' causing any erratic circuit operation. I have successfully tested and used this circuit powered at 3.3v and 5v which makes it very useful to interface with single input TTL, CMOS, Raspberry Pi and Arduino based circuitry. Additional buffering of the 4050 output is necessary if driving multiple circuits.


Components

R1 100kΩ 1/4w
R2 4.7kΩ 1/4w
R3 2.2kΩ 1/4w
C1 100nF
C2 3uF
D1 1N914 (or similar general purpose low voltage diode)
D2 Red Led
IC1 4584 Schmitt Trigger (6 channels)
IC2 4050 Hex buffer (6 channels)
  

References:

Decoupling

Switch bounce

IC 4584 Schmitt Trigger datasheet

IC 4050 Hex buffer datasheet


Tuesday 17 May 2016

A Latch - Set & Reset


Background

I have experimented with various logic circuits within the 74xx and 4000 integrated circuit series, the Raspberry Pi and an Arduino clone using directly connected switches to simulate logic level changes. In some cases this is to 'preset' a logic level on a particular input, to simulate a logic level change on another input, or to act as a 'gate' function to control a particular logic function. Due to the phenomenon of something known as switch 'bounce', unwanted or unexpected results can occur. In some cases when using microprocessors or micro-controllers, code can be written to mitigate the effects of switch bounce. However, this isn't alway practical or possible if switch connections need to be made directly to logic circuits.

Research

Using various information sources in reference books and on-line, I put together this circuit below, based around the 555 'timer' device. I claim no originality for how the 555 is being used, but through experimentation I used some additional discrete components to provide two 'logic' outputs to allow interfacing to both 3.3v and 5v logic circuitry.

Operation

When power is first applied, output 1 (o/p1) is 'low' at 0v. This 0v level is also applied via R6 to the Base of Q1 turning  the transistor 'off'. The voltage present at the Emitter/R5 junction and therefore output 2 (o/p2) is 0v.

When Switch 1 (SW1) is pressed and released, pin 2 of TLC555 is taken low momentarily, the result of which sets pin 3 high at 5v. This logic 'high' level can be directly connected to TTL, CMOS or other +5v digital circuitry - ensuring that the current draw from the 555 doesn't exceed the specification, typically 100mA maximum.

The Led (D1) illuminates to confirm the transition on pin 3 from 'low' to 'high', with R3 preventing unnecessary current draw. R6 provides transistor base current limitation as Q1 is forward biased and switches on. Output 2 becomes 3.3v due to the voltage divider effect of R4 and R5. This o/p is suitable for direct connection to digital devices operating at 3.3v such as the Raspberry Pi and Arduino, current draw is limited by R4. The addition of Q1 and associated resistors provides separation between o/p1 and o/p2.

The Led remains illuminated and both outputs remain 'high' until Switch 2 (SW2) is pressed. Pin 6 is taken low resetting the latch, after which pin 3 goes low, the Led goes off and both outputs return to 0v.

Voltage measurements - no load attached
Output 1 is either 0v or 5v
Output 2 is either 0v or 3.3v

Current measurements - no load attached
Total measured supply current:
Latch 'set' : 1.4mA
Latch 'reset' : 0.11mA
Led current 0.94mA with Latch 'set'
Q1 Collector-Emitter 0.25mA

Components
R1, R2 1MΩ 1/4w
R3 3.3kΩ 1/4w
R4 6.8kΩ 1/4w
R5, R6 10kΩ 1/4w
C1 100nF
D1 Red Led
Q1 BC337 (or similar general purpose NPN transistor)
IC1 TLC555 (or similar low power NE555 type timer)

References:
7400 TTL series

4000 CMOS series

Switch bounce

555 Tutorial

Touch On-Off circuit [50 - 555 Circuits - Talking Electronics] http://www.talkingelectronics.com/te_interactive_index.html

TLC555 Datasheet