Pages: 1 [2]   Go Down
Author Topic: PCF8574AN configured as output for relay  (Read 1752 times)
0 Members and 1 Guest are viewing this topic.
Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34213
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 46
I just want to learn more :)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

this is a part of the code.

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  
« Last Edit: February 15, 2013, 04:39:26 pm by Midway » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34213
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Forget about accessing the pins directly and just go through there two functions:-
Code:
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
Code:
setOutput(4);

when you want to turn it off then use
Code:
clearOutput(4);

As long as you use those two calls nothing else will change only the one bit that you specify.
« Last Edit: February 16, 2013, 12:24:41 am by Grumpy_Mike » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 46
I just want to learn more :)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, great.

i will test tomorrow.

let u know!.

thanks for the help so far smiley

edwin
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 46
I just want to learn more :)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

like this ?
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
{
 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
}
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34213
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

No,
you haven't got what I put.

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
{
 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
Code:
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.
Code:
outputData &= ~(1<< bitToChange);
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 46
I just want to learn more :)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

sorry, i dont get it working.
« Last Edit: February 17, 2013, 03:57:18 pm by Midway » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 46
I just want to learn more :)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
when you want to turn it off then use
Code:
setOutput(4);

Quote
when you want to turn it off then use
Code:
clearOutput(4);

also where to put those
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34213
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Quote
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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 46
I just want to learn more :)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34213
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 627
Posts: 34213
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
// 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.

Code:
/*
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();
}
Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 67
Posts: 2702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Pages: 1 [2]   Go Up
Jump to: