Menu

PCF8574 Demo File

Help
Keith
2023-01-29
2023-04-10
<< < 1 2 (Page 2 of 2)
  • Anobium

    Anobium - 2023-04-09

    Kieth the syntax you are using will not work. PCF8574Port is not register ( like porta.0) but a Constant ( like 0X7A ). So, you are trying to SET a CONSTANT to ON with a parameter of ( LED1).

    Try adding this to give you something similar. You still need IC2 setup but you could use the following syntax by adding the new subroutine. Note you need the comma between the state and the LEDn, and, you + LEDs together to change the state.

    See if this works for you.

    Example usage:

    PCF8574Port On, LED1
    Wait 1 s
    PCF8574Port Off, LED1
    Wait 1 s
    PCF8574Port On, LED1 + LED2
    Wait 1 s
    PCF8574Port Off, LED1 + LED2
    End
    

    ~~~

    Sub PCF8574Port ( __state, __port )

    Dim __portstatus as Byte 
    //! read the status of the port into the variable __portstatus
    PCF8574_readbyte(PCF8574_DEVICE_1, __portstatus )
    
    #DEFINE LED0 1
    #DEFINE LED1 2
    #DEFINE LED2 4
    #DEFINE LED3 8
    #DEFINE LED4 16
    #DEFINE LED5 32
    #DEFINE LED6 64
    #DEFINE LED7 128
    
    If __state = On then
        __portstatus = __portstatus OR __port
    else
        __portstatus = __portstatus XOR __port
    end if
    
    //! send to the I2C device that sets the PCF8574 ports
        PCF8574_sendbyte(PCF8574_DEVICE_1, __portstatus )
    

    End Sub

    ~~~

     
  • Keith

    Keith - 2023-04-09

    Thank you so much. That WORKS !! Really long winded but hey, so what it works. Never in a month of Easter Sundays would I have come up with that.

    One more thing. On the datasheet it looks like the device can be configured in different modes, you mention that above in "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"

    I take it that "to either high or low" to be 0 or 1 but even with that, I cannot get that to work.

     
  • Anobium

    Anobium - 2023-04-09

    You needs to read the PCF8574. The following expands the concept to return the state of switches attached the PCF8574.

    In this demo I have assumed something like it the following. Where the LEDs and SWs are number LED0..LED7 and the switches SW0..SW7. So, you can check the state of many SWs at the same time. And, you should be able to read the bit value of a specific chip.

    I am not testing this here... you are. So, hopefully this new code works.

    Replace the previous post entirely to make sure you get all the changes.

    Evan

    // PCF8574
    // 0----1-----2---3----4----5----6----7
    // LED0 LED1 LED2 LED3 SW4  SW5  SW6  SW7
    
    PCF8574Port On, LED1 + LED2
    Wait 1 s
    PCF8574Port Off, LED1
    Wait 1 s
    PCF8574Port On, LED1 + LED2
    Wait 1 s
    PCF8574Port Off, LED1 + LED2
    
    Dim Portstate as Byte
    ' Portstate will return the bit value of the switches as a byte.
    Portstate = PCF8574Port ( SW4 + SW5 + SW6 + SW7 )
    
    If PCF8574Port.7 = 1 then 
        'The Switch is HIGH
     ELSE
         'The Switch is Low
    End If
    
    
    End
    
    
    Function PCF8574Port ( __port )
    
        Dim __portstatus as Byte 
        //! read the status of the port into the variable __portstatus
        PCF8574_readbyte(PCF8574_DEVICE_1, __portstatus )
    
        #DEFINE SW0 1
        #DEFINE SW1 2
        #DEFINE SW2 4
        #DEFINE SW3 8
        #DEFINE SW4 16
        #DEFINE SW5 32
        #DEFINE SW6 64
        #DEFINE SW7 128
    
        PCF8574Port = __portstatus AND __port
    
    End Function
    
    
    Sub PCF8574Port ( __state, __port )
    
        Dim __portstatus as Byte 
        //! read the status of the port into the variable __portstatus
        PCF8574_readbyte(PCF8574_DEVICE_1, __portstatus )
    
        #DEFINE LED0 1
        #DEFINE LED1 2
        #DEFINE LED2 4
        #DEFINE LED3 8
        #DEFINE LED4 16
        #DEFINE LED5 32
        #DEFINE LED6 64
        #DEFINE LED7 128
    
    
        If __state = On then
            __portstatus = __portstatus OR __port
        else
            __portstatus = __portstatus XOR __port
        end if
    
        //! send to the I2C device that sets the PCF8574 ports
            PCF8574_sendbyte(PCF8574_DEVICE_1, __portstatus )
    
    End Sub
    
     
  • Keith

    Keith - 2023-04-09

    I have another annoying problem that I cannot resolve. A single instruction

    PCF8574Port Off, LED0 (the logic is inverted)

    Turns on the port 0 but then it begins to oscillate at almost 1 second. I have double checked that there is nothing else in the routine to make it turn on or off.

     
    • Anobium

      Anobium - 2023-04-09

      Attach the program. Else, I would be guessing.

       
  • Keith

    Keith - 2023-04-09
      Do
    
          HSerPrint "Send to PCF8574 0x"
        HserPrint hex(ledstatus)
        HSerSend 9
        //! send a variable to the I2C device that sets the device ports
        //    PCF8574_sendbyte(PCF8574_DEVICE_1, ledstatus )
              PCF8574_sendbyte(PCF8574_DEVICE_1, low )
    
     ;   wait 1000 ms
        //! read the status of the port into the variable portstatus
            PCF8574_readbyte(PCF8574_DEVICE_1, portstatus )
        HSerPrint "Recieved from PCF8574 0x"
        HSerPrintStringCRLF hex((portstatus & 0XF0 ) / 16 )
    
    ;    Set C Off
    ;    Rotate ledstatus left
    ;    if ledstatus = 16 then ledstatus = 1
    ;      PCF8574Port On, LED1 + LED2 + LED3
    
          PCF8574Port Off, LED0     ; Turn on Port P0 
    
    
    
     Sub PCF8574Port ( __state, __port )
    
    Dim __portstatus as Byte
    //! read the status of the port into the variable __portstatus
    PCF8574_readbyte(PCF8574_DEVICE_1, __portstatus )
    
    #DEFINE LED0 1
    #DEFINE LED1 2
    #DEFINE LED2 4
    #DEFINE LED3 8
    #DEFINE LED4 16
    #DEFINE LED5 32
    #DEFINE LED6 64
    #DEFINE LED7 128
    
    If __state = On then
        __portstatus = __portstatus OR __port
    else
        __portstatus = __portstatus XOR __port
    end if
    
    //! send to the I2C device that sets the PCF8574 ports
        PCF8574_sendbyte(PCF8574_DEVICE_1, __portstatus )
    End Sub     
    
     
  • Keith

    Keith - 2023-04-09

    This is a video of what is presented with the current code. It should be on solid but instead it oscillates

     

    Last edit: Keith 2023-04-09
  • Anobium

    Anobium - 2023-04-09

    What does this do? and, what is the value of low

    PCF8574_sendbyte(PCF8574_DEVICE_1, low )

      `Low` meant to be a value?
    
     
  • Keith

    Keith - 2023-04-10

    It doesn't do what I thought it would do change the output polarity, but instead all it does is to interfere with the port 1 output.

    I'm beginning to get the feeling that this device is not going to do what I'm expecting it to do. I have stripped the program down to the bare minimum to where I thought I had established what was causing the On/ Off cycling. The stripped program is below:

    Initially all four ports are turned on which extinguishes the four LED's and if you omit the 100ms wait statement it gives you the impression that LED 0 is on solid - success !!
    but with the wait statement or in fact any other programming code causes LED 0 to flash on and off without being told to turn off anywhere in the routine.

    I am minded to change tack and either use a 3 to 8 line decoder, start back at the beginning with another board reconfigured to give me 8 I/O ports or as a last resort cross over onto the Dark Side with an Arduino.

    ;;;;  Spindle Motor Coolant Temperature Controller.
    ;;;; Project Date 19:59 29.01.2023
    
    
    #chip 16F18326, 32
    
     #option NoConfig
     #include <DS18B20.h>
     #include <I2CEEPROM.h>
     #INCLUDE <PCF8574.H>
     #include <Encoder.h>
    
     #option explicit
    
        #startup InitPPS, 85
        #define PPSToolPart 16lf18326
    
                 'SDA1 > RC1 (bi-directional)
    
    ; ----- Define Hardware settings
      '     Define I2C settings - CHANGE PORTS if required
    
     #define HI2C_BAUD_RATE 400
     #define HI2C_DATA PORTC.1
     #define HI2C_CLOCK PORTC.0
     #define DQ PortC.2
    
    ; ---- Encoder
     #define ENCODER_A PortA.4       ;sometimes called CLK
     #define ENCODER_B PortA.5       ;sometimes called DT
     #define ENCODER_SW PortC.5      ;the central switch
    ;
     #define Pump PORTC.3
     #define Fan PORTC.4
    
      ; ----- Define 24LC256 or 24LC512 EEProm
     #define eepDev 0xA0              'Change this ADDRESS to suit
     #define EEpromPageSize 32        'Change this typical 16, 32, 64, or 128.
    
    
     '                16F18326
    '                 -------
    '            VDD-|1    14|-Vss
    '            RA5-|2    13|-RA0 - DAT
    '    AN4 IN  RA4-|3    12|-RA1 - CLK
    '      MCLR  RA3-|4    11|-RA2
    '            RC5-|5    10|-RC0 - I2C CLK
    '   modeBut  RC4-|6     9|-RC1 - I2C DAT
    '    setBut  RC3-|7     8|-RC2
    '                 -------
    
    
     #DEFINE USART_BAUD_RATE 19200
     #DEFINE USART_TX_BLOCKING
    
     ; ----- Define 24LC256 or 24LC512 EEProm
    ; #define eepDev 0xA0              'Change this ADDRESS to suit
    ; #define EEpromPageSize 32       'Change this typical 16, 32, 64, or 128.
     #define EEpromPageSize 32        'Change this typical 16, 32, 64, or 128.
    
    
    'Initialise I2C Master
    'I2C pins need to be input for SSP module
    Dir HI2C_DATA In
    Dir HI2C_CLOCK In
    'MASTER Second Port
    HI2CMode Master
    
     '''Set up LCD
     '''Set LCD_10 to 10 for the YwRobot LCD1602 IIC V1 or the Sainsmart LCD_PIC I2C adapter
     '''Set LCD_10 to 12 for the Ywmjkdz I2C adapter with pot bent over top of chip
    #DEFINE LCD_IO 10
    
    'You may need to use SLOW or MEDIUM if your LCD is a slower device.
    #DEFINE LCD_SPEED FAST
    'You may need to invert these states. Dependent of LCD I2C adapter.
    #DEFINE LCD_Backlight_On_State  1
    #DEFINE LCD_Backlight_Off_State 0
    #define LCD_I2C_Address_1 0x7E
    
    #DEFINE PCF8574_DEVICE_1 0X7A
    
        Dim DSDATA,  as Byte
        Dim TempC_100 as word
        Dim WHOLE, FRACT, DIG as Byte
        Dim LEDStatus as Byte
        Dim PortStatus as Byte
        Dim Temp as Byte
        Dim TargetT as Byte
        Dim TempT as Byte
    ;    Dim Pump as Byte
        dim value as Word
        Dim Target as Byte
        Dim Whole_Number as Word
        Dim Decimal_Value as Byte
        Dim ledstatus,portstatus as Byte
    
    
     Initialise
    
     ' SPLASH SCREEN 1
          CLS
          Locate 0,3
          Print "SPINDLE MOTOR"
          Locate 1,6
          Print "COOLING"
          Locate 2,5
          Print "CONTROLLER"
          Locate 3,2
          Print ChipNameStr
          Locate 3,11
          Print "@"
          Locate 3,13
          Print ChipMhz
          Locate 3,15
         Print "Mhz"
          wait 3 S
          CLS
    
    
    Main:       ;----- start main
    
     Deg_Symbol            ; Call Degree Symbol Routine
    
    //Locate 2,5
    //Print value
    
      Do
    ;      HSerPrint "Send to PCF8574 0x"
    ;   HserPrint hex(ledstatus)
    ;    HSerSend 9
        //! send a variable to the I2C device that sets the device ports
          //  PCF8574_sendbyte(PCF8574_DEVICE_1, ledstatus )
          //  PCF8574_sendbyte(PCF8574_DEVICE_1, 0 )
    
    
    ;    PCF8574Port Off, LED0
    wait 100 ms
        PCF8574Port Off, LED0
    
    
      Loop
    
    
    goto Main
    
    ;----- end main
    
    
    
    Sub EPReadWord(IN EEAddress, OUT epWordVar as Word)
        EPREAD(EEAddress, epWordVar)
        EPREAD(EEAddress+1), epWordVar_H
    End sub
    
    
    
    Sub PCF8574Port ( __state, __port )
    Dim __portstatus as Byte
    //! read the status of the port into the variable __portstatus
    PCF8574_readbyte(PCF8574_DEVICE_1, __portstatus )
    
    #DEFINE LED0 1
    #DEFINE LED1 2
    #DEFINE LED2 4
    #DEFINE LED3 8
    #DEFINE LED4 16
    #DEFINE LED5 32
    #DEFINE LED6 64
    #DEFINE LED7 128
    
        If __state = On then
            __portstatus = __portstatus OR __port
          else
            __portstatus = __portstatus XOR __port
        end if
    
    //! send to the I2C device that sets the PCF8574 ports
        PCF8574_sendbyte(PCF8574_DEVICE_1, __portstatus )
    End Sub
    
    
    
    
    Sub Initialise
    ; Read data from 24LC256 EEProm
    
      PCF8574Port On, LED0 + LED1 + LED2 + LED3
    
    
    End Sub
    
        Sub InitPPS
                UNLOCKPPS
    
                'Module: EUSART
                RA0PPS = 0x0014    'TX > RA0
                RXPPS = 0x0001     'RA1 > RX
    
                'Module: MSSP1
                RC1PPS = 0x0019    'SDA1 > RC1
                SSP1DATPPS = 0x0011    'RC1 > SDA1 (bi-directional)
                RC0PPS = 0x0018    'SCL1 > RC0
                SSP1CLKPPS = 0x0010    'RC0 > SCL1 (bi-directional)
    
    
        End Sub
    

    Initially all four ports are turned on which extinguishes the four LED's and if you omit the wait

     

    Last edit: Keith 2023-04-10
  • Anobium

    Anobium - 2023-04-10

    What is inside <Encoder.h> - an interrupt?
    What is going on the I2C bus? Other devices chattering? Check with a scope.
    How are the LEDs attached the PCF? Are you pulling to much current?
    Is the 18f18326 chattering in the I2C lines when in the wait? Check with a scope.

     
<< < 1 2 (Page 2 of 2)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.