First off some things I do know the PCF8574 is a GPIO expander with some limitations vs a typical esp8266 digital pin.
Possible limitations: I DO NOT KNOW IF THESE ARE TRUE ASSUMPTIONS BE WARNED!!!!
I am not entirely sure but I do not think you can control the PWM of a pin this is an assumption just based off of reading so I could be wrong here but just figured it was worth the mention there may be other limitations as well.
It may be possible that we can or can't read the last status of the pins or read them while operating as an output. I have not read enough to determine this but it should be possible to somehow track the information in our code. Pin status is huge knowing the last status of your pins enables you to know if your GPIO is in the On or OFF state everyone I know and see post values this information and with good reason. And as a side note there is really no good way that I personally know of tracking your own variable in esp basic v3.0 all attempts for me seem to fail to manually track a pin. There is io(laststat,D5) this works great for tracking the status of the esp's GPIO however a method of tracking the value of your own variables so that you can track the state of the pin seems to prove a little more difficult in basic 3.x. Just a fair warning does not like to track beyond the first attempt at tracking it seems. There likely is a way to do it but I am too dense to know it currently interestingly enough I was able to do it in early versions of esp basic so dense or not something has changed which deleted a bit of my understanding of basic. But enough on this moving along LETS GATHER SOME IMPORTANT INFO!!!!
I am completely blank when it comes to basic and the I2C protocol so I must first gather an understanding and do some research sorry for not knowing all this stuff folks but I will admit I am dead in the water when it comes to a lot of the hardware interfacing with the esp8266 and basic.
Questions to answer when gathering info:
Q: What is the I2C code in basic?
A: The I2C code in basic is as follows:
else if (fname.startsWith(F("i2c.")) ) // block I2C functions; this reduces the number of compares
{
fname = fname.substring(4); // skip the term i2c.
if ( fname == F("begin") && num_args == 1 ) {
// function i2c.begin(address)
// set return value
Wire.beginTransmission((byte)args[0]);
*value_str = String(F(""));
return PARSER_STRING;
}
else if ( fname == F("write") && num_args == 1 ) {
// function i2c.write(byte to be written)
// set return value
*value_str = String(Wire.write((byte)args[0]));
return PARSER_STRING;
}
else if ( fname == F("end") && num_args == 0 ) {
// function i2c.end()
// set return value
*value_str = String(Wire.endTransmission());
return PARSER_STRING;
}
else if ( fname == F("requestfrom") && num_args > 0 ) {
// function i2c.requestfrom(address, qty)
// set return value
*value_str = String(Wire.requestFrom((byte)args[0], (byte)args[1]));
return PARSER_STRING;
}
else if ( fname == F("available") && num_args == 0 ) {
// function i2c.available()
// set return value
*value_str = String(Wire.available());
return PARSER_STRING;
}
else if ( fname == F("read") && num_args == 0 ) {
// function i2c.read()
// set return value
*value_str = String(Wire.read());
return PARSER_STRING;
}
}
Q: Knowing that D3 and D4 of nodemcu is I2C for basic which line is clock D3 or D4? Then the other line is data when using basic.
A: ????? Dunno Yet...
Q: What parameters are available in basic to communicate with a device using I2C?
A: Looking at the espbasic v3.0 documentation here is what it says:
FUNCTIONS I2C
i2c functions:
For more information on usage look at this example.
i2c.begin():
Will begin transmission to the I2C device with desired address.
i2c.begin({value or var for device address})
i2c.write():
Will write a single value (1 character) to the i2c device.
i2c.write({value or var for data})
i2c.end():
Will terminate the i2c contamination with a particular device.
i2c.end()
i2c.requestfrom():
Will request a quantity of bytes from device.
i2c.requestfrom({value or var for device id},{value or var for number of bytes to request})
i2c.available():
Returns the number of bytes available for retrieval with i2c.read().
i2c.available()
i2c.read():
Will return a single character as an integer. Character returned will be next out of buffer.
i2c.read()
Side Note:
For reasons really unknown to me personally Raintime believes it is not possible to properly use the I2C functions built into basic to handle the PCF8574 fully but if I understand him right we will need to still use it to address the PCF8574? But he states there may likely be a bitbang type routine to handle the states of the ports of the PCF8574 and this will be potentially a lot slower due to everything being interpreted?
Q: After knowing this would it be best to have basic support in the forum of a library and some code possibly for the PCF8574 and have a build of basic that would support this would this solve speed issues as well?
A: IDK ??? After looking at this page to see what libs are available for esp8266 HERE I have determined that under other libs there is a library available for the esp8266 which can be found HERE
Q: Okay that's nice but how do we add these libs and add support for it?
A: IDK for sure but HERE IS A START
Q: How do we address the PCF8574 ?
A: I2C Address table for PCF8574 and PCF8574A below
Q: Where is a good datasheet of the PCF8574?
A: This seems to be fairly in depth coverage: http://www.ti.com/product/PCF8574/datasheet
EDIT RAINTIME added this datasheet as a better alternative
http://www.ti.com/lit/ds/symlink/pcf8574.pdf both hosted on the same website may be possible we have the same thing just different links as I wanted people to be able to click on technical documents etc as well.
Anyhow just keep in mind both links may and should apply.
Q: Are there any good examples of putting any of this information to use with ELI5 (Explain Like I'm 5 years old) explanations
A: ???? Dunno Yet...
Q: Does the hardware allow for tracking last status of the pins?
A: Don't Know ????
Q: If the hardware does not allow for tracking last status of pins can basic do it if so what is a good way of doing this in v3.0 where the variable is constantly tracked without fail through the entire operation of the code? Often I find tracking the status of a variable the status somehow gets lost in translation so would be nice to see a solid example of this?
A: ??? Dunno LIkely But How IDK???
Q: Is it possible to bitbang this device to toggle GPIO on/off?
A: I don't know ??? I really not even have researched this possibility at all!
Interested goat head chime in and share some info :P
EDIT:
woops didn't mean to call you a goat head I meant to say go ahead!
CONCLUSION WE HAVE WORKING CODE FOR EXPANSION!
Conclusion of all of this I now have a working example it works very similar to a shift register no bit bang required just math functions getting it to work how it works I cannot really explain I just kind of took the code that was provided by TrackerJ and modified it until it worked. His code would cause all GPIO expansion ports to be on on first button push and his code also only allowed you to turn port on at a time...
So after messing around I arrived at a program I now know and understand. If you wish to understand open a calculator in programmer's mode and you will see the bits going high and low as you run the xor routines.
But here you go folks if you like it then donate to me some dogecoin :P
let address = 32 'PCF8574 I2C Address
'below we sync the chip all on or all off your choice for all on use ss = ss xor 255
'instead of ss = 0 xor 255
i2c.begin(address)
ss = 0 xor 255 ' this is the line that syncs the chip
i2c.write(ss)
i2c.end()
button "1", [1]
button "2", [2]
button "3", [3]
button "4", [4]
button "5", [5]
button "6", [6]
button "7", [7]
button "8", [8]
button "OFF", [9]
wait
[9]
i2c.begin(address)
ss = 0 xor 255
i2c.write(ss)
i2c.end()
wait
[1]
i2c.begin(address)
ss = ss xor 1
i2c.write(ss)
i2c.end()
wait
[2]
i2c.begin(address)
ss = ss xor 2
i2c.write(ss)
i2c.end()
wait
[3]
i2c.begin(address)
ss = ss xor 4
i2c.write(ss)
i2c.end()
wait
[4]
i2c.begin(address)
ss = ss xor 8
i2c.write(ss)
i2c.end()
wait
[5]
i2c.begin(address)
ss = ss xor 16
i2c.write(ss)
i2c.end()
wait
[6]
i2c.begin(address)
ss = ss xor 32
i2c.write(ss)
i2c.end()
wait
[7]
i2c.begin(address)
ss = ss xor 64
i2c.write(ss)
i2c.end()
wait
[8]
i2c.begin(address)
ss = ss xor 128
i2c.write(ss)
i2c.end()
wait
Where I buy my ESP8266 boards from... (Banggood)