multipbe IOExtender PCF8574

Hi,

i wanna control 4DC Motors and manage ther Speed by using each drive a 1203BB Module (H-Bridge dosent work with my drives).
To do that i uns a NodeMCU with ESP8266 and 2 of the PCF8574 IOExtender.

The PCF8574 are bit dificult to use for me and í need help.
For the drive controlers i need 4 ports of each Extender, thats why i have 2 of them.

No my Problem, i initilize the PCFs in my global code and use a own class to put the pin informations in it.
But i cant put a reference of the PCF object in the class.

If i try to put the PCF initialisation in myDrive class, i got address errors after first pin manipulation.
And if i init the PCF 4 times (for each drive controler) the pn manipulation works, but not correct because its bad to handle an i2c module in 2 obcets.

Does anyone have a idea to handel that ?

Example Code:

#include "PCF8574.h"

// Set i2c address
PCF8574 IOBank[2] = { 0x20, 0x21 };

class myDrive{
  private:
  public:
    int Bank, POT_UC, POT_INC, PIN_OnOff, PIN_UpDwn;
    String Direction;

    myDrive() { }
    myDrive( int arg1, int arg2, int arg3, int arg4, int arg5 )
    { 
      Bank = arg1;
      POT_UC = arg2;
      POT_INC = arg3;
      PIN_OnOff = arg4;
      PIN_UpDwn = arg5;
    }
};
myDrive DriveObj[5]{ {},
    { 0, 0, 1, 2, 3 },    // Drive 1: Bank0 , Pin 0-3
    { 0, 4, 5, 6, 7 },    // Drive 2: Bank0 , Pin 4-7
    { 1, 0, 1, 2, 3 },    // Drive 3: Bank1 , Pin 0-3
    { 1, 4, 5, 6, 7 }     // Drive 4: Bank1 , Pin 4-7
};

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("start Setup");

  // PCF8574 init
  int p;
  for( p=0; p<=7; p++ )
  {
    IOBank[0].pinMode(p, OUTPUT);
    IOBank[1].pinMode(p, OUTPUT);
  }
  IOBank[0].begin();
  IOBank[1].begin();
  
  // test once the direction Pins
  int d;
  for( d=1; d<=4; d++ )
  {
    Serial.print("\tDriveObj "); Serial.print(d); Serial.print("   PIN_OnOff: "); Serial.println(DriveObj[1].PIN_OnOff);
    IOBank[DriveObj[d].Bank].digitalWrite( DriveObj[d].PIN_UpDwn, 1 );
    delay(1000);
    IOBank[DriveObj[d].Bank].digitalWrite( DriveObj[d].PIN_UpDwn, 0 );
    delay(1000);
    IOBank[DriveObj[d].Bank].digitalWrite( DriveObj[d].PIN_UpDwn, 1 );
  }
  
  Serial.println("Setup done");
}

void loop() {
  
}

the following doesn't look right. it makes sense to create 2 instances of the PCF8574, but it doesn't make sense to initialize them to two integer values

PCF8574 IOBank[2] = { 0x20, 0x21 };

see how two instances: PCF_38 and PCF_39 are created in PCF8574Class

hmm ?
Thats what i describe, i have two modules.
And ech module i have to initialize them.

is in your example the same =>
....
PCF8574 PCF_38(0x38); // add switches to lines (used as input)
PCF8574 PCF_39(0x39); // add LEDs to lines (used as output)
....

The different between my solution is, that i put the object instances in one array.

Where you see integer values ??? oO
Anyway, my example code works, thats not the problem.

I only need a way to put an object referenz in a class.
Or a way to use a pointer of an object in a array, eG.

PCF8574 Instance1 (0x20);
PCF8574 Instance1 (0x21);
PCF8574 myArray[4];
myArray[0] = Instance1;
myArray[1] = Instance1;
myArray[2] = Instance2;
myArray[3] = Instance2;

But that dosent work right, because if i change a output bit in myArray[0] and after that another output bit in myArray[0], then the first change is overwritten.

My C++ is not good enougth to handle pointers and references, thats why i need help.

many thanks in advance

myArray[0] = Instance1;
myArray[1] = Instance1;

why are you setting two array elements to the same instance?

because to ittarate the drives

Drive#1 got 4 Pins (0-3) on PCF8574 #1 (0x20)
Drive#2 got 4 Pins (4-7) on PCF8574 #1 (0x20)
Drive#3 got 4 Pins (0-3) on PCF8574 #2 (0x21)
Drive#4 got 4 Pins (4-7) on PCF8574 #2 (0x21)

as special i use a 3Achses Gyro MPU6050 because all drives run in different speed (thats my root problem).
for my program logic is it for me the easiest way to handle all drives in seperate objects.

nobody who can help me to use pointer ?

Kay_L:
My C++ is not good enougth to handle pointers and references, thats why i need help.

i don't understand what you're thinking, why you have two arrays elements to the same instance of an object?

