Raspberry Pi MC SL with MCP23017

2019-12-20
2023-04-04
  • oliverboswall - 2019-12-20

    Hello Everyone,

    I am a new user here and I have a raspberry Pi 3 model B which I have installed CODESYS Control for Raspberry Pi MC SL. I am trying to communicate with the MCP23017 chip using i2c. I have downloaded the library, and driver as well as the sample code but I am not able to get it to work - thus any help would be greatly appreciated.

    I have managed to communicate with the MCP23017 chip using the raspberry pi terminal itself using the code

    $ i2cset -y 1 0x20 0x00 0x00 (this code on the pi declares all pins of Bank A (GPA) as outputs)
    $ i2cset -y 1 0x20 0x14 0x01 (this code on the pi turns on the 1st led on channel A)

    I have been trying to replicate this in codesys but its not working and I am quite lost. If anyone has some tips please contact me.

    Kind regards, Oliver

     
  • Anonymous - 2019-12-21

    Originally created by: phenixrb

    hello oliver,
    Codesys does not manage MCP23017 in I2C, but MCP23S17 in SPI.

    l viewtopic.php?f=23&t=6247 l

     
  • i-campbell

    i-campbell - 2019-12-21

    Hello, in my brief search I couldn't find your exact Codesys driver.

    You can make your own though, here is the documentation.
    https://forge.codesys.com/drv/io-drivers/doc/I2C/

    If you decide to develop your driver on forge.codesys.com, there is a wonderful community to help when you are stuck.

    Let me know if there are any specific questions about the process, or of course you can ask there.

     
  • eschwellinger

    eschwellinger - 2019-12-28

    Hi,
    you could give the driver from the section here a try:
    l viewtopic.php?f=23&t=5872 l
    or is it what you have already done?

    This section will move to forge too...next
    BR
    Edwin

     
  • oliverboswall - 2019-12-30

    Hello everyone,

    Sorry for my late response - hope you all had a lovely Christmas.

    Yes I downloaded that driver, library and sample code from that thread Edwin but I was not able to get any response. I think I am missing something trivial but such as setting the GPIO to an input/output but I am not able to see the i2c gpio in codesys. Is this correct?

    If anyone has 30 minutes (or any time at all) to have a quick run through of what I have already done and give some advice I would greatly appreciate it.

    I look forward to hearing from you

     
  • eschwellinger

    eschwellinger - 2019-12-31

    Hi,
    no mapping is needed for I2C on the GPIO's.
    Did you enable I2C by using CLI?

    sudo raspi-config
    That's basically the only thing which is needed.

    You could check your device by:
    i2cdetect -y 1
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    If this works CODESYS should work with the I2C too.

    BR
    Edwin

     
  • JJoe - 2020-01-13

    Hello
    from time to time I trying to work with the MCP23017. I have no problem to use the MCP ports as inputs but until now I was not able to use the MCP ports as outputs (e.g. to control a LED).
    Regards
    JJoe

     
  • JJoe - 2020-01-13

    Sorry I forgot my Codesys code:
    MCP23017_0x24.OUT_A:=16#00; //Porta --> Output
    MCP23017_0x24.OUT_B:=16#FF; //PortB --> Input
    GVL.xPB:=MCP23017_0x24.IN_B.0;

    IF NOT GVL.xPB THEN
    MCP23017_0x24.OUT_A.0:=TRUE;
    MCP23017_0x24.OUT_A.1:=TRUE;
    MCP23017_0x24.OUT_A.2:=TRUE;
    MCP23017_0x24.OUT_A.3:=TRUE;
    MCP23017_0x24.OUT_A.4:=TRUE;
    MCP23017_0x24.OUT_A.5:=TRUE;
    MCP23017_0x24.OUT_A.6:=TRUE;
    MCP23017_0x24.OUT_A.7:=TRUE;
    END_IF

    IF GVL.xPB THEN
    MCP23017_0x24.OUT_A.0:=FALSE;
    MCP23017_0x24.OUT_A.1:=FALSE;
    MCP23017_0x24.OUT_A.2:=FALSE;
    MCP23017_0x24.OUT_A.3:=FALSE;
    MCP23017_0x24.OUT_A.4:=FALSE;
    MCP23017_0x24.OUT_A.5:=FALSE;
    MCP23017_0x24.OUT_A.6:=FALSE;
    MCP23017_0x24.OUT_A.7:=FALSE;
    END_IF

     
  • razvoj - 2020-09-17

    Hello,

    I have used this library and this example to use the MCP23017 as digital outputs, but there is no change on IO pins when I change the state (always 5V on pins).

    Why is there no change on pins?

    Regards

     
  • laruso - 2023-01-13

    Because there is something wrong with the initalization andthe preconfigured values (inputs) from the library are used.

    I found solutions for the issue "not being able to change the outputs, before a dump via linux shell":

    • quick and dirty: change the preconfigured value in the library for your needs. Use 16#FF for Inputs and 16#00 for outputs:
    IO_A : BYTE := 16#FF;
    IO_B : BYTE := 16#FF;
    
    • more usually one: reinitialize the port configuration on request. Add this code in the library to the case structure in the FB:
    10:
        IF REINIT THEN
            _iState := 0;
        END_IF
    

    Additionally you have to trigger/request the reinitialization of the configuration after the device is "operational". And if you want to you can change the polarity and wether the Port A/B is configured as input or output during runtime. Add this code or parts of it to your project:
    Declaration:

    RTRIG_operational: R_TRIG;
    xInitialized: BOOL;
    xReinitialze: BOOL;
    xSwitchIO: BOOL;
    xSwitchIO_old: BOOL;
    xInputPolarity: BOOL;
    xInputPolarity_old: BOOL;
    
    Button_1: BOOL;
    Button_2: BOOL;
    Button_3: BOOL;
    Button_4: BOOL;
    Button_5: BOOL;
    Button_6: BOOL;
    Button_7: BOOL;
    Button_8: BOOL;
    
    Rele_1: BOOL;
    Rele_2: BOOL;
    Rele_3: BOOL;
    Rele_4: BOOL;
    Rele_5: BOOL;
    Rele_6: BOOL;
    Rele_7: BOOL;
    Rele_8: BOOL;
    

    Code:

    RTRIG_operational(CLK:=MCP23017.Operational);
    
    IF NOT xInitialized AND RTRIG_operational.Q THEN
        xReinitialze := TRUE;
        xInitialized := TRUE;
    END_IF
    
    IF xSwitchIO <> xSwitchIO_old THEN
        xReinitialze := TRUE;
        xSwitchIO_old := xSwitchIO;
    END_IF
    
    IF xInputPolarity <> xInputPolarity_old THEN
        xReinitialze := TRUE;
        xInputPolarity_old := xInputPolarity;
    END_IF
    
    IF xReinitialze THEN
        IF NOT xSwitchIO THEN
            MCP23017.IO_A := 16#FF; // Input
            MCP23017.IO_B := 16#00; // Output
        ELSE
            MCP23017.IO_A := 16#00; // Output
            MCP23017.IO_B := 16#FF; // Input
        END_IF
        IF NOT xInputPolarity THEN
            MCP23017.IPOL_A := 16#00;   // Same
            MCP23017.IPOL_B := 16#00;   // Same
        ELSE
            MCP23017.IPOL_A := 16#FF;   // Opposite
            MCP23017.IPOL_B := 16#FF;   // Opposite
        END_IF
        MCP23017.REINIT := TRUE;
        xReinitialze := FALSE;
    END_IF
    
    IF NOT MCP23017.REINIT THEN
        IF NOT xSwitchIO THEN
            Button_1 := MCP23017.IN_A.0;
            Button_2 := MCP23017.IN_A.1;
            Button_3 := MCP23017.IN_A.2;
            Button_4 := MCP23017.IN_A.3;
            Button_5 := MCP23017.IN_A.4;
            Button_6 := MCP23017.IN_A.5;
            Button_7 := MCP23017.IN_A.6;
            Button_8 := MCP23017.IN_A.7;
    
            MCP23017.OUT_B.0 := Rele_1;
            MCP23017.OUT_B.1 := Rele_2;
            MCP23017.OUT_B.2 := Rele_3;
            MCP23017.OUT_B.3 := Rele_4;
            MCP23017.OUT_B.4 := Rele_5;
            MCP23017.OUT_B.5 := Rele_6;
            MCP23017.OUT_B.6 := Rele_7;
            MCP23017.OUT_B.7 := Rele_8;
        ELSE
            MCP23017.OUT_A.0 := Rele_1;
            MCP23017.OUT_A.1 := Rele_2;
            MCP23017.OUT_A.2 := Rele_3;
            MCP23017.OUT_A.3 := Rele_4;
            MCP23017.OUT_A.4 := Rele_5;
            MCP23017.OUT_A.5 := Rele_6;
            MCP23017.OUT_A.6 := Rele_7;
            MCP23017.OUT_A.7 := Rele_8;
    
            Button_1 := MCP23017.IN_B.0;
            Button_2 := MCP23017.IN_B.1;
            Button_3 := MCP23017.IN_B.2;
            Button_4 := MCP23017.IN_B.3;
            Button_5 := MCP23017.IN_B.4;
            Button_6 := MCP23017.IN_B.5;
            Button_7 := MCP23017.IN_B.6;
            Button_8 := MCP23017.IN_B.7;
        END_IF
    END_IF
    

    I tested this positively with the old library (posted from eschwellinger at 2021-11-27 https://forge.codesys.com/forge/talk/Runtime/thread/8981ce928a/?page=1&limit=25#1cc1) and with the new library (posted from elconfa at 2019-01-10 https://forge.codesys.com/forge/talk/Runtime/thread/a2dd4dd45f/#774c). Finally, I extended the new library so that the polarity switching of the inputs can be controlled with a variable:
    Declaration:

    IPOL_A: BYTE := 16#00;  // Port A configuration: 0=same/1=opposite (INPUT POLARITY PORT REGISTER)
    IPOL_B: BYTE := 16#00;  // Port B configuration: 0=same/1=opposite (INPUT POLARITY PORT REGISTER)
    

    Code:

    STATE := STATE AND write8(16#02,IPOL_A);    //  IPOL: INPUT POLARITY PORT REGISTER
                            //      1=GPIO register bit reflects the opposite logic state of the input pin.
                            //      0=GPIO register bit reflects the same logic state of the input pin.
    STATE := STATE AND write8(16#03,IPOL_B);    //  IPOL: INPUT POLARITY PORT REGISTER
                            //      1=GPIO register bit reflects the opposite logic state of the input pin.
                            //      0=GPIO register bit reflects the same logic state of the input pin.
    
     
    • rubendijk - 2023-04-04

      Nice job, What am I doing wrong here? I added the device and library. When adding the module it says the following.

       

      Last edit: rubendijk 2023-04-04

Log in to post a comment.