How to digitalWrite value for multiple PCF8574 Expanders in loop

Hello!
I want to use PFC8574 expander to control relays, but I have no idea how to use multiple expanders in a loop.
I read this
get a digitalRead value for multiple PCF8574 Expanders
and there is the solution for digitalRead.

My code for digitalWrites using Arduino, but I need more outputs.

void loop() {
  for (byte i = 0; i < noRelays; i++){
        if(debouncer[i].update()){
            byte value = debouncer[i].read();
            if(value == 0){
                Relays[i].relayState = !Relays[i].relayState;
                digitalWrite(Relays[i].relayPin, Relays[i].relayState? RELAY_ON:RELAY_OFF);
                send(msg[i].set(Relays[i].relayState? true : false) );
                saveState(i, Relays[i].relayState);
            }
        }
    }
}

@mojito_p, your topic has been moved to a more suitable location on the forum. Introductory Tutorials is for tutorials that e.g. you write, not for questions. Feel free to write a tutorial once you have solved your problem :wink:

Please post your complete code; is there already a PCF8574 involved?

Read this.

So, there is my whole sketch with MySensors. I have a problem with PCF8574 addresses array. IDE says: could not convert '{32, 33, 34, 35, 36, 37, 38, 39}' from brace-enclosed initializer list>' to 'PCF8574' in this line:

PCF8574 expa = {0x20, 0x21, 0x22, 0x23,0x24, 0x25, 0x26, 0x27};// expanders addresses
#define MY_DEBUG 
#define MY_GATEWAY_SERIAL
#if F_CPU == 8000000L
#define MY_BAUD_RATE 38400
#endif

#define MY_INCLUSION_MODE_FEATURE
#define MY_INCLUSION_BUTTON_FEATURE

#define MY_INCLUSION_MODE_DURATION 60 
#define MY_INCLUSION_MODE_BUTTON_PIN  3 


#include <SPI.h>
#include <MySensors.h>  
#include <Bounce2.h>
#include <SimpleTimer.h>
#include <PCF8574.h> // i/o expander ic library
#define RELAY_ON 0 // switch around for realy HIGH/LOW state
#define RELAY_OFF 1

#define MY_REPEATER_FEATURE

#define noRelays 1 // number of relays
const int buttonPin[] = {3}; // input button pins

PCF8574 expa = {0x20, 0x21, 0x22, 0x23,0x24, 0x25, 0x26, 0x27};// expanders addresses

const byte expaCount = sizeof expa/ sizeof expa[0];

class Relays {
    public:
        int buttonPin;
        //int relayPin;
        byte oldValue;
        boolean relayState;
};

SimpleTimer timer;
Relays Relay[noRelays]; 
Bounce debouncer[noRelays];
MyMessage msg[noRelays];

void setup() {
    delay(250);
    sendSketchInfo("My Switch Relay PCF8574", "1.0"); //MySensors Device Info
    delay(250);
    // For each port extender
    for (byte p = 0; p < expaCount; p++) {
        // Set all 8 pins on the port extender to OUTPUT
        for (byte i = 0; i < 8; i++) {
        expa[p].pinMode(i, OUTPUT);
        }
        //start the communication with the ic's
        expa[p].begin();
    }
    
    for (int i = 0; i < noRelays; i++) {
        Relay[i].buttonPin = buttonPin[i];
        msg[i].sensor = i;                // initialize messages
        msg[i].type = V_LIGHT;
        debouncer[i] = Bounce();            // initialize debouncer
        debouncer[i].attach(buttonPin[i]);
        debouncer[i].interval(5);
        pinMode(Relay[i].buttonPin, INPUT_PULLUP);
        Relay[i].relayState = loadState(i);

        send(msg[i].set(Relay[i].relayState? true : false) );  // make controller aware of last status
        present(i, S_LIGHT);              // present sensor to gateway
        delay(250);
    }
    for (int i = 0, int j = 0, k = 0; i < noRelays; i++, k++) {
        if (k > 8) {j++; k = 0;}
        if (Relay.relayState[i] = 0){
            expa[j].digitalWrite(k, LOW);
        }
        if (Relay.relayState[i] = 1){
            expa[j].digitalWrite(k, HIGH);
        }
    }
}

void loop() {
for (int i = 0, int j = 0, k = 0; i < noRelays; i++, k++) {
    if (k > 8) {j++; k = 0;}
    if(debouncer[i].update()){
        byte value = debouncer[i].read();
        if(value == 0){
            Relay[i].relayState = !Relay[i].relayState;
            send(msg[i].set(Relay[i].relayState? true : false) );
            serial.println(Relay[i].relayState);
            saveState(i, Relay[i].relayState);
        }
        
    }
    if (Relay.relayState[i] = 0){
        expa[j].digitalWrite(k, LOW);
    }
    if (Relay.relayState[i] = 1){
        expa[j].digitalWrite(k, HIGH);
    }
}
}

