PCF8574AN configured as output for relay

it is like flashing loop light.

what i want to make is to have full control on each output port.

example:
i want to switch on some pin. this pin must stay on if the code say so.
in the mean time i want have some other pin switched on or off if it is asking in the code.

hope u understand, little poor english.

edwin

Yep sitting on my bench now with one light going on one after the other and after the third light goes off the first comes on again.
With the code directly copied from your post with a copy and paste.

what i want to make is to have full control on each output port.

You have it?

i want to switch on some pin. this pin must stay on if the code say so.

That is what your code does.

in the mean time i want have some other pin switched on or off if it is asking in the code.

Just change the number you send to the port. All the bits with a zero in them will turn on. If you want to change one pin without the other then just toggle that bit.
Hang on I will write you a demo.

This code flashes each LED in turn and then leaves it in the inverse state.

/*
PCF adress = 0x38

configured as output to control the relay

*/

#define PCF2_output 0x38          // (Relay) PCF8574AN, Address 0x38 with A0-A1-A2 pins grounded.
#include <Wire.h>

byte dat = 0xff;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  outputData(dat); // all outputs high
}
void loop()
{
 // pin 0 toggling
for(int i=0;i<5;i++){
  dat ^= 0x1; // toggle output 0
  outputData(dat);
  delay(200);
}
 // pin 0 toggling
for(int i=0;i<5;i++){
  dat ^= 0x2; // toggle output 1
  outputData(dat);
  delay(200);
}
 // pin 0 toggling
for(int i=0;i<5;i++){
  dat ^= 0x4; // toggle output 2
  outputData(dat);
  delay(200);
}

}

void outputData(byte dat){
    Wire.beginTransmission(PCF2_output);
  Wire.write(dat);                      // turn relay 3 on (P2)
  Wire.endTransmission();
}

thanks for the example, that works fine as i expected.

but the question are still here.

it must switch a relay ON or OFf and not flashing hihi.
just to test the code i have used a LED

maybe i have a idee,

my Project code is to big and to private to post it here.

maybe i can send it to u by email, where u can see inside the code where to put the relay on and off .

i think this will helpfull and to better understand for u, if u want help me with this

regards,
edwin

Sorry I really do not know what you want.

To keep a relay or LED on you just do not change that bit in the variable you send to the expander.
To change that output you change the bit corresponding to the output you want to change.
You can change bits with the bit set and bit clear instructions or as grown up do use the bit wise logical AND and OR operations.
In the example I was using the bit wise EXCLUSIVE OR operation to toggle the bits. Notice that only one LED flashes at a time and the others not flashing do not change. This surely is what you want isn't it?