the pcf8574 has 8 pins. if you connect those 8 pins to 2 different h-bridges, you need to keep track of which pins are controlling which h-bridge on each instance of the pcs8574.

I would probably define the myDrive class to include a (private) instance of an PCF8574 object.

Or, perhaps, have myDrive inherit from PCF8574 .

gfvalvo:
I would probably define the myDrive class to include a (private) instance of an PCF8574 object.

Or, perhaps, have myDrive inherit from PCF8574.

how would you share the same instance of PCF8574 between separate instances of myDrive?

gcjr:
how would you share the same instance of PCF8574 between separate instances of myDrive?

I'd design myDrive to handle both sets of 2 x 4 pins of the PCF8574 instance. Calls to myDrive functions would include an argument specifying which set to manipulate.

so your mydrive would support 2 h-bridges?

Yup.

gcjr:
the following doesn't look right. it makes sense to create 2 instances of the PCF8574, but it doesn't make sense to initialize them to two integer values

PCF8574 IOBank[2] = { 0x20, 0x21 };

see how two instances: PCF_38 and PCF_39 are created in PCF8574Class

gcjr:
the following doesn't look right. it makes sense to create 2 instances of the PCF8574, but it doesn't make sense to initialize them to two integer values

PCF8574 IOBank[2] = { 0x20, 0x21 };

see how two instances: PCF_38 and PCF_39 are created in PCF8574Class

You can create the objects like this:

PCF8574 IOBank[2] = {PCF8574(0x20), PCF8574(0x21)};

gfvalvo:
I would probably define the myDrive class to include a (private) instance of an PCF8574 object.

Or, perhaps, have myDrive inherit from PCF8574 .

and how ?
could you please post an example ?
thank you

what's not obvious to me, is how to create a class to control a single h-bridge that requires 3 pins using a class that control 8 pins. It makes sense to perhaps inherits from a class that knows how to control a PCF8574 but specify which pins to use perhaps for each pin, a device and pin

gcjr:
what's not obvious to me, is how to create a class to control a single h-bridge that requires 3 pins using a class that control 8 pins. It makes sense to perhaps inherits from a class that knows how to control a PCF8574 but specify which pins to use perhaps for each pin, a device and pin

Like I said, I'd create a class each instance of which runs a single PCF8574 that controls 2 H-Bridges.

@Kay_L, is this the PCF8574 library you're using?

gfvalvo:
Like I said, I'd create a class each instance of which runs a single PCF8574 that controls 2 H-Bridges.

Something like this. I simplified things by using static assignments of pins to functions. You can make that more flexible if desired. This code compiles but is untested due to lack of PCF8574 devices.

#include <PCF8574.h>

class MyDrive {
  public:
    MyDrive(uint8_t addr)  : expander(addr) {}
    void begin();
    bool setPin(uint8_t bank, uint8_t pin, uint8_t value);

    static const uint8_t potUc = 0;
    static const uint8_t potInc = 1;
    static const uint8_t pinOnOff = 2;
    static const uint8_t pinUpDown = 3;

  private:
    PCF8574 expander;

};

void MyDrive::begin() {
  expander.begin();
  for (uint8_t i = 0; i < 8; i++) {
    expander.pinMode(i, OUTPUT);
  }
}

bool MyDrive::setPin(uint8_t bank, uint8_t pin, uint8_t value) {
  if (bank > 1) {
    return false;
  }
  if (pin > pinUpDown) {
    return false;
  }

  if (value) {
    expander.digitalWrite(pin + 4 * bank, 1);
  } else {
    expander.digitalWrite(pin + 4 * bank, 0);
  }
  return true;
}

MyDrive drives[] = {0x20, 0x21};
const uint8_t numDrives = sizeof(drives) / sizeof(drives[0]);

void setup() {
  for (uint8_t i = 0; i < numDrives; i++) {
    drives[i].begin();
  }

  for (uint8_t i = 0; i < numDrives; i++) {
    for (uint8_t bank = 0; bank < 2; bank++) {
      drives[i].setPin(bank, MyDrive::pinUpDown, 1);
      delay(1000);
      drives[i].setPin(bank, MyDrive::pinUpDown, 0);
      delay(1000);
      drives[i].setPin(bank, MyDrive::pinUpDown, 1);
    }
  }
}

void loop() {
}

Hi,

sorry my late answer, but i´ve had a bunch of todo´s :-/

no, i use this one =>

gfvalvo:
@Kay_L, is this the PCF8574 library you're using?
Arduino/libraries/PCF8574 at master · RobTillaart/Arduino · GitHub

Kay_L:
no, i use this one =>
GitHub - xreef/PCF8574_library: PCF8574 library. i2c digital expander for Arduino, Raspberry Pi Pico and rp2040 boards, esp32, SMT32 and ESP8266. Can read write digital values with only 2 wire. Very simple to use and encoder support.

Doesn't matter. The concept would be the same as what I showed in Reply #16.

ah thanks, i will try and give a feedback :slight_smile: