Mcp23017 inputs (16-128 ports)

Moderator: leecollings

Post Reply
User avatar
ILoveIOT
Posts: 59
Joined: Sunday 25 March 2018 17:47
Target OS: Linux
Domoticz version: 2020.2
Location: NL
Contact:

Mcp23017 inputs (16-128 ports)

Post by ILoveIOT »

I created a script for receiving inputs from the mcp23017 using the interrupt port, so you're wire the mcp23017 usual with i2c + 1 cable from each mcp23017 to a GPIO port on the PI. The mcp23017 receives on 1 of the 16 ports a change, send there is a change to the PI, PI is using a script to read all the port on that mcp23017 chip, when a port is active it runs a script for example /root/scripts/mcp23017/mcp23017.GPA0.sh, mcp23017.GPA1.sh etc, when multiple ports are active, multiple scripts will run. By doing it like this, it uses so much less CPU time, its just waiting on 1 port on the PI for a change, and not polling 16 ports the whole time.

If you want more ports, you can create more files based on this, for i2c address 0x20,0x21,0x22 etc

This example uses the first 8 ports (GPA0-GPA7) as low inputs, so the chip is set to pull up internal, the last 8 ports (GPB0-GPB7) are for the PIR in my case, they send HIGH when active, so I have 10K resistors between GND and each GPB0-GPB7 (chip has no internal pull down), some PIR don't need them, and don't react if placed, some PIR need them because the generate false positive (or being in flooting state). You can change easy mcp23017.input.c and mcp23017.setup.sh to you're own config. Place in this example the 10K resistors between GND and each GPB0-GPB7 when noting is connected or you will get false warning about port state, and switch with +3.3V

Beware every time a PIR send a signal the script will run, or a switch that stays open, will run a script every 50ms, I created a lock dir example, so you're create a dir, and sleep for some time, every time another same script is running it will exit, because there is a "lock" dir.

Image

I included a zip file with all the example's

Filename : mcp23017.input.c

Code: Select all

/*
 * mcp23017.input.c:
 * This script provide 16 channel input with the MCP23017 with Orange-PI with the interupt port, so only when a button is pressed, the PI will check status all ports 
 * This take much less cpu time then when waiting for the interrupt on all 16 ports.
 *
 * 1. Connect the mcp23017 as usual with i2c, in this example on address 0x20 (3x GND)
 * 2. Connect MCP23017 port 20 (INTA) to port (Physical) 37 on the PI (Number off the Physical pin 37 - Broadcom pin 20 - GPIO.25 - wPi 25)
 * 3. Connect push buttons with GND on MCP23017 port 1-16
 *
 * This example uses the first 8 ports (GPA0-GPA7) as low inputs, so the chip is set to pull up internal, 
 * the last 8 ports (GPB0-GPB7) are for the PIR in my case, they send HIGH when active, 
 * so I have 10K resistors between GND and each GPB0-GPB7 (chip has no internal pull down), 
 * some PIR don't need them, and don't react if placed, some PIR need them because the generate false positive (or being in flooting state). 
 * You can change easy mcp23017.input.c and mcp23017.setup.sh to you're own config.
 *
 * When pushed or detection, it will start a script /root/scripts/mcp23017/mcp23017.GPA0, mcp23017.GPA1, mcp23017.GPB0 etc
 *
 *
 * Created by ILoveIOT 2019 
 ***********************************************************************************
 * For compiling use  : cd /root/scripts/mcp23017 ; gcc -Wall -o mcp23017.input mcp23017.input.c -lwiringPi
 * For console use    : /root/scripts/mcp23017/mcp23017.input
 * For background use : /root/scripts/mcp23017/mcp23017.input &
 ***********************************************************************************
 */

#include <stdio.h>    // Used for printf() statements
#include <wiringPi.h> // Include WiringPi library!
#include <stdlib.h>   // Standard Library
#include <mcp23017.h> // I2C mcp23017 communication
#define Q2W_BASE 100

// We're using the Physical pin number, for the INTA/INTB, Orange-PI GPIO.25 to MCP23017 INTA
const int butPin = 37; // Number off the Physical pin 37 - Broadcom pin 20 - GPIO.25 - wPi 25