this is a part of the code.

  int Stereovalue = analogRead(A2);                 // Read the Stereo input on Analog pin 2:
  float Stereo = Stereovalue * (4.5 / 1023.0);      // Convert the Stereo value to a voltage

  if (Stereo<1)                                     // A Stereo signal wil be present Lower then 1 volts!(0,8v) Mono = 3,6v
{
    Wire.beginTransmission(PCF2_output);            // Begin the transmission to PCF8574AN
    Wire.write(Yellow);                             // (P2) Stereo led (Yellow)
    Wire.endTransmission();                         // End the Transmission

    digitalWrite(Stereoled, HIGH);                  // Turn Stereo LED "ON" when Tuner receive a Stereo signal
    lcd.setCursor(21,0);
    lcd.print("S");                                 // display Stereo signal received
}
  else
{
    Wire.beginTransmission(PCF2_output);            // Begin the transmission to PCF8574AN
    Wire.write(0, Yellow);                             // turn off LED (P2)
    Wire.endTransmission();                         // End the Transmission

    digitalWrite(Stereoled, LOW);                   // Turn Stereo LED "OFF" when there is no Stereo signal
    lcd.setCursor(21,0);
    lcd.print("M");

the Relay PCF2 is compare as the "digitalWrite(Stereoled, HIGH)" or "digitalWrite(Stereoled, LOW)"
This mean that in this code, when i dont have a Stereo signal the relay (LED for now) is switched off and stay off
and if there is a signal, it swiched on and stay on

for testing the code i have put a LED color Yellow in the PCF

Forget about accessing the pins directly and just go through there two functions:-

byte outputData = 0xff;
void setOutptr(byte bitToChange){
    Wire.beginTransmission(PCF2_output);
    outputData |= 1<< bitToChange;
  Wire.write(outputData);                      // set the bit and leave the others alone
  Wire.endTransmission();
}

void clearOutptr(byte bitToChange){
    Wire.beginTransmission(PCF2_output);
    outputData &= ~(1<< bitToChange);
  Wire.write(outputData);                      //  clear the bit and leave the others alone
  Wire.endTransmission();
}

So when you want to turn on say relay 4, that is the relay on bit 4 you just use

setOutput(4);

when you want to turn it off then use

 clearOutput(4);

As long as you use those two calls nothing else will change only the one bit that you specify.

ok, great.

i will test tomorrow.

let u know!.

thanks for the help so far :slight_smile:

edwin

like this ?

}
  int Stereovalue = analogRead(A2);                 // Read the Stereo input on Analog pin 2:
  float Stereo = Stereovalue * (4.5 / 1023.0);      // Convert the Stereo value to a voltage

  if (Stereo<1)                                     // A Stereo signal wil be present Lower then 1 volts!(0,8v) Mono = 3,6v
{
 void setOutptr(byte bitToChange)
{
    Wire.beginTransmission(PCF2_output);
    outputData |= 1;
    Wire.write(outputData);                         // set the bit and leave the others alone
    Wire.endTransmission();

    digitalWrite(Stereoled, HIGH);                  // Turn Stereo LED "ON" when Tuner receive a Stereo signal
    lcd.setCursor(21,0);
    lcd.print("S");                                 // display Stereo signal received
}
  else
{
 void clearOutptr(byte bitToChange)
 {
    Wire.beginTransmission(PCF2_output);
    outputData &= ~(1);
    Wire.write(outputData);                         //  clear the bit and leave the others alone
    Wire.endTransmission();

    digitalWrite(Stereoled, LOW);                   // Turn Stereo LED "OFF" when there is no Stereo signal
    lcd.setCursor(21,0);
    lcd.print("M");                                 // display Mono signal received
}

No,
you haven't got what I put.

}
  int Stereovalue = analogRead(A2);                 // Read the Stereo input on Analog pin 2:
  float Stereo = Stereovalue * (4.5 / 1023.0);      // Convert the Stereo value to a voltage

  if (Stereo<1)                                     // A Stereo signal wil be present Lower then 1 volts!(0,8v) Mono = 3,6v
{
 void setOutptr(byte bitToChange)
{
    Wire.beginTransmission(PCF2_output);
    outputData |= 1 << bitToChange;
    Wire.write(outputData);                         // set the bit and leave the others alone
    Wire.endTransmission();

    digitalWrite(Stereoled, HIGH);                  // Turn Stereo LED "ON" when Tuner receive a Stereo signal
    lcd.setCursor(21,0);
    lcd.print("S");                                 // display Stereo signal received
}
  else
{
 void clearOutptr(byte bitToChange)
 {
    Wire.beginTransmission(PCF2_output);
    outputData &= ~(1<<bitToChange);
    Wire.write(outputData);                         //  clear the bit and leave the others alone
    Wire.endTransmission();

    digitalWrite(Stereoled, LOW);                   // Turn Stereo LED "OFF" when there is no Stereo signal
    lcd.setCursor(21,0);
    lcd.print("M");                                 // display Mono signal received
}

The statement should be

outputData |= 1 << bitToChange;

This sets the appropriate bit to a 1 without altering any of the other bits. The << is a shift to the left, you shift a one by as many bits to the left as the number of the bit you want to change.
Similarly when you want to clear a bit you create a number with a one in the bit you want to change, then you invert it, that is swap all the zeros and ones. Then you AND it with the number, this clears the bit.

outputData &= ~(1<< bitToChange);

sorry, i dont get it working.

when you want to turn it off then use

setOutput(4);

when you want to turn it off then use

clearOutput(4);

also where to put those

What I gave you was two functions to turn on and off individual bits in your interface.

clearOutput(4);
also where to put those

You put them in your code when ever you want to turn something on or off. Specifically when you want to turn bit 4 off. If you want to turn bit 1 off you would put clearOutput(1) ; if you want to turn bit 6 off you would use clearOutput(6) ; if you want to turn bit 8 off then you understand even less because there is no bit 8 in your interface.

The code you just posted is a nonsense, it contains a function definition in the middle of a function, that does not make sense and the compiler no doubt tells you so. The functions I gave you must be put separately at the end of your code. Then in the code you call the functions when ever you want to turn something on or off. That will be turned on or off without affecting any other things attached to the same expander. Which is what I thought you wanted.

I don't think you know enough about programming to do your project. I would advise you learning some very basic fundamentals of programming. Like what is a function.

thanks for posting Mike,

just with some help i almost finish the project.

it is only this past part with the PCF what makes it hard to find out.

Midway:
it is only this past part with the PCF what makes it hard to find out.

No it is not.
It is exactly the same technique that is used to make individual bits change in shift registers. It is exactly the same technique that is used to make a digitalWrite() function work on individual pins of a port on the arduino.
It is a very simple concept which you seem to be making heavy weather out of.

The concept is you have a variable, you change only one bit in that variable and then you write the whole thing out to your peripheral / port / shift register. The bits you have not changed in the variable do not change in the output. The bits that you have changed in the variable change in the output.

Just to finish off this thread for anyone following it up later I have written a function that works exactly like the digitalWrite function but for a PCF8574. It is called digitalOutput and it takes the same parameters as digitalWrite.

// Output to I2C device as if it were a digitalWrite pin
void digitalOutput(byte pin, boolean level){
  static byte reg = 0xff;
  byte mask;
  mask = 1<< pin;
  if(level){
    reg |= mask;
  }
  else {
    mask = ~mask; // invert mask
    reg &= mask;
  }
  Wire.beginTransmission(PCF_address1);
  Wire.write(reg);                      // change bit
  Wire.endTransmission();
}

This code includes that function and also shows three ways you can use it.

/*
Using a PCF8574
and controlling only one bit at a time
the function digitalOutput(pin, LEVEL) works just like the function
digitalWrite does for internal pins but for pins on the PCF8574
To drive an LED connect anode to +5V, cathode to resistor, resistor to
PCF8574 output pin.

By Mike Cook Feb 2013 - creative commons license share and share alike.
*/

#define PCF_address1 0x38 // PCF8574AN, Address 0x38 with A0-A1-A2 pins grounded.
#include <Wire.h>

void setup()
{
  Wire.begin();
  digitalOutput(0, HIGH); // initialise outputs
}

void loop()
{ 
  static boolean flip = false;
  // examples of using digitalOutput
 // pin 0 toggling by direct HIGH and LOW
for(int i=0;i<9;i++){
  digitalOutput(0, HIGH);
  delay(200);
  digitalOutput(0, LOW);
  delay(200);  
}
 // pin 1 toggling using the least significant bit of a variable to set HIGH and LOW
for(int i=0;i<8;i++){ 
  digitalOutput(1, i & 0x1);
  delay(200);
}
 // pin 2 toggling once per loop using a boolean variable to define HIGH and LOW
  digitalOutput(2, flip);
  flip = !flip; // invert the variable
  delay(300);

}

// Output to I2C device as if it were a digitalWrite pin
void digitalOutput(byte pin, boolean level){
  static byte reg = 0xff;
  byte mask;
  mask = 1<< pin;
  if(level){
    reg |= mask;
  }
  else {
    mask = ~mask; // invert mask
    reg &= mask;
  }
  Wire.beginTransmission(PCF_address1);
  Wire.write(reg);                      // change bit
  Wire.endTransmission();
}

Grumpy_Mike,
Never underestimate how people can misinterpret things.
I think using the term "pin" may not be clear to some folks
since the parameter is actually a bit number.
It might be a bit clearer for folks to change the names and/or terminology of your parameter
to clearly show that the parameter is bit numbers of the output port.
Or at least include some additional explanation that 0 is for controlling the pin P0,
1 is for the the pin P1, etc...

I've wrestled with a similar issue with an i2c lcd library.
In the case of the i2c to hd44780 adapters, people
would insert pin numbers of the PCF8574 or even the pin numbers of the hd44780 interface
rather than the actual bit numbers of the pcf8574 output register.
Once they finally "get it", it becomes clear, but often there is quite a bit of back and
forth and explanation needed until it finally sinks in.

--- bill