HELP: PCF8575 Port Expander was PCF8574

Hi all
I would like to free up some pins on my Uno R3, i have 3 input buttons
button 1 = Audio Filter switch, has 4 output pins
button 2 = RF Att switch, has 5 output pins
button 3 = Mode switch, has 4 output pins

I would like to use a i2c port expander but not sure which one to use, think a 16 port one might be ok.
The problem is i don’t know how to change the code that i have, the port expander outputs must
go high on select.

Can anyone help with code??
Howard
Here is my code:

//***Audio Filter, RF Att and Mode button ATMega328 OK***
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address to 0x27 for a 20 chars and 4 line display

const int switchPin0 = 2;    // set up a constant for the Audio Filter switch
int switchState = 0;         // variable to hold the value of the switchpin
int prevSwitchState = 0;     // variable to hold previous value of the switchpin
int buttonPushCounter = 0;   // counter for the number of button presses

const int switchPin1 = 3;    // set up a constant for the RF Att switch
int switchState1 = 0;        // variable to hold the value of the switchpin
int prevSwitchState1 = 0;    // variable to hold previous value of the switchpin
int buttonPushCounter1 = 0;  // counter for the number of button presses

const int switchPin2 = 4;    // set up a constant for the Mode switch
int switchState2 = 0;        // variable to hold the value of the switchpin
int prevSwitchState2 = 0;    // variable to hold previous value of the switchpin
int buttonPushCounter2 = 0;  // counter for the number of button presses

