In this guide we are going to learn how to use logic gates. Even if you can usually do things by just taking more GPIO pins and do the logic in a code then there will be times you may want to do things in hardware. For example you might have sensor that does some boolean logic then sends it as RF signal to the Raspberry PI as one result then you may want to do some logic on the sensor side, or you might need to save up to not use to many GPIO pins.
For a test case then we will be doing a circuit in this example that uses one GPIO pin that should get triggered when a Infrared sensor is triggered and if there is fire. (Yes I know this is not good real world example but its good for the purpose of learning how to use the logic gates)
So what we will be using is one NOT gate and one AND gate, we will put the NOT gate infant of the Flame sensor, and then the AND gate will connect the result of the NOT gate with the result of the Infra red sensor.
We do not take any responsibility for possible errors in the guide or errors that you might do wiring it up. Incorrect wiring can result in damaged sensor or damaged Raspberry PI.
Pieces we use in this example:
- Raspberry PI 2
- Cobbler and Cobbler cable
- Bread board and mini breadboard
- 1 K-ohm resistor
- 560 ohm resistor
- IC74HC08N and gate circuit.
- IC74HC04N not gate circuit.
- Flame sensor (Can use some other sensors also since this guide is focusing on gates and not the sensors)
- HC-SR501 infrared sensor. (Can use some other sensors also since this guide is focusing on gates and not the sensors)
If you don’t know resistor color codings to find correct resistors then you can click the link bellow
Putting it all together:
We will be focusing on our logic circuit as a separate piece first and worry about the sensors and GPIO part later.
I used IC74HC08N for the AND gate circuit which has 4 separate AND gates in it and I used IC74HC04N for the NOT gate which has 6 separate NOT gates in it.
So this here is how our logic circuit would look like:
The circuits I used had multiple gates in them but we only use one in each. You could use them all if you wanted.
Point marked as 2 will go to the Infrared sensor, point marked as 3 will go to the Flame sensor, and Point marked number one will go to GPIO pin on the Raspberry PI. Red 5V will go to 5V and Blue will go to ground.
The outputs from the gates can be up to 5V so we have to use resistors before sending the result back to the Raspberry PI GPIO.
TTL gates usually are as follows:
Input: 0 V to 0,8V for LOW, and 2 to 5V for HIGH
Output: 0 V to 0,5 V for LOW and 2,7V to 5V for HIGH
For CMOS gate then values can be more like:
Input: 0 V to 1,5V for LOW, and 3,5 to 5V for HIGH
Output: 0 V to 0,05 V for LOW and 4,95V to 5V for HIGH
We apply same method as we used in the Ultrasonic examples to calculate the Resistors. R1 was chosen as 1K, so R2 is calculated as:
3,3 = 5 * (1000 / (R + 1000))
0.66 = (1000 / (R + 1000))
0.66R + 660 = 1000
0.66R = 340
R2 = 515 Ohm, nearest one with higher value I had was 560 Ohm which I used.
For the inputs into the Logic gates from the Flame sensor and Infra red sensor we will risk that high and low fall in between the TTL spec shown above for Input of gates. If it does not then we would need to probably work around it with some transistors.
On a mini breadboard this circuit will look like this:
At top you can see the wires that will go to the main board. (or directly to the sensors)
Green: Infrared sensor
Yellow: Flame sensor
Once this is done then all we will have to do is to connect the Red, White, Green, Yellow and Blue wires to the main board which will have the Cobbler and the sensors.
Note since we had so many blue and red wires then I connected the Reds and blue to the Voltage rail on the breadboard.
The white wire got connected to GPIO 5.
The Xojo code:
Here we just use exactly same code as for the Infrared sensor guide. (Using the Interrupt version of it)
When using interrupts then we must be really careful to not call anything from within the interrupt since Xojo does not support that. So the idea is we have a safe function that only logs the interrupt then we poll the log. That way event is never lost and timer or whatever method you use to poll does not need to be very intensive.
We just have a Window here with one Listbox on it and one Timer. You can set the Timer to 1000 or maybe 500 depending on what responsiveness your looking for.
The open event of the Window:
Sub Open() GPIO.PinMode(5,GPIO.INPUT) GPIO.PullUpDnControl(5,GPIO.PUD_DOWN) if GPIO.WIringPiISR(5,GPIO.EDGE_RISING, AddressOf InteruptModule.SensorInterupt) = -1 then MsgBox "Could not register interupt for pin number 5" return end if Timer1.Mode = Timer.ModeMultiple End Sub
The timer action event:
Sub Action() If InteruptModule.DetectionCount > 0 then Listbox1.AddRow("Motion detected") InteruptModule.DetectionCount = 0 end if End Sub
We create a module called InteruptModule, the Module has one property and one method:
Protected DetectionCount As Integer Protected Sub SensorInterupt() // We need some pragmas here to make this safe since this is called from interupt. #Pragma StackOverflowChecking False #Pragma DisableBackgroundTasks // We only count the events here. DetectionCount = DetectionCount + 1 End Sub
We need to patch Paul’s GPIO module, adding the following to the module (the function we are adding likely already exists but is not fully implemented so verify that or just blindly override it) and remember to add the four constants also:
Protected Const EDGE_FALLING = 1 Protected Const EDGE_BOTH = 3 Protected Const EDGE_RISING = 2 Protected Const EDGE_SETUP = 0 Protected Function WIringPiISR(pin as integer,edgeType as integer, p as ptr) As Integer //This function registers a function to received interrupts on the specified pin. // The edgeType parameter is either INT_EDGE_FALLING, INT_EDGE_RISING, // INT_EDGE_BOTH or INT_EDGE_SETUP. If it is INT_EDGE_SETUP then no // initialisation of the pin will happen – it’s assumed that you have already // setup the pin elsewhere (e.g. with the gpio program), but if you specify one // of the other types, then the pin will be exported and initialised as specified. // This is accomplished via a suitable call to the gpio utility program, // so it need to be available. // // The pin number is supplied in the current mode – native wiringPi, BCM_GPIO, // physical or Sys modes. // // This function will work in any mode, and does not need root privileges to work. // // The function will be called when the interrupt triggers. // When it is triggered, it’s cleared in the dispatcher before calling your // function, so if a subsequent interrupt fires before you finish your handler, // then it won’t be missed. (However it can only track one more interrupt, // if more than one interrupt fires while one is being handled then they will be ignored) // // This function is run at a high priority (if the program is run // using sudo, or as root) and executes concurrently with the main program. // It has full access to all the global variables, open file handles and so on. // // See the isr.c example program for more details on how to use this feature. #If TargetARM And TargetLinux Then Soft Declare Function wpISR Lib "libwiringPi.so" Alias "wiringPiISR" (pin As Integer, mode As Integer, p as ptr) as Integer return wpISR(pin, edgeType,p) #Endif End Function
Run it with sudo to get admin mode to get full access to GPIO.
When running it then we got record in the listbox whenever the flame sensor detected fire and the infrared sensor detected a human.