This library supports the 8-bit quasi-bidirectional port on the PCG8574 via an I2C-bus interface.
The PCF8574 has a low current consumption and includes latched outputs with high current drive capability for directly driving LEDs.
It also possesses an interrupt line (INT) which can be connected to the interrupt logic of the microcontroller. By sending an interrupt signal on this line to the microcontroller, the remote I/O can inform the microcontroller if there is incoming data on its ports without having to communicate via the I2C-bus.
This means that the PCF8574 can remain a simple slave device.
The driver support two commands via I2C - this supports hardware and software I2C PCF8574_sendbyte( PCF8574_device, [out_byte] ) where PCF8574_device is the 8bit I2C address and out_byte is the byte variable data to be sent PCF8574_readbyte( PCF8574_device, [in_byte] ) where PCF8574_device is the 8bit I2C address and in_byte is the byte variable data to be received
To address a specific slave. Use the constant #DEFINE PCF8574_DEVICE_1 0X4E where 0x4E is the correct address identified by I2C Discovery.
I2C must be defined prior to calling the methods shown above. Either Software or Hardware I2C is supported.
Are you using Hardware I2C2 for discovery ?
With the PCF library using Hardware I2C module 1) ..it will not work. PCF library supports Hardware I2C only.
Change the discovery and your Hardware I2C to I2C ( I2C module 1) or, I can change the PCF library to support Hardware I2C2.
Evan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
No, I used the I2C Discovery program to check that I had conectivity and that is was sitting at the right address. The file I'm using is attached and the two lines of code are sitting on line 85.
As I said, I need to find out what I have to do to turn on and off the LED's on my Breadboard connected to P0 and P1 of the PCF8574
As it is I can begin to develop the code for the project. It's a pain having to load the i2c Discovery program before I can see the display with my controller code but I can work with it for the time being.
The issue is PPS. You have set the chips I2C (via PPS) to I2C2 ( therefore the second I2C channel. Marked as MSSP2) and then used I2C for the control of the I2C software within GCBASCIC.
I have attached the Demo I2C discovery. Therefore, MSSP1. Please test and validate.
And, a demo program for the PCF8574. If this works then reintegrate all your other devices. Let us get this demo program working on the PCF8574 before reintegrating the other devices.
Note: the PCF8574 demo. It works. It will set the LEDs in sequence. The read operation ... you need to set ports appropriately/ Meaning, if you write a value to the PCF8574 tp set some port state and then read the port you will get the port status but the attached device (LED etc) will have some residual state. So, you should adapt the program to suit the inputs and output you have.
So, to make the demo clearer. The ports on the PCF are as follows:
The root cause of the I2C discovery issues was the I2C discover program. With the specific configuration of I2C devices the program caused the I2C bus to lock the clock low - not good!
My error from about five years.
So, so, sorry as this cause Keith many hours of angst.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have flogged on nearly all day trying to get this PCF8574 to show some signs of life nd eventually discovered that it is sitting on the wrong address it is occupying 70 and 71 (0x46 & 0x47) How has it manged to do that?? but more to the point how do I change it back?
Looks like lead A2 on the IC maybe shorted to ground. The addressing method is explained in the device datasheet. A0, A1, A2 determine the address. An Address of 0x70 correlates with A2 Low, A1 High and A0 High. Get you meter out and read them. Correct as necessary.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you William, had a sneaky feeling it was something to do with those three pins, but being afraid of a stupid mistake with a six quid chip and making the smoke escape.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you William, had a sneaky feeling it was something to do with those three pins, but being afraid of a stupid mistake with a six quid chip and making the smoke escape.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I found out what upset the PCF8574 addressing. The address given to me for the PCF8574 0x7E but it spat its dummie out as 0x7E is the address for the I2C LCD Adaptor
I have moved the address of the PCF8574 to 0x7A and 0x7B with hardware jumpers on A0, A1 and A2 no conflicts but I still cannot get any activity on the LED's. Is the activity Hi or Lo ?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm back again where I left off, been down with Flu which really knocked the stuffing out of me. I really must get this PCF8574 device to work, it is crucial to my project.
Is there any demo code available that is simple enough for me to follow ?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm still really struggling with these Demo's five of which relate to Atmega devices to which I feel, bear very little relevance to the PCF8574 device I am trying to get my head around.
I am making an assumption that the Demo folder you say is the Demo folder in 'My'GCB/Demos on my PC as there are a few files you mention to check out are not there.
I have bashed this about all day and the only thing I managed to do is confuse myself even more.
below is some code you sent me a while back, I cannot follow it as I cannot get to work as it only shows "Send to PCF8574 0x01" Again on assumption 01 refers to port 01 of the device.
I really feel this is a topic which needs a simplified explanatory demo as there most be others who struggle with high level programming language especially when it goes into using interrupts
;;;;SpindleMotorCoolantTemperatureController.;;;;ProjectDate19:5929.01.2023' ----- Configuration'Chip Settings.#CHIP 16f18326,32#OPTION Explicit'Set the PPS of the PWM and the RS232 ports.'Set the PPS for this solution.#STARTUP InitPPS, 85SubInitPPSUNLOCKPPS'Pin RC5 source is an input for RXRXPPS=0x15'Pin RC4 source is TX/CKRC4PPS=0x14'RA2->MSSP:SDA;RA2PPS=0x0019'RA2->MSSP:SDA;SSP1DATPPS=0x0002'RA4->MSSP:SCL;SSP1CLKPPS=0x0004'RA4->MSSP:SCL;RA4PPS=0x0018LOCKPPSEndSub''-------------------PORTA----------------''Bit#: -7---6---5---4---3---2---1---0---''IO:-------------SCL-----SDA----------''-----------------------------------------''''-------------------PORTB----------------''Bit#: -7---6---5---4---3---2---1---0---''IO:---------------------------------''-----------------------------------------''''------------------PORTC-----------------''Bit#: -7---6---5---4---3---2---1---0---''IO:---------RX-TX-LED--LED-LEDLED--''-----------------------------------------#DEFINE SWITCH_DOWN 1#DEFINE SWITCH_UP 0#DEFINE LEDD2 PORTC.0#DEFINE LEDD3 PORTC.1#DEFINE LEDD4 PORTC.2#DEFINE LEDD5 PORTC.3#DEFINE LEDBANK portc//!#DEFINE SWITCH PORTA.1DirLEDD2OutDirLEDD3OutDirLEDD4OutDirLEDD5Out//!DirSWITCHIn#DEFINE USART_BAUD_RATE 19200#DEFINE USART_TX_BLOCKING' ----- Define Hardware settings for HWI2C' Define I2C settings - CHANGE PORTS if required for your specific device.#DEFINE HI2C_BAUD_RATE 400#DEFINE HI2C_DATA PORTA.2#DEFINE HI2C_CLOCK PORTA.4'Initialise I2C Master'I2C pins need to be input for SSP moduleDirHI2C_DATAInDirHI2C_CLOCKIn'MASTER Second PortHI2CModeMaster' ----- Main body of program commences here *******************************************' Now assumes Serial Terminal is operational''------------------PCF8574C-----------------''Bit#: -7---6---5---4---3---2---1---0---''IO:-SW1-SW--SW--SW--LED-LED-LED-LED--''-----------------------------------------#INCLUDE <PCF8574.H>#DEFINE PCF8574_DEVICE_1 0X7A // This is the correct address Dimledstatus,portstatusasByte//!Initialvalueledstatus=1DoHSerPrint"Send to PCF8574 0x"HserPrinthex(ledstatus)HSerSend9//!sendavariabletotheI2CdevicethatsetsthedeviceportsPCF8574_sendbyte(PCF8574_DEVICE_1,ledstatus)wait1000ms//!readthestatusoftheportintothevariableportstatusPCF8574_readbyte(PCF8574_DEVICE_1,portstatus)HSerPrint"Recieved from PCF8574 0x"HSerPrintStringCRLFhex((portstatus&0XF0)/16)SetCOffRotateledstatusleftifledstatus=16thenledstatus=1Loop
Using the example as below I have managed to get some life from Ports 0 - 3
#DEFINE PCF8574_DEVICE_1 0X7AHSerPrint"Send to PCF8574 0x"HserPrinthex(ledstatus)HSerSend9//!sendavariabletotheI2CdevicethatsetsthedeviceportsPCF8574_sendbyte(PCF8574_DEVICE_1,ledstatus)wait1000ms//!readthestatusoftheportintothevariableportstatusPCF8574_readbyte(PCF8574_DEVICE_1,portstatus)HSerPrint"Recieved from PCF8574 0x"HSerPrintStringCRLFhex((portstatus&0XF0)/16)SetCOffRotateledstatusleftifledstatus=16thenledstatus=1
It cycles 4 active low LED's with a latching output. I'm still extremely confused as to how it does it but at least I can poke about a bit with it and fathom out what makes it tick.
On a PIC C is the Status register (STATUS.C). On AVR/LGT the carry is the SREG bit C. Think of STATUS.C acts as a ninth bit of the variable that is being rotated. So, C accesses the carry bit. Using C rather that SREG.C or STATUS.C makes the program portable with the compiler transforming C to the correct name for the specific chip.
A simple way to would be use a Constant and send that to the PCF8574. Then, you could use a If-then or select-case statement to index through setting the LEDs.
You are already reading the value of the PCF (shown in your code above). What does the serial terminal show?
Last edit: Anobium 2023-04-08
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have tried every conceivable combination of logic to try and make use of the ledstatus variable from simply
repeat 5
ledstatus = 1
wait 1 S
ledstatus = 0
wait 1 S
end repeat
which under normal usage should give me a straightforward 1 second flash, 5 times - it doesn't
Having four LED's cycle through a sequence is pretty, and the code to do it is pretty clever but it is neither use to man or beast on a fine day !
You Write, " A simple way to would be use a Constant and send that to the PCF8574. Then, you could use a If-then or select-case statement to index through setting the LEDs."
Once again, this is way above my programming knowledge. All I want to do is to turn on and off two or three outputs from within my program. I would dearly love to understand how to read the input ports also.
Last edit: Keith 2023-04-08
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The PCF8574 is a remote device and it communicates via I2C therere is a low level protcol.
We cannot simple say LETSTATUS = 1 as that implies that LETSTATUS is an output port on the chip - which it is not.
So, we have to tell the PCF8574 the configuration that you require - for that you use PCF8574_sendbyte( in PCF8574_device, in PCF8574_data ) where PCF8574_device is the device and PCF8574_data is the state you will be setting the output of the PCF8574 to either high or low.
That is how the PCF8574 works as per the datasheet.
The GCBASIC library supports the 8-bit quasi-bidirectional port via an I2C-bus interface.
The PCF8574 has a low current consumption and includes latched outputs with high current drive capability for directly driving LEDs.
So, we can make is simpler. Would this work? It would need to writtem but that is easy.
I don't seem to be able to get the simplified version to compile albeit edited to what I feel it should look like declaring both statements with Dim PCF8574Port as Byte
Set PCF8574Port On (LED1)
Set PCF8574Port Off(LED1)
WARNINGs / ERRORs reported by Great Cow BASIC (if Syntax Error, doubleclick on the errormessage below) <<<
My Spindle Motor Temp Controller.gcb (158): Error: Invalid status in Set command: LED1
My Spindle Motor Temp Controller.gcb (160): Error: Array/Function 0 has not been declared
My Spindle Motor Temp Controller.gcb (160): Error: Invalid status in Set command: LED1
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm trying to use the PCF8574 serial I/O device in this project but the Demo file is written up for a mega328p (Don't want to go there again)
Does anyone have any suggestions as to what to do to get this to compile with a 16F18326 so as I can get a handle on how this little beastie works.
the demo file is ic2_pcf8574_serial_expander_mega328p
This library supports the 8-bit quasi-bidirectional port on the PCG8574 via an I2C-bus interface.
The PCF8574 has a low current consumption and includes latched outputs with high current drive capability for directly driving LEDs.
It also possesses an interrupt line (INT) which can be connected to the interrupt logic of the microcontroller. By sending an interrupt signal on this line to the microcontroller, the remote I/O can inform the microcontroller if there is incoming data on its ports without having to communicate via the I2C-bus.
This means that the PCF8574 can remain a simple slave device.
The driver support two commands via I2C - this supports hardware and software I2C
PCF8574_sendbyte( PCF8574_device, [out_byte] )
where PCF8574_device is the 8bit I2C address and out_byte is the byte variable data to be sentPCF8574_readbyte( PCF8574_device, [in_byte] )
where PCF8574_device is the 8bit I2C address and in_byte is the byte variable data to be receivedTo address a specific slave. Use the constant
#DEFINE PCF8574_DEVICE_1 0X4E
where 0x4E is the correct address identified by I2C Discovery.I2C must be defined prior to calling the methods shown above. Either Software or Hardware I2C is supported.
Evan
Last edit: Anobium 2023-01-30
See https://github.com/GreatCowBASIC/Help/blob/main/source/pcf8574.adoc
Edit and correct as required.
I'm a little confused, well a big confused. I have the PCF8574 on the breadboard, I have ran i2c Discovery and I can see the device sitting on 0X4E
I have added the line PCF8574_sendbyte(PCF8574_DEVICE_1, LEDStatus ) into my code. together with the other two lines of code as above.
the burning question is how do I get it to switch on and off the LED's I have hooked up tp P0 and P1 ???
Are you using Hardware I2C2 for discovery ?
With the PCF library using Hardware I2C module 1) ..it will not work. PCF library supports Hardware I2C only.
Change the discovery and your Hardware I2C to I2C ( I2C module 1) or, I can change the PCF library to support Hardware I2C2.
Evan
No, I used the I2C Discovery program to check that I had conectivity and that is was sitting at the right address. The file I'm using is attached and the two lines of code are sitting on line 85.
As I said, I need to find out what I have to do to turn on and off the LED's on my Breadboard connected to P0 and P1 of the PCF8574
As it is I can begin to develop the code for the project. It's a pain having to load the i2c Discovery program before I can see the display with my controller code but I can work with it for the time being.
The issue is PPS. You have set the chips I2C (via PPS) to I2C2 ( therefore the second I2C channel. Marked as MSSP2) and then used I2C for the control of the I2C software within GCBASCIC.
I have attached the Demo I2C discovery. Therefore, MSSP1. Please test and validate.
And, a demo program for the PCF8574. If this works then reintegrate all your other devices. Let us get this demo program working on the PCF8574 before reintegrating the other devices.
Note: the PCF8574 demo. It works. It will set the LEDs in sequence. The read operation ... you need to set ports appropriately/ Meaning, if you write a value to the PCF8574 tp set some port state and then read the port you will get the port status but the attached device (LED etc) will have some residual state. So, you should adapt the program to suit the inputs and output you have.
So, to make the demo clearer. The ports on the PCF are as follows:
The demo will set the LEDs and read the switches. As follows:
All switches are high.
Last edit: Anobium 2023-02-01
PS. I have tested and this demo works.
See https://sourceforge.net/p/gcbasic/discussion/579125/thread/96d08f3f46/?limit=250#ed18
The root cause of the I2C discovery issues was the I2C discover program. With the specific configuration of I2C devices the program caused the I2C bus to lock the clock low - not good!
My error from about five years.
So, so, sorry as this cause Keith many hours of angst.
No problem Evan, all sorted now. Thanks.
I have flogged on nearly all day trying to get this PCF8574 to show some signs of life nd eventually discovered that it is sitting on the wrong address it is occupying 70 and 71 (0x46 & 0x47) How has it manged to do that?? but more to the point how do I change it back?
Last edit: Keith 2023-02-19
Looks like lead A2 on the IC maybe shorted to ground. The addressing method is explained in the device datasheet. A0, A1, A2 determine the address. An Address of 0x70 correlates with A2 Low, A1 High and A0 High. Get you meter out and read them. Correct as necessary.
Thank you William, had a sneaky feeling it was something to do with those three pins, but being afraid of a stupid mistake with a six quid chip and making the smoke escape.
Thank you William, had a sneaky feeling it was something to do with those three pins, but being afraid of a stupid mistake with a six quid chip and making the smoke escape.
I found out what upset the PCF8574 addressing. The address given to me for the PCF8574 0x7E but it spat its dummie out as 0x7E is the address for the I2C LCD Adaptor
I have moved the address of the PCF8574 to 0x7A and 0x7B with hardware jumpers on A0, A1 and A2 no conflicts but I still cannot get any activity on the LED's. Is the activity Hi or Lo ?
I'm back again where I left off, been down with Flu which really knocked the stuffing out of me. I really must get this PCF8574 device to work, it is crucial to my project.
Is there any demo code available that is simple enough for me to follow ?
There are demos wth the device. I did a search in GCCode of the Demos folder. See attached.
Last edit: Anobium 2023-04-06
I'm still really struggling with these Demo's five of which relate to Atmega devices to which I feel, bear very little relevance to the PCF8574 device I am trying to get my head around.
I am making an assumption that the Demo folder you say is the Demo folder in 'My'GCB/Demos on my PC as there are a few files you mention to check out are not there.
I have bashed this about all day and the only thing I managed to do is confuse myself even more.
below is some code you sent me a while back, I cannot follow it as I cannot get to work as it only shows "Send to PCF8574 0x01" Again on assumption 01 refers to port 01 of the device.
I really feel this is a topic which needs a simplified explanatory demo as there most be others who struggle with high level programming language especially when it goes into using interrupts
Progress !
Using the example as below I have managed to get some life from Ports 0 - 3
It cycles 4 active low LED's with a latching output. I'm still extremely confused as to how it does it but at least I can poke about a bit with it and fathom out what makes it tick.
Last edit: Keith 2023-04-07
Well done.
PCF8574_sendbyte(PCF8574_DEVICE_1, ledstatus )
You are sending a value of
ledstatus
to the device and it sets the ports in the device. This is how it works.Are you asking how the I2C works?
My issues are trying to work out how this works
This I find complex and confusing. Is there a simplified way to turn the LED's On and Off?
How do I read the 4 input ports and what will I be looking for?
https://youtu.be/aDHZKknT2rE
The video explains the process of Rotate with C.
On a PIC
C
is the Status register (STATUS.C). On AVR/LGT the carry is the SREG bit C. Think of STATUS.C acts as a ninth bit of the variable that is being rotated. So, C accesses the carry bit. Using C rather that SREG.C or STATUS.C makes the program portable with the compiler transforming C to the correct name for the specific chip.A simple way to would be use a Constant and send that to the PCF8574. Then, you could use a If-then or select-case statement to index through setting the LEDs.
You are already reading the value of the PCF (shown in your code above). What does the serial terminal show?
Last edit: Anobium 2023-04-08
I have tried every conceivable combination of logic to try and make use of the ledstatus variable from simply
repeat 5
ledstatus = 1
wait 1 S
ledstatus = 0
wait 1 S
end repeat
which under normal usage should give me a straightforward 1 second flash, 5 times - it doesn't
Having four LED's cycle through a sequence is pretty, and the code to do it is pretty clever but it is neither use to man or beast on a fine day !
You Write, " A simple way to would be use a Constant and send that to the PCF8574. Then, you could use a If-then or select-case statement to index through setting the LEDs."
Once again, this is way above my programming knowledge. All I want to do is to turn on and off two or three outputs from within my program. I would dearly love to understand how to read the input ports also.
Last edit: Keith 2023-04-08
OK.
The PCF8574 is a remote device and it communicates via I2C therere is a low level protcol.
We cannot simple say
LETSTATUS = 1
as that implies thatLETSTATUS
is an output port on the chip - which it is not.So, we have to tell the PCF8574 the configuration that you require - for that you use
PCF8574_sendbyte( in PCF8574_device, in PCF8574_data )
wherePCF8574_device
is the device andPCF8574_data
is the state you will be setting the output of the PCF8574 to either high or low.That is how the PCF8574 works as per the datasheet.
The GCBASIC library supports the 8-bit quasi-bidirectional port via an I2C-bus interface.
The PCF8574 has a low current consumption and includes latched outputs with high current drive capability for directly driving LEDs.
So, we can make is simpler. Would this work? It would need to writtem but that is easy.
Where LED1 .. to LED8 relates to the 8 ports.
Would that work for you?
I don't seem to be able to get the simplified version to compile albeit edited to what I feel it should look like declaring both statements with Dim PCF8574Port as Byte