void setup() {
  lcd.begin(20, 4);                 // set up the number of columns and rows on the LCD
  pinMode(switchPin0,INPUT);        // set up the switch pin as an input
  digitalWrite(switchPin0, HIGH);   // turn on pullup resistor
  pinMode(switchPin1,INPUT);        // set up the switch pin as an input
  digitalWrite(switchPin1, HIGH);   // turn on pullup resistor
  pinMode(switchPin2,INPUT);        // set up the switch pin as an input
  digitalWrite(switchPin2, HIGH);   // turn on pullup resistor
  //Setup Filter Outputs
  pinMode(A0, OUTPUT);  //Initiates off pin 
  pinMode(A1, OUTPUT);  //Initiates 1.5Khz pin 
  pinMode(A2, OUTPUT);  //Initiates 2.0Khz pin
  pinMode(A3, OUTPUT);  //Initiates 2.5Khz pin
  //Setup rf att Outputs
  pinMode(9, OUTPUT);   //Initiates Off pin 
  pinMode(10, OUTPUT);  //Initiates -10dB pin 
  pinMode(11, OUTPUT);  //Initiates -20dB pin
  pinMode(12, OUTPUT);  //Initiates -30dB pin
  pinMode(13, OUTPUT);  //Initiates +10dB pin
  //Setup mode Outputs
  pinMode(5, OUTPUT);   //Initiates AM pin 
  pinMode(6, OUTPUT);   //Initiates FM pin 
  pinMode(7, OUTPUT);   //Initiates LSB pin
  pinMode(8, OUTPUT);   //Initiates USB pin
}
void loop()
{
  switchState = digitalRead(switchPin0);    //check the status of the switc
  if (switchState != prevSwitchState)       //compare the switchState to its previous state
  {
    if (switchState == LOW)                 //If the switch is pressed, count the press
    {
      buttonPushCounter ++;  
      buttonPushCounter %= 4;
    }
    lcd.clear();                            //clean up the screen before printin
  }
  switch (buttonPushCounter)
  {
  case 0:
    lcd.setCursor(0, 0);
    lcd.print("OFF");
    digitalWrite(A0, HIGH);                 //Output ON
    digitalWrite(A1, LOW);                  //Output off
    digitalWrite(A2, LOW);                  //Output off
    digitalWrite(A3, LOW);                  //Output off
    break;
  case 1:
    lcd.setCursor(0, 0);
    lcd.print("1.5K");
    digitalWrite(A0, LOW);                  //Output off
    digitalWrite(A1, HIGH);                 //Output ON
    digitalWrite(A2, LOW);                  //Output off
    digitalWrite(A3, LOW);                  //Output off
    break;
  case 2:
    lcd.setCursor(0, 0);
    lcd.print("2.0K");
    digitalWrite(A0, LOW);                  //Output off
    digitalWrite(A1, LOW);                  //Output off
    digitalWrite(A2, HIGH);                 //Output ON
    digitalWrite(A3, LOW);                  //Output off
    break;
  case 3:
    lcd.setCursor(0, 0);
    lcd.print("2.5K");
    digitalWrite(A0, LOW);                  //Output off
    digitalWrite(A1, LOW);                  //Output off
    digitalWrite(A2, LOW);                  //Output off
    digitalWrite(A3, HIGH);                 //Output ON
    break;
  }
  prevSwitchState = switchState;            //save the current switch state as the last state
  switchState1 = digitalRead(switchPin1);   //check the status of the switch
  if (switchState1 != prevSwitchState1)     //compare the switchState to its previous state
  {   
    if (switchState1 == LOW)                //If the switch is pressed, count the press
    {
      buttonPushCounter1 ++;
      buttonPushCounter1 %= 5;
    } 
    lcd.clear();                            //clean up the screen before printin
  }
  switch (buttonPushCounter1)
  {
  case 0:
    lcd.setCursor(7, 0);
    lcd.print("0dB");
    digitalWrite(9, LOW);                   //Output off 
    digitalWrite(10, LOW);                  //Output off 
    digitalWrite(11, LOW);                  //Output off 
    digitalWrite(12, LOW);                  //Output off 
    digitalWrite(13, LOW);                  //Output off 
    break;
  case 1:
    lcd.setCursor(7, 0);
    lcd.print("-10dB");
    digitalWrite(9, LOW);                   //Output off
    digitalWrite(10, HIGH);                 //Output ON
    digitalWrite(11, LOW);                  //Output off
    digitalWrite(12, LOW);                  //Output off
    digitalWrite(13, LOW);                  //Output off
    break;
  case 2:
    lcd.setCursor(7, 0);
    lcd.print("-20dB");
    digitalWrite(9, LOW);                   //Output off
    digitalWrite(10, HIGH);                 //Output ON
    digitalWrite(11, HIGH);                 //Output ON
    digitalWrite(12, LOW);                  //Output off
    digitalWrite(13, LOW);                  //Output off
    break;
  case 3:
    lcd.setCursor(7, 0);
    lcd.print("-30dB");
    digitalWrite(9, LOW);                   //Output off
    digitalWrite(10, HIGH);                 //Output ON
    digitalWrite(11, HIGH);                 //Output ON
    digitalWrite(12, HIGH);                 //Output ON
    digitalWrite(13, LOW);                  //Output off
    break;
  case 4:
    lcd.setCursor(7, 0);
    lcd.print("+10dB");
    digitalWrite(9, LOW);                   //Output off
    digitalWrite(10, LOW);                  //Output off
    digitalWrite(11, LOW);                  //Output off
    digitalWrite(12, LOW);                  //Output off
    digitalWrite(13, HIGH);                 //Output ON
    break;
  }
  prevSwitchState1 = switchState1;          //save the current switch state as the last state
  switchState2 = digitalRead(switchPin2);   //check the status of the switc
  if (switchState2 != prevSwitchState2)     //compare the switchState to its previous state
  {
    if (switchState2 == LOW)                //If the switch is pressed, count the press
    {
      buttonPushCounter2 ++;  
      buttonPushCounter2 %= 4;
    }
    lcd.clear();                            //clean up the screen before printin
  }    
  switch (buttonPushCounter2)
  {
  case 0:
    lcd.setCursor(15, 0);
    lcd.print("AM");
    digitalWrite(5, HIGH);                  //Output ON
    digitalWrite(6, LOW);                   //Output off
    digitalWrite(7, LOW);                   //Output off
    digitalWrite(8, LOW);                   //Output off
    break;
  case 1:
    lcd.setCursor(15, 0);
    lcd.print("FM");
    digitalWrite(5, LOW);                   //Output off
    digitalWrite(6, HIGH);                  //Output ON
    digitalWrite(7, LOW);                   //Output off
    digitalWrite(8, LOW);                   //Output off
    break;
  case 2:
    lcd.setCursor(15, 0);
    lcd.print("LSB");
    digitalWrite(5, LOW);                   //Output off
    digitalWrite(6, LOW);                   //Output off
    digitalWrite(7, HIGH);                  //Output ON
    digitalWrite(8, LOW);                   //Output off
    break;
  case 3:
    lcd.setCursor(15, 0);
    lcd.print("USB");
    digitalWrite(5, LOW);                   //Output off
    digitalWrite(6, LOW);                   //Output off
    digitalWrite(7, LOW);                   //Output off
    digitalWrite(8, HIGH);                  //Output ON
    break;
  }
  prevSwitchState2 = switchState2;  // save the current switch state as the last state  
}

i have 3 input buttons button 1 = Audio Filter switch, has 4 output pins

This needs some clarification. An INPUT has ONE input, and no outputs.

the port expander outputs must go high on select.

On select of what? By what?

i have 3 input buttons button 1 = Audio Filter switch, has 4 output pins

Should be, button 1 = Audio Filter switch

the port expander outputs must go high on select.

Should be, the port expander outputs must go high on button press.

Howard

const int switchPin0 = 2;    // set up a constant for the Audio Filter switch
int switchState = 0;         // variable to hold the value of the switchpin
int prevSwitchState = 0;     // variable to hold previous value of the switchpin
int buttonPushCounter = 0;   // counter for the number of button presses

const int switchPin1 = 3;    // set up a constant for the RF Att switch
int switchState1 = 0;        // variable to hold the value of the switchpin
int prevSwitchState1 = 0;    // variable to hold previous value of the switchpin
int buttonPushCounter1 = 0;  // counter for the number of button presses

const int switchPin2 = 4;    // set up a constant for the Mode switch
int switchState2 = 0;        // variable to hold the value of the switchpin
int prevSwitchState2 = 0;    // variable to hold previous value of the switchpin
int buttonPushCounter2 = 0;  // counter for the number of button presses

Whenever you find yourself appending numeric suffixes to variable names, you should think arrays, instead.

On the other hand, these names are crappy. audioSwitchPin, rfSwitchPin, and modeSwitchPin make a lot more sense. Corresponding changes to the state and counter names are in order, too.

Should be, the port expander outputs must go high on button press.

Press one of the 3 switches and all expander outputs should go HIGH? I don't think that's what you mean. I think that your problem with writing the code stems from not understanding, or not clearly defining, the requirements. Getting working code starts with getting usable requirements.

If you can explain what you want to happen when one switch is pressed (or is that becomes pressed?), then we can probably help you with the code.

On the other hand, these names are crappy. audioSwitchPin, rfSwitchPin, and modeSwitchPin make a lot more sense. Corresponding changes to the state and counter names are in order, too.

Like this ??

const int audioSwitchPin = 2;    // set up a constant for the Audio Filter switch
int audioSwitchState = 0;             // variable to hold the value of the switchpin
int prevaudioSwitchState = 0;         // variable to hold previous value of the switchpin
int audiobuttonPushCounter = 0;       // counter for the number of button presses

Press one of the 3 switches and all expander outputs should go HIGH? I don't think that's what you mean

I will try to explain what happens when one switch is pressed (audioSwitchPin) This button has a counter that counts the number of times it is pressed, each press has a case output

case 0:
    lcd.setCursor(0, 0);
    lcd.print("OFF");                     //Print to LCD
    digitalWrite(A0, HIGH);                 //Output ON
    digitalWrite(A1, LOW);                  //Output off
    digitalWrite(A2, LOW);                  //Output off
    digitalWrite(A3, LOW);                  //Output off
    break;
  case 1:
    lcd.setCursor(0, 0);
    lcd.print("1.5K");                     //Print to LCD
    digitalWrite(A0, LOW);                  //Output off
    digitalWrite(A1, HIGH);                 //Output ON
    digitalWrite(A2, LOW);                  //Output off
    digitalWrite(A3, LOW);                  //Output off
    break;
  case 2:
    lcd.setCursor(0, 0);
    lcd.print("2.0K");                    //Print to LCD
    digitalWrite(A0, LOW);                  //Output off
    digitalWrite(A1, LOW);                  //Output off
    digitalWrite(A2, HIGH);                 //Output ON
    digitalWrite(A3, LOW);                  //Output off
    break;
  case 3:
    lcd.setCursor(0, 0);
    lcd.print("2.5K");                    //Print to LCD
    digitalWrite(A0, LOW);                  //Output off
    digitalWrite(A1, LOW);                  //Output off
    digitalWrite(A2, LOW);                  //Output off
    digitalWrite(A3, HIGH);                 //Output ON
    break;
  }

I would like the port expander outputs to switch the same way, only one pin go high at a time in this case (audioSwitchPin). The other switch's have different case settings. Howard

I would like the port expander outputs to switch the same way, only one pin go high at a time in this case (audioSwitchPin).

No problem. Pick a port expander, and we can go from there.

Pick a port expander, and we can go from there.

Well i was thinking of a PCF8575

Howard

Well i was thinking of a PCF8575

http://forum.arduino.cc/index.php/topic,21977.0.html

The PCF8575 can sink approx. 25ma, but only source approx. 5 ma

I was going to use the outputs of the PCF8575 to drive 2 of UDN2981 relay driver chips that need a high on there inputs. Would the PCF8575 do the job ??

Howard

I was going to use the outputs of the PCF8575 to drive 2 of UDN2981 relay driver chips

With this chip requiring a maximum of 200uA on the input what is the problem?

With this chip requiring a maximum of 200uA on the input what is the problem?

Which chip ?

Howard

G7LQY:

With this chip requiring a maximum of 200uA on the input what is the problem?

Which chip ?

Howard

The chip you are trying to drive with your PCF8574 the UND2981.

Hi
been having a go at getting the code to control a PCF8575 port expander, but not got
the PCF8575 yet!
Trying to work out how to get 1 button (audioSwitchPin) to switch 4 independent outputs and print
on lcd “OFF” “1.5Khz” “2.0Khz” “2.5Khz”, i used to do it with buttoncounter and case commands
but not sure now.
this is a test code, it might work

Howard

#include <Wire.h>

const int audioSwitchPin = 2;  // set up a constant for the Audio Filter switch
int audioSwitchState = 0;      // variable to hold the value of the switchPin

void setup() {
  Wire.begin();   // wake up I2C bus
  pinMode(audioSwitchPin,INPUT);       // set up the switch pin as an input
  digitalWrite(audioSwitchPin, HIGH);  // turn on pullup resistor

  // set I/O pins to outputs
  Wire.beginTransmission(0x20);
  Wire.write(0x00); // IODIRA register
  Wire.write(0x00); // set all of port A to outputs
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x01); // IODIRB register
  Wire.write(0x00); // set all of port B to outputs
  Wire.endTransmission();
}

void loop(){
  //Off
  Wire.beginTransmission(0x20);
  Wire.write(0x12); // address port A
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13); // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  //1.5Khz
  Wire.beginTransmission(0x20);
  Wire.write(0x12); // address port A
  Wire.write(0x64);  // value to send B01000000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13); // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  //2.0Khz
  Wire.beginTransmission(0x20);
  Wire.write(0x12); // address port A
  Wire.write(0x32);  // value to send B00100000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13); // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  //2.5Khz
  Wire.beginTransmission(0x20);
  Wire.write(0x12); // address port A
  Wire.write(0x16);  // value to send B00010000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13); // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
}

Even test code should be readable (especially when posted :wink:

#include <Wire.h>

const int audioSwitchPin = 2;  // set up a constant for the Audio Filter switch
int audioSwitchState = 0;      // variable to hold the value of the switchPin

void setup() {
  Wire.begin();   // wake up I2C bus
  pinMode(audioSwitchPin,INPUT);       // set up the switch pin as an input
  digitalWrite(audioSwitchPin, HIGH);  // turn on pullup resistor

  setPinModes(0, 0);
}

void loop()
{
  //Off
  sendValue(0,0);
  delay(1000);

  //1.5Khz
  sendValue(0x64, 0x00);
  delay(1000);

  //2.0Khz
  sendValue(0x32, 0x00);
  delay(1000);

  //2.5Khz
  sendValue(0x16, 0x00);
  delay(1000);
}

void setPinModes(byte IOA,  byte IOB)
{
  Wire.beginTransmission(0x20);
  Wire.write(0x00);               // IODIRA register
  Wire.write(IOA);                       // set all of port A to outputs
  Wire.endTransmission();

  Wire.beginTransmission(0x20);
  Wire.write(0x01);             // IODIRB register
  Wire.write(IOB);               // set all of port B to outputs
  Wire.endTransmission();
}

void sendValue(byte valA, byte valB)
{
  //Off
  Wire.beginTransmission(0x20);
  Wire.write(0x12); 
  Wire.write(valA); 
  Wire.endTransmission();

  Wire.beginTransmission(0x20);
  Wire.write(0x13); 
  Wire.write(valB);  
  Wire.endTransmission();
}

Hi

Even test code should be readable (especially when posted smiley-wink

Did i make a few mistakes (i'am still learning) XD Howard

void setPinModes(byte IOA,  byte IOB)
{
  Wire.beginTransmission(0x20);
  Wire.write(0x00);               // IODIRA register
  Wire.write(IOA);                       // set all of port A to outputs
  Wire.endTransmission();

Where do you get the idea that the PCF8574 has I/O data direction register? Read pages 12 & 13 in the data sheet.

Sorry guys that was coded for a MCP23017 :astonished: Howard

Grumpy_Mike: void setPinModes(byte IOA,  byte IOB) {  Wire.beginTransmission(0x20);  Wire.write(0x00);               // IODIRA register  Wire.write(IOA);                       // set all of port A to outputs  Wire.endTransmission();

Where do you get the idea that the PCF8574 has I/O data direction register? Read pages 12 & 13 in the data sheet.

Sorry Grumpy, my post was to clean up the code a bit - not check the data sheet, and IIRC the PCF8574 has only 8 datalines not 16 :)

Hi All
Well i have decided to use the MCP23017 port expander
so here is some code, at the moment it is only for 1 button which is connected to pin2 on the UNO
there are some lines for the i2c lcd display, as i wan’t a readout of the switch status ie: “off”, “1.5khz”, “2.0khz” and “2.5khz”.
I would also like to expand this code to have 2 more buttons for other functions from the MCP23017.
The code size at the moment is 5,082 bytes, can it be cleaned up to make it smaller ??
Thanks for any help
Howard

// THIS IS TEST CODE FOR THE MCP23017 16BIT PORT EXPANDER
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address to 0x27 for a 20 chars and 4 line display

const int audioSwitchPin = 2;  // set up a constant for the Audio Filter switch
int audioSwitchState = 0;      // variable to hold the value of the switchPin
int prevaudioSwitchState = 0;     // variable to hold previous value of the switchpin
int audiobuttonPushCounter = 0;   // counter for the number of button presses

void setup() {
  Wire.begin();   // wake up I2C bus
  lcd.begin(20, 4);                    // set up the number of columns and rows on the LCD
  pinMode(audioSwitchPin,INPUT);       // set up the switch pin as an input
  digitalWrite(audioSwitchPin, HIGH);  // turn on pullup resistor

  // set I/O pins to outputs
  Wire.beginTransmission(0x20);
  Wire.write(0x00);  // IODIRA register
  Wire.write(0x00);  // set all of port A to outputs
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x01);  // IODIRB register
  Wire.write(0x00);  // set all of port B to outputs
  Wire.endTransmission();
}

void loop(){
   audioSwitchState = digitalRead(audioSwitchPin);   // check the status of the switc
  if (audioSwitchState != prevaudioSwitchState)      // compare the switchState to its previous state
  {
  if (audioSwitchState == LOW)     // If the switch is pressed, count the press
  {
      audiobuttonPushCounter ++;  
      audiobuttonPushCounter %= 4;
  }
      lcd.clear();    // clean up the screen before printin
  }
  switch (audiobuttonPushCounter)
  {
  case 0:   //Off
    lcd.setCursor(0, 0);
    lcd.print("OFF");
  Wire.beginTransmission(0x20);
  Wire.write(0x12);  // address port A
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13);  // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  break;
  
  case 1:   //1.5Khz
    lcd.setCursor(0, 0);
    lcd.print("1.5K");
  Wire.beginTransmission(0x20);
  Wire.write(0x12);  // address port A
  Wire.write(0x64);  // value to send B01000000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13);  // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  break;
  
  case 2:   //2.0Khz
    lcd.setCursor(0, 0);
    lcd.print("2.0K");
  Wire.beginTransmission(0x20);
  Wire.write(0x12);  // address port A
  Wire.write(0x32);  // value to send B00100000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13);  // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  break;
  
  case 3:   //2.5Khz
    lcd.setCursor(0, 0);
    lcd.print("2.5K");
  Wire.beginTransmission(0x20);
  Wire.write(0x12);  // address port A
  Wire.write(0x16);  // value to send B00010000
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x13);  // address port B
  Wire.write(0x00);  // value to send B00000000
  Wire.endTransmission();
  break;
}
prevaudioSwitchState = audioSwitchState;  // save the current switch state as the last state
}

If you look at the code in your three cases you will see there is little difference between them. Combine them into one function, and just pass in the different values you want to use.