Using the PCF8574 expander on a MidiUSB project

Hello!

I would like to use the PCF8574 I/O expander with my Nano ESP32.
I'm trying to control a midi note button through the expander but I'm unable to assign the input to the button. The button is connected to the pin P0 of the expander.
Could you please help?
Please see the schematic and sketch attached.


#include <Control_Surface.h>
#include "PCF8574.h"

PCF8574 pcf8574(0x20); 

USBMIDI_Interface midi;

using namespace MIDI_Notes;

NoteButton button1 = {
  ????,         // Push button on pin
  {note(Ab, -1), CHANNEL_1}, // Note on MIDI channel 
};


void setup() {

  pcf8574.begin();
  
pinMode(P0, INPUT); ///????
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);

  Control_Surface.begin(); 

}

void loop() {

     Control_Surface.loop();

}

Thank you

Sorry I am not familiar with your libraries. I simply write a 1 to the appropriate bit that I want as an input. I then read the port and when the switch is closed that bit will be zero otherwise it will be a 1.

Me neither, but it looks like the library may have to be modified in order to be able to use a port expander.

Nope it is only a few lines:

#define PCF8574_ADDR 0x20

// This gets called from setup to initialize the port
void initializePCF8574() {
  // Configure all pins as inputs by writing 0xFF to the PCF8574
  Wire.beginTransmission(PCF8574_ADDR);
  Wire.write(0xFF); // Set all pins as inputs (pull-up resistors are enabled by default)
  Wire.endTransmission();
}

//This fnction will return the port value, call from anywhere
uint8_t readPCF8574() {
  Wire.beginTransmission(PCF8574_ADDR);
  Wire.endTransmission();
  Wire.requestFrom(PCF8574_ADDR, 1); // Request 1 byte from PCF8574

  if (Wire.available()) {
    return Wire.read(); // Read and return the byte (input values of all 8 pins)
  }
  
  return 0xFF; // Return 0xFF if no data is available (indicating an error)
}
Have fun!

I'm sure your code will work to read the pin, but...

I agree with @rsmls. The Control_Surface library will work only with native Arduino pins, not the pins of a pcf857x chip or any other I/o expander (unless you modify the library).

The op only wanted read, for write it is just as simple:

void writePCF8574(uint8_t data) {
  Wire.beginTransmission(PCF8574_ADDR);
  Wire.write(data); // Write the byte to the PCF8574
  Wire.endTransmission();
}

No, the op wants the NoteButton class from the Control_Suface library to work with a pin of an I/o expander , but it expects to be given an Arduino pin number. There is no pin number you could give it that would make it read the pin on the I/o expander.

EDIT: there may be hope after all. See below.

Hmmm...

Just found this:

In projects with large numbers of inputs and outputs, Control Surface allows you to seamlessly add multiplexers, shift registers and other port expanders, and treat them as if they were ordinary GPIO pins.

I also found this in the Control_Surface documentation:

https://tttapa.github.io/Control-Surface-doc/Doxygen/d5/dd2/classAH_1_1MCP23017.html#details

It may be that it only works with mcp23017 chips, and not pcf8574.

The MCP23017 class defined in the library has a .pin() method with returns an "extended pin number" which might be used with the NoteButton class.

Need to find some example code...

EDIT: here's some example code

https://tttapa.github.io/Control-Surface-doc/Doxygen/d3/db1/MCP23017_8ino-example.html

There are two main options:

  1. Add a PCF78574 class similar to the MCP23017 class mentioned above. This allows you to use most of the Control Surface library's features, like NoteButton. You can use this (incomplete and untested) implementation as a starting point: PCF8574 Digital I/O Port Expander (with toggle Buttons and KY-040 Digital Encoder) · Issue #329 · tttapa/Control-Surface · GitHub
  2. Poll the PCF8574 yourself, and call Control_Surface.sendNoteOn(...) manually. See the library's examples for details, e.g. Control Surface: MIDI-Output.ino, Control Surface: MIDI Tutorial.
2 Likes