Включение одного реле, подключенного к Raspberry Pi I2C, выключает другое реле

В настоящее время у меня есть два 2-канальных контроллера сигнальных реле SPDT на 1 ампер, подключенных к моему Raspberry Pi 3 через I2C, и когда я сейчас запускаю функцию для включения одного реле, другое отключается одновременно (одно или другой включен). Кроме того, моя кнопка для отключения реле 1 и моя кнопка для отключения реле 2 отключат оба реле.

Моя программа написана в форме Windows (визуальная студия), и я получаю доступ к общей библиотеке C через импорт Dll, но я точно знаю, что моя проблема находится в моей библиотеке C. Я очень новичок в C и в том, как работает смещение, поэтому корень моей проблемы лежит в логике и структуре моего кода. Честно говоря, я запутался в том, как правильно кодировать это.

В настоящее время это метод включения реле 1. Это правильно включает реле, но одновременно выключает реле 2.

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);

}

Вот код для выключения реле 1, я не буду публиковать включение/выключение реле 2, потому что это в основном то же самое, в Relay2On просто добавлено data += 1; после char data = 0x01;. Оба метода «Выкл.» приводят к отключению обоих реле.

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);
}

Все, что я хочу, это сделать методы, как описано, включить реле 1 при вызове метода. При вызове Relay1Off отключите только реле 1. Я уверен, что это просто, но, как я уже говорил выше, C для меня совершенно новый.

Заранее благодарим вас за любой вклад.


person Community    schedule 17.07.2019    source источник
comment
Если вы попытаетесь включить и выключить реле 2, повлияет ли это на реле 1, только на реле 2 или ничего не произойдет?   -  person Thomas Jager    schedule 17.07.2019
comment
@ThomasJager Включение реле 2 отключит реле 1, да. Отключение реле 2 приводит к тому же результату, что и отключение реле 1 — питание обоих отключено. Я могу опубликовать код для функций реле 2, если это поможет лучше   -  person    schedule 17.07.2019
comment
глупый вопрос, у них одинаковый адрес I2C?   -  person yhyrcanus    schedule 18.07.2019
comment
@yhyrcanus да, два реле на одной плате. Одна плата имеет адрес 0x20   -  person    schedule 18.07.2019
comment
Подождите, MCP23008 — это расширитель ввода-вывода. Сами реле не являются устройствами I2C. Вы, вероятно, захотите использовать побитовую математику с данными, а не просто приравнивать их. Каждый раз вы УСТАНАВЛИВАЕТЕ биты равными 10, 01 или 00. Если вы сохранили статус того, какие реле активированы, вы могли бы ИЛИ это/И это с маской, чтобы включить оба / только то, которое вы хотите выключить.   -  person yhyrcanus    schedule 18.07.2019
comment
Во втором примере значение данных будет 0xFC (т. е. нижние два бита равны нулю). Если команда 0x09 берет второй байт и устанавливает состояние вывода обоих реле (вероятно), то ваш код выключит их оба. Если вы хотите настроить реле по отдельности, вам нужно либо самостоятельно отслеживать состояние, либо использовать другую команду. Кроме того, вы захотите вызывать close(file) в конце каждой функции.   -  person bdowling    schedule 18.07.2019
comment
@yhyrcanus Приношу свои извинения, это именно то, что написано на доске. Вот плата: ссылка Спасибо за это предложение, я попробую. Я не понимаю, как отключить только одно реле.   -  person    schedule 18.07.2019
comment
Вам нужно поддерживать свою собственную переменную, чтобы вести запись желаемого состояния каждого реле. Затем вы должны либо установить, либо сбросить отдельный бит в этой переменной, чтобы включить или выключить конкретное реле. Вы отправляете содержимое этой переменной на свое устройство I2C — вы не можете индивидуально управлять только одним за раз — вам нужно выяснить состояние, в котором вы хотите, чтобы они оба находились, а затем отправить его.   -  person brhans    schedule 18.07.2019
comment
@brhans спасибо за предложение   -  person    schedule 18.07.2019


Ответы (1)


Я не знаю, как работает причудливый ioctl материал, но я бы попытался выполнить всю инициализацию вне этой функции, включая настройку всех GPIO для вывода.

Вероятно, у вас должен быть только один вызов функции для установки/сброса реле. Я бы сделал что-то вроде этого, чтобы начать:

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);
}

Вы передаете, какое реле вы хотите контролировать, и логическое значение для включения/выключения. Если вы сделаете переменную данных статической, она «запомнит» это значение от вызова функции до вызова функции. Включение/отключение устанавливает/очищает бит для любого реле, которое вы передаете (0-7).

person yhyrcanus    schedule 17.07.2019
comment
По сути, ioctl — это просто способ найти устройство и настроить его для вывода или ввода, насколько я понимаю (что минимально). Хотя спасибо за ответ - person ; 18.07.2019