// process incoming message 
void receive(const MyMessage &message){
if (message.type == V_LIGHT){
    Relay[message.sensor].relayState = message.getBool(); 
    //digitalWrite(Relay[message.sensor].relayPin, LOW); // and set relays accordingly
    saveState( message.sensor, Relay[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
    //timer.setTimeout(500L, off);
    }

}

// void off(){
//     digitalWrite(Relay[message.sensor].relayPin, HIGH);
// }

do you sure that you soldered every single expansion module to one individual (unique) address?
what says I2C_scanner ?

expa is not an array; change it to

PCF8574 expa[] = {0x20, 0x21, 0x22, 0x23,0x24, 0x25, 0x26, 0x27};// expanders addresses

If you still have problems after that, please post the updated sketch (and the full error message if there are compiler/upload errors; use the copy error messages at the right in the orange bar).

I'm curious, will that work? Will the compiler understand that the hex values should be interpreted as parameters for the PCF8574 class constructor, resulting in an array of PCF8574 objects rather than an array of ints?

I'm pretty sure the below works, but if your suggestion works, it is much neater.

PCF8574 expa[] = {PCF8574(0x20), PCF8574(0x21),... PCF8574(0x27)};// expanders addresses
1 Like

You're right; I did not pay enough attention.

PCF8574 expa[] = {PCF8574(0x20), PCF8574(0x21),... PCF8574(0x27)};// expanders addresses

It worked, thanks a lot :smiley:

I made a whole sketch for MySensors gateway with PCF8574. It's compiling but I can't check it now. Waiting for a package with hardware.

#define MY_DEBUG 
#define MY_GATEWAY_SERIAL
#if F_CPU == 8000000L
#define MY_BAUD_RATE 38400
#endif

#define MY_INCLUSION_MODE_FEATURE
#define MY_INCLUSION_BUTTON_FEATURE

#define MY_INCLUSION_MODE_DURATION 60 
#define MY_INCLUSION_MODE_BUTTON_PIN  3 


#include <SPI.h>
#include <MySensors.h>  
#include <Bounce2.h>
#include <SimpleTimer.h>
#include <PCF8574.h> // i/o expander ic library
#define RELAY_ON 0 // switch around for realy HIGH/LOW state
#define RELAY_OFF 1

#define MY_REPEATER_FEATURE

#define noRelays 1 // number of relays
const int buttonPin[] = {3}; // input button pins

PCF8574 expa[] = {PCF8574(0x20), PCF8574(0x21), PCF8574(0x22), PCF8574(0x23), PCF8574(0x24), PCF8574(0x25), PCF8574(0x26), PCF8574(0x27)};// expanders addresses

const byte expaCount = sizeof expa/ sizeof expa[0];

class Relays {
    public:
        int buttonPin;
        byte oldValue;
        boolean relayState;
};

SimpleTimer timer;
Relays Relay[noRelays]; 
Bounce debouncer[noRelays];
MyMessage msg[noRelays];

void setup() {
    delay(250);
    sendSketchInfo("My Switch Relay PCF8574", "1.0"); //MySensors Device Info
    delay(250);
    for (int i = 0; i < expaCount; i++) {
            expa[i].begin();
    }
    int e, p = 0;
    for (int i = 0; i < noRelays; i++){
        Relay[i].buttonPin = buttonPin[i];
        msg[i].sensor = i;                // initialize messages
        msg[i].type = V_LIGHT;
        debouncer[i] = Bounce();            // initialize debouncer
        debouncer[i].attach(buttonPin[i]);
        debouncer[i].interval(5);
        Relay[i].relayState = loadState(i);
        send(msg[i].set(Relay[i].relayState? true : false) );  // make controller aware of last status
        present(i, S_LIGHT);              // present sensor to gateway
        delay(250);
        expa[e].write(p, Relay[i].relayState? RELAY_ON:RELAY_OFF);
        p++;
        if(p == 7){
            p = 0;
            e++;
        }
        
    }
}

void loop(){
    int e, p = 0;
    for(int i = 0; i < noRelays; i++) {
        if(debouncer[i].update()) {
            byte value = debouncer[i].read();
            if(value == 0){
                Relay[i].relayState = !Relay[i].relayState;
                expa[e].write(p, Relay[i].relayState? RELAY_ON:RELAY_OFF);
                send(msg[i].set(Relay[i].relayState? true : false) );
                saveState(i, Relay[i].relayState);
                p++;
                if(p == 7){
                    p = 0;
                    e++;
                }
            }
        
        }
    }
}

void receive(const MyMessage &message){
if (message.type == V_LIGHT){
    Relay[message.sensor].relayState = message.getBool(); 
    saveState( message.sensor, Relay[message.sensor].relayState );
    }

}

Why call .begin() 8 times for each multiplexer?

You're right the second loop is unnecessary. I'll edit code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.