0

Currently, I have two, 2-Channel 1 Amp SPDT Signal Relay Controllers connected to my Raspberry Pi 3 via I2C, and when I currently run the function to turn one relay on, the other one will shut off at the same time (one or the other is on). In addition, my button to shut off relay 1 and my button to shut off relay 2 will shut both relays off.

My program is written in a windows form (visual studio), and I am accessing a C Shared Library via Dll Import, but I know for a fact my problem is within my C library. I am very new to C and how shifting works, so the root of my problem lies within the logic and structure of my code. Frankly, I'm confused on how to properly code this.

This is currently the method to turn Relay 1 On. It turns the relay on properly, but this also turns Relay 2 Off at the same time.

void Relay1On() ***CURRENTLY TURNS OTHER OFF WHEN ACTIVATED***
{
    // Create I2C bus
    int file;
    char *bus = "/dev/i2c-1";
    if ((file = open(bus, O_RDWR)) < 0) 
    {
        printf("Failed to open the bus. \n");
        exit(1);
    }
    // Get I2C device, MCP23008 I2C address is 0x20(32)
    ioctl(file, I2C_SLAVE, 0x20);

    // Configure all pins of port as output (0x00)
    char config[2] = {0};
    config[0] = 0x00;
    config[1] = 0x00;
    write(file, config, 2);

    //Turn the first relay on
    char data = 0x01;
    config[0] = 0x09;
    config[1] = data;
    write(file, config, 2);

}

Here is the code for Relay 1 Off, I will not post Relay 2 On/Off because it is basically the same, Relay2On just has an added data += 1; after char data = 0x01;. Both 'Off' methods result in both relays shutting off.

void Relay1Off()
{
    // Create I2C bus
    int file;
    char *bus = "/dev/i2c-1";
    if ((file = open(bus, O_RDWR)) < 0) 
    {
        printf("Failed to open the bus. \n");
        exit(1);
    }
    // Get I2C device, MCP23008 I2C address is 0x20(32)
    ioctl(file, I2C_SLAVE, 0x20);

    // Configure all pins of port as output (0x00)
    char config[2] = {0};
    config[0] = 0x00;
    config[1] = 0x00;
    write(file, config, 2);

    //Turn the first relay off *****Turns all off at the moment******
    char data = 0xFE;
    data = (data << 1);
    config[0] = 0x09;
    config[1] = data;
    write(file, config, 2);
}

All I want is the methods to do as described, turn Relay 1 On when the method is called. When Relay1Off is called, shut only Relay 1 off. I'm sure it is simple, but as I've stated above C is quite new to me.

Thank you in advance for any contribution.

  • If you try to turn relay 2 on and off, does it also affect relay 1, only do relay 2, or do nothing? – Thomas Jager Jul 17 '19 at 20:29
  • @ThomasJager Turning Relay 2 on will shut Relay 1 Off, yes. Shutting Relay 2 off results in the same result as shutting Relay 1 Off - Both are powered off. I can post the Code for the Relay 2 functions if that would help better –  Jul 17 '19 at 20:48
  • dumb question, do they have the same I2C address? – yhyrcanus Jul 17 '19 at 21:05
  • @yhyrcanus yes they do, the two relays are on one board. The one board has an address of 0x20 –  Jul 17 '19 at 21:06
  • 2
    Wait, MCP23008 is an IO expander. The relays themselves aren't I2C devices. You probably want to use bitwise math with the data, instead of just equaling it. Every time, you're SETTING the bits to be 10 or 01 or 00. If you kept the status of what relays are activated, you could OR it/AND it with a mask to turn both on/just the one you want off. – yhyrcanus Jul 17 '19 at 21:13
  • In your second example, the value of data will be 0xFC (i.e., the bottom two bits are zero). If command 0x09 takes the second byte and sets the output state of both relays (likely), then your code will turn both of them off. If you want to set the relays individually, then you'll either need to keep track of the state yourself or use a different command. Also, you'll want to call `close(file)` at the end of each function. – bdowling Jul 17 '19 at 21:16
  • @yhyrcanus My apologies, that's just what the board says on it. Here is the board: [link](https://store.ncd.io/product/mcp3427-16-bit-2-channel-analog-to-digital-converter-i2c-mini-module/) Thank you for that suggestion, I'll give it a try. I don't understand how to turn just one relay off though. –  Jul 17 '19 at 21:19
  • You need to maintain your own variable to keep a record of the desired state of each relay. You should then either set or clear an individual bit in that variable to turn a particular relay on or off. You send the contents of that variable to your I2C device - you can't individually control just one at a time - you need to figure out the state you want them both to be in and then send that. – brhans Jul 17 '19 at 21:22
  • @brhans thank you for the suggestion –  Jul 17 '19 at 21:23

1 Answers1

0

I don't know how the fancy ioctl stuff works, but I'd try to do all initialization outside of this function, including setting all the GPIO's to output.

You should probably just have one function call to set/clear a relay. I'd do something like this to start:

void RelayOnOff(unsigned char relay, unsigned char enable)
{
    //Init to all off
    static unsigned char data = 0x00;
    ...  
    if (enable){
        data |= ( 1 << relay );
    }
    else{
        data &= ~( 1 << relay );
    }
    config[0] = 0x09;
    config[1] = data;
    write(file, config, 2);
}

You pass in what relay you want to control, and a boolean value for enable/disable. If you make the data variable static, it'll "remember" that value from function call to function call. The enable/disable sets/clears the bit for whatever relay you pass in (0-7).

yhyrcanus
  • 3,743
  • 2
  • 23
  • 28
  • Basically ioctl is just a method to find a device and configure it to output or input, from my understanding (which is minimal). Thank you for the answer though –  Jul 18 '19 at 13:25