int main(void)
{
    //printf("MCP23017 input script is running! Press CTRL+C to quit.\n");
	
	// Add in the mcp23017 on the q2w board
	mcp23017Setup (Q2W_BASE, 0x20) ;

	// Enable the on-goard GPIO
    wiringPiSetup () ;
	
    // Setup stuff:
	wiringPiSetupPhys(); // Initialize wiringPi -- Physical pin numbers
    pinMode(butPin, INPUT); // Set button as INPUT on the PI
    pullUpDnControl(butPin, PUD_UP); // Enable pull-up resistor on button

	// Setup the MCP23017
	system("/bin/bash -c /root/scripts/mcp23017/mcp23017.setup.sh");	
	// Reset the INTA and INTB
	system("/bin/bash -c /usr/sbin/i2cget -y 0 0x20 0x12 > /dev/null 2>&1");
	system("/bin/bash -c /usr/sbin/i2cget -y 0 0x20 0x13 > /dev/null 2>&1");
	
	delay(250);
	
    // Loop (while(1)):
    while(1)
    {
        if (digitalRead(butPin)) // Button is released if this returns 1
        {
			delay(50); // Wait 50ms again
        }
        else // If digitalRead returns 0, button is pressed
        {		
					
		if (digitalRead (Q2W_BASE + 15) == HIGH)  // While Pushed
	    {
			//printf ("GPB7 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB7.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 14) == HIGH)  // While Pushed
	    {
			//printf ("GPB6 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB6.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 13) == HIGH)  // While Pushed
	    {
			//printf ("GPB5 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB5.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 12) == HIGH)  // While Pushed
	    {
			//printf ("GPB4 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB4.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 11) == HIGH)  // While Pushed
	    {
			//printf ("GPB3 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB3.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 10) == HIGH)  // While Pushed
	    {
			//printf ("GPB2 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB2.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 9) == HIGH)  // While Pushed
	    {
			//printf ("GPB1 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB1.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 8) == HIGH)  // While Pushed
	    {
			//printf ("GPB0 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPB0.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 7) == LOW)  // While Pushed
	    {
			//printf ("GPA7 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA7.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 6) == LOW)  // While Pushed
	    {
			//printf ("GPA6 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA6.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 5) == LOW)  // While Pushed
	    {
			//printf ("GPA5 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA5.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 4) == LOW)  // While Pushed
	    {
			//printf ("GPA4 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA4.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 3) == LOW)  // While Pushed
	    {
			//printf ("GPA3 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA3.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 2) == LOW)  // While Pushed
	    {
			//printf ("GPA2 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA2.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 1) == LOW)  // While Pushed
	    {
			//printf ("GPA1 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA1.sh &");
        }
		
		if (digitalRead (Q2W_BASE + 0) == LOW)  // While Pushed
	    {
			//printf ("GPA0 is ON\n") ;
			system("/bin/bash -c /root/scripts/mcp23017/mcp23017.GPA0.sh &");
        }
		
		// Reset the INTA and INTB
		system("/bin/bash -c /usr/sbin/i2cget -y 0 0x20 0x12 > /dev/null 2>&1");	
		system("/bin/bash -c /usr/sbin/i2cget -y 0 0x20 0x13 > /dev/null 2>&1");
		delay(50); // Wait 150ms again
        }
    }
    return 0;
}
Filename : mcp23017.setup.sh

Code: Select all

#/bin/bash  

# Change in /boot/armbianEnv.txt overlays=i2c0 i2c1 i2c2
# apt-get install i2c-tools
# i2cdetect -y 0 of i2cdetect -y 1

#$ i2cdetect -y 0
#     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
#00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
#10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 
#20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#70: -- -- -- -- -- -- -- --                     

# Define complete bank A as IN-Port: 
/usr/sbin/i2cset -y 0 0x20 0x00 0xFF
# Define complete bank B as IN-Port: 
/usr/sbin/i2cset -y 0 0x20 0x01 0xFF
# Activate all internal pullup resistors at bank A: 
/usr/sbin/i2cset -y 0 0x20 0x0C 0xFF
# Activate all internal pullup resistors at bank B: 
#/usr/sbin/i2cset -y 0 0x20 0x0D 0xFF
# Activate Interrupt OnChange for Port INTA: 
/usr/sbin/i2cset -y 0 0x20 0x04 0xFF
# Activate Interrupt OnChange for Port INTB: 
/usr/sbin/i2cset -y 0 0x20 0x05 0xFF
# Connect Interrupt-Pin A with the one of B (MIRROR = 1): 
/usr/sbin/i2cset -y 0 0x20 0x0A 0x40
# Connect Interrupt-Pin B with the one of A (MIRROR = 1): 
/usr/sbin/i2cset -y 0 0x20 0x0B 0x40

exit

### EOF
Have fun !! :D
Attachments
mcp23017.input_bb.png
mcp23017.input_bb.png (330.36 KiB) Viewed 6598 times
mcp23017.zip
(12.24 KiB) Downloaded 277 times
1x OPI PC 5.8.16 Debian 10, MiniDNLA,SMD230,EpEver,MPD,800GB,Wiegand,7 temps,DHT,32/64 I/O,2022.1
2x OPI PC 4.19.25 Debian 9, MPD,7 temps,16/32 I/O,BMP,4.10717
1x IntelNUC 5.10 Debian 10, 2TB,DalyBMS,2023.1
3x ESPEasy NodeMCU V3, 16/16 I/O
PhilippeBP59
Posts: 2
Joined: Monday 05 August 2019 0:17
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Mcp23017 inputs (16-128 ports)

Post by PhilippeBP59 »

Good evening,
Interested in your I2C port write reading approach in Domoticz, I would like you to tell me how and where to install the files "mcp23017.input.c" and "mcp23017.setup.sh"?
Thank you
User avatar
ILoveIOT
Posts: 59
Joined: Sunday 25 March 2018 17:47
Target OS: Linux
Domoticz version: 2020.2
Location: NL
Contact:

Re: Mcp23017 inputs (16-128 ports)

Post by ILoveIOT »

I would like you to tell me how and where to install the files "mcp23017.input.c" and "mcp23017.setup.sh"?
You can install them everywhere but I installed them under /root/scripts/mcp23017/

So all the files (for the mcp23017 input) are in the same dir, but like I sed you can use youre own dirs.

There was a hint for you in the script "* For compiling use : cd /root/scripts/mcp23017 ; gcc -Wall -o mcp23017.input mcp23017.input.c -lwiringPi"
1x OPI PC 5.8.16 Debian 10, MiniDNLA,SMD230,EpEver,MPD,800GB,Wiegand,7 temps,DHT,32/64 I/O,2022.1
2x OPI PC 4.19.25 Debian 9, MPD,7 temps,16/32 I/O,BMP,4.10717
1x IntelNUC 5.10 Debian 10, 2TB,DalyBMS,2023.1
3x ESPEasy NodeMCU V3, 16/16 I/O
PhilippeBP59
Posts: 2
Joined: Monday 05 August 2019 0:17
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Mcp23017 inputs (16-128 ports)

Post by PhilippeBP59 »

Good evening, I will apply your recommendation. Thank you
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests