pcf8574 switching seperate pins (solved)

Hi all,

Playing with an arduino mega and a pcf8574 8-bit I/O expander on i2c bus. What i would like to do is switch on/off individual led's connected to seperate pins on the pcf8574. Strictly speaking i've accomplished that. Problem is that i can't do it without 'touching' the others. here's the code so far;

#include <Wire.h>

#define expander B00100000 // i2c address

#define led1on (B11111111 & ~(1 << 0))
#define led1off (B11111111 | (1 << 0))
#define led2on (B11111111 & ~(1 << 7))
#define led2off (B11111111 | (1 << 7))
#define led3on (B11111111 & ~(1 << 1))
#define led3off (B11111111 | (1 << 1))
#define led4on (B11111111 & ~(1 << 6))
#define led4off (B11111111 | (1 << 6))
#define led5on (B11111111 & ~(1 << 2))
#define led5off (B11111111 | (1 << 2))
#define led6on (B11111111 & ~(1 << 5))
#define led6off (B11111111 | (1 << 5))
#define led7on (B11111111 & ~(1 << 3))
#define led7off (B11111111 | (1 << 3))
#define led8on (B11111111 & ~(1 << 4))
#define led8off (B11111111 | (1 << 4))
#define alloff B11111111
#define allon B00000000

void setup() {
Wire.begin();
}

void loop() {
expanderWrite(alloff);
delay(1000);
expanderWrite(led8on);
delay(1000);
expanderWrite(led6on);
delay(1000);
expanderWrite(led4on);
delay(1000);
expanderWrite(led2on);
delay(1000);
}

void expanderWrite(byte _data ) {
Wire.beginTransmission(expander);
Wire.send(_data);
Wire.endTransmission();
}

What i wanted with this code is to start with all led's off and end with led's 8, 6, 4 and 2 on.
Any tips/directions how to accomplish this?

The reason of the weard order and '0 = on' is how the expansion board is put together.

Thanks in advance,

Jeroen

Not wanting to upset anyone but...
Am i asking the wrong question or in a wrong form? I'm really stuck on this issue. :frowning:

As humble as i can be.

Jeroen

How many LEDs are connected to the PCF8574?

After this runs...

expanderWrite(alloff);

...which LEDs are on and which are off?

After this runs...

expanderWrite(led8on);

...which LEDs are on and which are off?

And after this...

expanderWrite(led6on);

After this...

expanderWrite(led4on);

Finally, after this...

expanderWrite(led2on);

That will help those of us unfamiliar with the PCF8574 to deduce what is wrong and how to fix the problem.

What you can do is define a global variable in your skecth that at all times holds a copy of the pin states on your port expander. For an 8 bit port expander this will conveniently fit in one byte. Then in order to change pin states you should do so in two steps:

  1. Change the pins in your local copy (using bit operations)
  2. Send the local copy to the port expander

If you follow this sequence then your local copy and the acual state of pins on the port expander will always be the same.

Perhaps you want to try this yourself rather than having someone write the code for you.

For BenF:

Does writing a value to the PCF8574 change the state of all eight pins? In other words, is it like writing to a port on the AVR processor?

From experience.. no..
If you download the byte from the 8574 and change the one bits you need and reupload it only the bits that changed will change physically....

Does writing a value to the PCF8574 change the state of all eight pins? In other words, is it like writing to a port on the AVR processor?

Yes, this is equivalent to writing a byte directly to the AtMega port registers.

Unless you do as Nachtwind suggests:

If you download the byte from the 8574 and change the one bits you need and reupload it only the bits that changed will change physically...

... or ...

you can keep a copy of the known state in a global variable, flip the required bits and send all bits back.

Thanks for all tips.
Just to make it clear; i was not looking for a 'complete code generation forum'. Sorry if i gave that impression.

Anwer to Coding Badly's post.

How many LEDs are connected to the PCF8574?

there are 8 led's connected.

expanderWrite(alloff); ...which LEDs are on and which are off?

All of the 8 led's are off or are switched off.

expanderWrite(led8on); ...which LEDs are on and which are off?

Only led 8 is on. All others are switched off/switching of if they were on.

The other answers are the same as the led8on answer except for the lednumber.

To BenF
Thanks for the strategy. I'll try this one. Once again, sorry for the wrong impression i made.

Here the lednumbers connected to portnumbers

Led1 is connected to port 0 of the expander.
led2 to port 7.
led3 to port 1.
led4 to port 6.
led5 to port 2.
led6 to port 5.
led7 to port 3
led8 to port 4.

Thanks for the suggestions.

Jeroen

Thanks for the help and here is my sketch.

#include <Wire.h>

#define expander B00100000 //expander address
#define time 1000

byte ledStatus = B11111111; //all off
byte led1 = 0; //led 1 connected to port 0 of expander
byte led2 = 7; //led 2 connected to port 7 of expander
byte led3 = 1;
byte led4 = 6;
byte led5 = 2;
byte led6 = 5;
byte led7 = 3;
byte led8 = 4;

void setup() {
Wire.begin();
}

void loop() {
changeLedStatusAlloff(); //switch all led's off to be sure
delay(time);
changeLedStatusOn(led1); //switch on only led 1
delay(time);
changeLedStatusOn(led2); //switch on led 2 (and don't touch other led's)
delay(time);
changeLedStatusOn(led3);
delay(time);
changeLedStatusOn(led4);
delay(time);
changeLedStatusOn(led5);
delay(time);
changeLedStatusOn(led6);
delay(time);
changeLedStatusOn(led7);
delay(time);
changeLedStatusOn(led8); //switch on led 8. now all led's are on
delay(time);
changeLedStatusOff(led1); //switch off led 1. now led 1 is off and 2 to 8 are on
delay(time);
changeLedStatusOff(led2); //switch off led 2. now led's 1 and 2 are off and 3 to 8 are on.
delay(time);
changeLedStatusOff(led3);
delay(time);
changeLedStatusOff(led4);
delay(time);
changeLedStatusOff(led5);
delay(time);
changeLedStatusOff(led6);
delay(time);
changeLedStatusOff(led7);
delay(time);
changeLedStatusOff(led8); //switch off led 8. now all led's are off.
delay(time);
changeLedStatusAllon(); //switch on all led's
delay(time);
changeLedStatusAlloff(); //switch off all led's
delay(time);
}

void changeLedStatusAllon (){
ledStatus = B00000000;
expanderWrite(ledStatus);
}

void changeLedStatusAlloff (){
ledStatus = B11111111;
expanderWrite(ledStatus);
}

void changeLedStatusOn(byte ledNumber){
ledStatus &= ~(1 << ledNumber);
expanderWrite(ledStatus);
}

void changeLedStatusOff(byte ledNumber){
ledStatus |= (1 << ledNumber);
expanderWrite(ledStatus);
}

void expanderWrite(byte _data ) {
Wire.beginTransmission(expander);
Wire.send(_data);
Wire.endTransmission();
}

One small suggestion: change these to constants...

const byte led1 = 0;              //led 1 connected to port 0 of expander
const byte led2 = 7;              //led 2 connected to port 7 of expander
const byte led3 = 1;
const byte led4 = 6;
const byte led5 = 2;
const byte led6 = 5;
const byte led7 = 3;
const byte led8 = 4;

This makes your intention more clear and, I believe, reduces your program's memory consumption by a few bytes.

Thanks Coding Badly.

The tip reduced final sketch size by 38 bytes. Not sure about ram usage.

Jeroen