OK I'm throwing the white flag, maybe someone here can help get me started. I am trying to read from the PCF8575 I2C Expander.
I can write to it OK, I can tell it which ports I want to light LED's. For some Reason reading is not as easy as writing and I could use some coding help.
My device address is byte address = 0x20;
I tried cutting and pasting several examples I found searching the web, but none of them seem to work, or I am implementing them incorrectly.
a short sketch of some type allowing me to read even one switch will get me started I just need to see a working example so I can dissect it and learn what is going on.
Here is the code that is not working. What I am trying to do:
Read two bytes from the PCF8575
If the 4th pin is high ( pin 13 on PCF8575)
send byte 11000000 to the PCF8575 ( which will light an LED on Pin 0 and 1 )
If pin 13 is low ( 0)
than light the LED's on Pins 00-7 differently ( that way I know it's not receiving the signal.)
#include <Wire.h>
byte address = 0x20; // address of PCF8575 with A0-A2 connected to GND "B01000000"
byte input;
byte c;
byte d;
void setup()
{
Wire.begin(); // join i2c bus
}
//control the pins
void loop(){
byte a = B11000000; //controls pins 0 - 7
byte b = B00110011; //controls pins 10-17
// by changing the 1's and 0's above you can control which pins are on and off.
// Remember the chip can sink more than it can source So the 1's are off and the 0's are on.
input = Wire.requestFrom(0x20,2);
if(input == 2) {
c = Wire.receive();
d = Wire.receive();
}
if(d == B00010000) {
Wire.beginTransmission(address); // send the address and the write cmnd
Wire.send(a);
Wire.endTransmission();
} // pack the first byte
else {
Wire.beginTransmission(address); // send the address and the write cmnd
Wire.send(b); // pack the second byte
Wire.endTransmission();
} // send the data
}
You can use Serial.begin() in setup(), and Serial.print(ln)() in loop(), to debug the code.
I've never done that, is what you typed above what I need to cut and paste in my code to make that work? or is that just an example/pseudo code?
How many bytes does Wire.requestFrom() say are available? Are there always exactly 2?
My understanding of the chip is that it has two registers, each is one byte each. The chip starts with register "0" and than goes to register "1" automatically, so From what I understand it should send two bytes whenever you request information from it.
If so, what values are returned by Wire.receive()? Are they what you expect?
Thats a good question, that I don't know the answer to. Will the Serial print function tell me that? and if so How do I do that?
OK Paul I got something to read, but I'm not sure how to use it. I cut and pasted a serial print snippet from the Arduino examples. Code here:
void loop(){
byte a = B11000000; //controls pins 0 - 7
byte b = B00110011; //controls pins 10-17
// by changing the 1's and 0's above you can control which pins are on and off.
// Remember the chip can sink more than it can source So the 1's are off and the 0's are on.
input = Wire.requestFrom(0x20,2);
// if(input == 2) {
c = Wire.receive();
d = Wire.receive();
Serial.println(c, DEC);
}
Now in the serial monitor If I connect a switch to each of my inputs from Pins 0 - 7 I get the following readings with the pind shorted to ground through a 1k resistor by a switch:
open circuit displays the value of "255"
With the pins switched to grnd I see the following in the serial monitor:
Pin0 = 254
Pin1 = 253
Pin2 = 251
Pin3 = 247
Pin4 = 239
Pin5 = 223
Pin6 = 191
Pin7 = 127
This is exciting news because that means each pin is giving a unique value to use. However How do I use this information? Also I currently only own one switch to experiment with. Does this mean that If two pins are set to ground that the value will be different? and if so How would you account for so many variables? Would I have to make some kind of library for the arduino to access that would decipher the many different combinations?
Ok, I shorted out two pins and yes the answer is, that it changes the value and somehow combines the values of the two pins giving me another value. SO now to make that work in Code, would I have to convert the value of 127 ( or whatever the pin is giving me) into HEX? than say for example:
if(byte c == this hex value){
do my stuff, and do it now!
}
Which brings me to my original question do I need a library to dictate what each HEX value is?
SO now to make that work in Code, would I have to convert the value of 127 ( or whatever the pin is giving me) into HEX?
First, you need to understand how numbers are stored internally. Every value is stored in binary. A bit is either off (0) or on (1). The Wire.receiveFrom() function returns byte-sized collections of bits.
If the bit pattern is 0010100, that value can be printed in binary (base 2), octal (base 8), decimal (base 10), hexadecimal (base 16), or any other base (although other bases are pretty rare).
The value isn't changed by printing it in different bases.
So, if b is the bit pattern shown above, it will print as B0010100, 024, 0x14, or 20.
Any of the printed patterns can appear in the if test:
if(b == B0010100)
if(b == 024)
if(b == 0x14)
if(b == 20)
So, the answer to your question is no, you do not need to convert anything.
You can use the bitRead() function to see if any given bit (0 to 7) is set, independent of any other bits.
OK, Thanks Paul. That actually made me aware of the second part of the Serial.print I copy and pasted. The second value is "DEC" meaning I was asking it to print a decimal value. I'm going to change that to BIN so I can see the 1's and 0's.
pwillard. I will read that, thanks. I think I read it before, but apparently I need to read it again.
I think I wasn't explaining myself right ( or maybe I'm not understanding your answer Paul), so let me try again Lets say I have 16 switches hooked to my PCF8575. I read the value and just some random number of switches are all pressed at one time. Weather it's binary or Hex or whatever format it is in, each switch of course will have it's own set of instructions. For example to keep it simple, Each switch will turn on an LED. SO depending on which switch you have pressed, that LED will light. So do I need some type of table or matrix or library telling my outputs which ones will turn on?
So Let's say, I read my inputs and I get my two bytes
byte a = b10101010
byte b = b11001100
each one of those 1's and 0's relates to the actual pin that is on or off on the chip, and I want them to coincide with an equal number of LED's on a second chip with the corresponding pin.
Wait...
I think I just answered my own question. ( sometimes it just helps to write everything out.
So actually to do that. I would read and get byte a and b, and than not convert or look up anything. I would just pass byte a and b to my output chip with a send() . Right?
OK Here I got to read the input and turn on an LED.
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Read from a PCF8575 to control the inputs using the I2C bus. In this example I get an input from a switch
// connected to ground through a reistor. Which will return a "0" when the switch is pressed. By pressing the selected
// switch it will then turn on an LED sinking to Arduino Pin 13.
// 1/01/2010 Sonny Schade triath5147@msn.com Use and have fun. If you make any changes that improve
// this code,Please post it to the community.
///////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <Wire.h>
byte address = 0x20; // address of PCF8575 with A0-A2 connected to GND "B01000000"
byte input; // variable to receive the two bytes
byte c; // first of the two bytes to read
byte d; // second of the two bytes to read
void setup()
{
Wire.begin(); // join i2c bus
Serial.begin(9600); // used to Debug , Thanks PaulS
}
void loop(){
input = Wire.requestFrom(0x20,2);
c = Wire.receive();
d = Wire.receive();
Wire.endTransmission();
if(d == B10111111) {
digitalWrite(13, LOW);
}
else {
digitalWrite(13, HIGH);
}
Serial.println(c, BIN);
// delay(1000);
Serial.println(d,BIN);
} // send the data
OK so there we have it. Now if someone in this forum is more familiar with the Wire programming that can double check my work, to see if I am doing anything I shouldn't be, that might effect the ability to run other code in the loop.
Not exactly the same thing, but probably closer to what you want to do. The B10111111 value being compared to REQUIRES all the other pins be HIGH. The bitRead part ignores the state of the other 7 pins.
Yes, a poor choice of words on my part. I meant to say since I am watching for a "0" on pin 6 of the second register. It does as I ask and lights the LED. But if the entire byte was important ( not just pin 6), than you are correct sir, my post above would be wrong. Touche.