MicroPython Driver for Testing Logic Gates
Contents
Introduction
This a MicroPython driver to test 1, 2, 3 and 4-input logic gates written specifically for the BBC micro:bit. It is assumed that the reader understands the basics of logic gates; in any case there are plenty of online tutorials on this topic.
The driver operates specifically on positive-logic gates. It uses the GPIO pins of the micro:bit to probe and discover the truth table. From the truth table it is possible to then determine the type of logic gate under test.
The driver is able to detect all common logic gate types: NOT (Inverter), Buffer, AND, OR, NAND, NOR, XOR and XNOR.
Preparing the driver for use on the micro:bit
The driver can be:
- Copied from this webpage onto the clipboard then paste into the MicroPython editor e.g. the Mu Editor. It should be saved as fc_logic_gate_tester.py - OR -
- Download as a zip file using the link. Unzip the file and save it as fc_logic_gate_tester.py into the default directory where the MicroPython editor e.g. Mu Editor saves python code files.
After saving the fc_logic_gate_tester.py file to the computer it should be copied to the small filesystem on the micro:bit. The examples on this page will not work if this step is omitted. Any MicroPython editor that recognises the micro:bit will have an option to do this.
The Mu Editor is recommended for its simplicity. It provides a Files button on the toolbar for just this purpose.
Connecting Logic Gates for Testing
This driver was tested against all gate types, predominantly with CD4000 series logic gate ICs. These chips have been around a long time - first introduced in 1968 by RCA (Radio Corporation of America) - and are inexpensive and (in most cases) still readily available.
Specifically, the following were successfully tested:
Input Pins | Logic Gate | Integrated Circuit |
---|---|---|
1-input | NOT[1] | CD4000BE, CD4009UBE, CD4041BE, CD4049UBE, CD4069BE, C40106BE |
Buffer | CD4041BE, CD4050BE | |
2-input | AND | CD4081 |
OR | CD4071BE | |
NOR | CD4001BE | |
NAND[2] | CD4011BE, CD4093BE, SN74HC00N | |
XOR | CD4030BE, CD4070BE | |
XNOR | CD4077BE | |
3-input | AND | CD4073BE |
OR | CD4075BE | |
NOR | CD4000BE, CD4025BE | |
NAND | CD4023BE | |
4-input | AND | CD4082BE |
OR | CD4072BE | |
NOR | CD4002BE | |
NAND | CD4012BE |
It is essential to consult the chip's datasheet before connecting to the micro:bit's GPIO pins. Its simply not feasible to list all the possible combinations. So choose the logic gate chip to be tested then refer to the pinout in the datasheet.
Fig 1 - CD4011BE quad 2-input NAND gate IC
Fig 1 is an example of a 2-input NAND logic gate. As the functional description diagram from the datasheet shows, the CD4011BE has four such independent gates.
Choose a gate to test on the chosen chip. Connect each of the input pins and the output pin of the chosen gate separately to available digital pins[3] on the micro:bit.
The driver's constructor (discussed below) is used to tell the driver which digital pins on the micro:bit have been connected to the gate's input pins and output pin.
Driver Overview
The driver is implemented as a class.
Class Constructor
The first thing to do is call the constructor. This provides an instance of the class and most importantly indicates the pin connections.
Syntax:
LGT(PINout,
PINin1,
PINin2 = None,
PINin3 = None,
PINin4 = None)
Where:
PINout is the micro:bit pin that is connected
to the logic gate output pin; Required.
PINin1 is the micro:bit pin that is connected
to the input 1 pin of the logic gate; Required.
PINin2 is the micro:bit pin that is connected
to the input 2 pin of the logic gate. This is
required if the logic gate is 2, 3 or 4-input.
PINin3 is the micro:bit pin that is connected
to the input 3 pin of the logic gate. This is
required if the logic gate is 3 or 4-input.
PINin4 is the micro:bit pin that is connected
to the input 4 pin of the logic gate. This is
required if the logic gate is 4-input.
Examples:
from fc_logic_gate_tester import *
# 1-input logic gate
lgt = LGT(pin9, pin0)
# 2-input logic gate
lgt = LGT(pin9, pin0, pin1)
# 3-input logic gate
lgt = LGT(pin9, pin0, pin1, pin2)
# 4-input logic gate
lgt = LGT(pin9, pin0, pin1, pin2, pin8)
User Methods
The driver provides the following user methods:
- GetTruthTable()
Returns the logic gate truth table as a list of lists. Each inner list is one line of the truth table containing all input values and the output value. - PrintTruthTable()
Outputs the truth table in a readable format. - LogicGate()
Returns the type of logic gate under test. - Report()
Outputs a formatted report comprising the truth table and the gate type. In most cases this is the only method that the user will need to call.
Example
This example will test the first NAND gate on the 4-input CD4012BE chip. From the CD4012BE datasheet:
- VSS = Pin 7
- VDD = Pin 14
- Output pin = Pin 1
- Input pin 1 = Pin 2
- Input pin 2 = Pin 3
- Input pin 3 = Pin 4
- Input pin 4 = Pin 5
So, with this information, the micro:bit was connected to the CD4012BE chip:
micro:bit | CD4012BE |
---|---|
GND | Pin 7 |
3.3V | Pin 14 |
pin9 | Pin 1 |
pin0 | Pin 2 |
pin1 | Pin 3 |
pin2 | Pin 4 |
pin8 | Pin 5 |
# Tests the first 4-input NAND gate
# on the CD4012BE.
from fc_logic_gate_tester import *
# 4-input logic gate
lgt = LGT(pin9, pin0, pin1, pin2, pin8)
# Get the truth table
print('Raw form of the truth table:')
tt = lgt.GetTruthTable()
for x in range(16):
print(tt[x], end='')
if (x !=15):
print(' , ', end='')
if (x % 2) != 0:
print()
# Output the formatted truth table
print('\nFormatted truth table:')
print(lgt.PrintTruthTable())
# Find the logic gate type
print('\nLogic Gate type:')
print(lgt.LogicGate())
# Print the entire report
# with one line of code!
lgt.Report()
Output:
Raw form of the truth table:
[0, 0, 0, 0, 1] , [0, 0, 0, 1, 1] ,
[0, 0, 1, 0, 1] , [0, 0, 1, 1, 1] ,
[0, 1, 0, 0, 1] , [0, 1, 0, 1, 1] ,
[0, 1, 1, 0, 1] , [0, 1, 1, 1, 1] ,
[1, 0, 0, 0, 1] , [1, 0, 0, 1, 1] ,
[1, 0, 1, 0, 1] , [1, 0, 1, 1, 1] ,
[1, 1, 0, 0, 1] , [1, 1, 0, 1, 1] ,
[1, 1, 1, 0, 1] , [1, 1, 1, 1, 0]
Formatted truth table:
TRUTH TABLE
In1 In2 In3 In4 Out
0 0 0 0 1
0 0 0 1 1
0 0 1 0 1
0 0 1 1 1
0 1 0 0 1
0 1 0 1 1
0 1 1 0 1
0 1 1 1 1
1 0 0 0 1
1 0 0 1 1
1 0 1 0 1
1 0 1 1 1
1 1 0 0 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0
None
Logic Gate type:
NAND
TRUTH TABLE
In1 In2 In3 In4 Out
0 0 0 0 1
0 0 0 1 1
0 0 1 0 1
0 0 1 1 1
0 1 0 0 1
0 1 0 1 1
0 1 1 0 1
0 1 1 1 1
1 0 0 0 1
1 0 0 1 1
1 0 1 0 1
1 0 1 1 1
1 1 0 0 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0
Logic Gate: NAND
Test Logic Gates Driver Code for micro:bit
Download as zip file
'''
Tester for 1, 2, 3, 4-input positive-logic gates.
Identify/test the following gate tyes:
NOT (Inverter), Buffer
AND, NAND, OR
NOR, XOR, XNOR
AUTHOR : fredscave.com
DATE : 2024/10
VERSION : 1.00
'''
from microbit import *
LG_Dict1 = {'Buffer':'01', 'NOT (Inverter)':'10'}
LG_Dict2 = {'AND':'0001', 'NAND':'1110',
'OR':'0111', 'NOR':'1000',
'XOR':'0110', 'XNOR':'1001'}
LG_Dict3 = {'AND':'00000001', 'OR':'01111111',
'NAND':'11111110', 'NOR':'10000000'}
LG_Dict4 = {'AND':'0000000000000001',
'OR':'0111111111111111',
'NAND':'1111111111111110',
'NOR':'1000000000000000'}
class LGT():
def __init__(self, PINout, PINin1,
PINin2 =None, PINin3 = None,
PINin4 = None):
self.PINout = PINout
self.PINin1 = PINin1
self.PINin2 = PINin2
self.PINin3 = PINin3
self.PINin4 = PINin4
if PINin2 == None:
self.Inputs = 1
elif PINin3 == None:
self.Inputs = 2
elif PINin4 == None:
self.Inputs = 3
else:
self.Inputs = 4
@staticmethod
def get_key(Dict, value):
for key in Dict:
if Dict[key] == value:
return key
return None
def GetTruthTable(self):
if self.Inputs == 1:
return self.GetTruthTable1()
elif self.Inputs == 2:
return self.GetTruthTable2()
elif self.Inputs == 3:
return self.GetTruthTable3()
else:
return self.GetTruthTable4()
def GetTruthTable1(self):
truth = list()
for x in range(2):
self.PINin1.write_digital(x)
out = self.PINout.read_digital()
truth.append([x, out])
return truth
def GetTruthTable2(self):
truth = list()
for x1 in range(2):
for x2 in range(2):
self.PINin1.write_digital(x1)
self.PINin2.write_digital(x2)
out = self.PINout.read_digital()
l = [x1, x2, out]
truth.append(l)
return truth
def GetTruthTable3(self):
truth = list()
for x1 in range(2):
for x2 in range(2):
for x3 in range(2):
self.PINin1.write_digital(x1)
self.PINin2.write_digital(x2)
self.PINin3.write_digital(x3)
out = self.PINout.read_digital()
l = [x1, x2, x3, out]
truth.append(l)
return truth
def GetTruthTable4(self):
truth = list()
for x1 in range(2):
for x2 in range(2):
for x3 in range(2):
for x4 in range(2):
self.PINin1.write_digital(x1)
self.PINin2.write_digital(x2)
self.PINin3.write_digital(x3)
self.PINin4.write_digital(x4)
out = self.PINout.read_digital()
l = [x1, x2, x3, x4, out]
truth.append(l)
return truth
def PrintTruthTable(self):
print('TRUTH TABLE')
if self.Inputs == 1:
self.PrintTruthTable1()
elif self.Inputs == 2:
self.PrintTruthTable2()
elif self.Inputs == 3:
self.PrintTruthTable3()
else:
self.PrintTruthTable4()
def PrintTruthTable1(self):
truth = self.GetTruthTable()
print('In', 'Out')
print(truth[0][0], ' ', truth[0][1])
print(truth[1][0], ' ', truth[1][1])
def PrintTruthTable2(self):
truth = self.GetTruthTable()
print('In1', 'In2', 'Out')
for x in range(4):
print(' ', truth[x][0], ' ', truth[x][1],
' ', truth[x][2], sep='')
def PrintTruthTable3(self):
truth = self.GetTruthTable()
print('In1', 'In2', 'In3', 'Out')
for x in range(8):
print(' ', truth[x][0], ' ', truth[x][1],
' ', truth[x][2], ' ', truth[x][3],
sep='')
def PrintTruthTable4(self):
truth = self.GetTruthTable()
print('In1', 'In2', 'In3', 'In4', 'Out')
for x in range(16):
print(' ', truth[x][0], ' ', truth[x][1],
' ', truth[x][2], ' ', truth[x][3],
' ', truth[x][4], sep='')
def LogicGate(self):
Dict_List = [LG_Dict1, LG_Dict2, LG_Dict3, LG_Dict4]
Dict = Dict_List[self.Inputs - 1]
truth = self.GetTruthTable()
output = ''
for x in range(2 ** self.Inputs):
output += str(truth[x][self.Inputs])
gate = LGT.get_key(Dict, output)
if gate != None:
return gate
else:
return 'Unknown gate'
def Report(self):
print('\n')
self.PrintTruthTable()
print('\nLogic Gate:', self.LogicGate(), '\n')