i2c Does not want to show what's on the bus?

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
LEEDNH
Posts: 42
Joined: Fri Feb 03, 2017 8:44 pm

i2c Does not want to show what's on the bus?

Post by LEEDNH » Tue Apr 06, 2021 3:14 am

Hello LEEDNH here again ...

I thought that I would try out the i2c scanner by bitfogav. The program is a great idea in so far as, if the i2c device isn't found by the scanner, one could rest well assured that sending or receiving data to the device would be a fool's errand...

What I did: copied the code, had to change the pic to an18f24k22 as I did not have the device used in the published code, and I took the liberty of adding a couple of spaces at the beginning of each line of output....

When the compiled code is run, every scanned address appears as being present.
The exact code I used follows:
I sure hope that I didn't do anything too stupid...

Code: Select all

      
      
   Device = 18F24K22
   Clock=16  

   Config
    FOSC = HSMP,        // HS oscillator (medium power 4-16 MHz)
    PLLCFG = OFF,       // Oscillator used directly
    PRICLKEN = ON,      // Primary clock enabled
    FCMEN = OFF,        // Fail-Safe Clock Monitor disabled
    IESO = OFF,         // Oscillator Switchover mode disabled
    PWRTEN = OFF,       // Power up timer disabled
    BOREN = SBORDIS,    // Brown-out Reset enabled in hardware only (SBOREN is disabled)
    BORV = 250,         // VBOR set to 2.50 V nominal
    WDTEN = ON,         // WDT is always enabled. SWDTEN bit has no effect
    WDTPS = 32768,      // 1:32768
    CCP2MX = PORTC1,    // CCP2 input/output is multiplexed with RC1
    PBADEN = OFF,       // PORTB<5:0> pins are configured as digital I/O on Reset
    CCP3MX = PORTC6,    // P3A/CCP3 input/output is mulitplexed with RC6
    HFOFST = ON,        // HFINTOSC output and ready status are not delayed by the oscillator stable status
    T3CMX = PORTC0,     // T3CKI is on RC0
    P2BMX = PORTB5,     // P2B is on RB5
    MCLRE = EXTMCLR,    // MCLR pin enabled, RE3 input pin disabled
    STVREN = ON,        // Stack full/underflow will cause Reset
    LVP = OFF,          // Single-Supply ICSP disabled
    XINST = OFF,        // Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    DEBUG = OFF,        // Disabled
    CP0 = OFF,          // Block 0 (000800-001FFFh) not code-protected
    CP1 = OFF,          // Block 1 (002000-003FFFh) not code-protected
    CPB = OFF,          // Boot block (000000-0007FFh) not code-protected
    CPD = OFF,          // Data EEPROM not code-protected
    WRT0 = OFF,         // Block 0 (000800-001FFFh) not write-protected
    WRT1 = OFF,         // Block 1 (002000-003FFFh) not write-protected
    WRTC = OFF,         // Configuration registers (300000-3000FFh) not write-protected
    WRTB = OFF,         // Boot Block (000000-0007FFh) not write-protected
    WRTD = OFF,         // Data EEPROM not write-protected
    EBTR0 = OFF,        // Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
    EBTR1 = OFF,        // Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
    EBTRB = OFF         // Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

// import libraries...   
   Include "usart.bas"
   Include "convert.bas"
   Include "I2C.bas"

   Dim nDevices As Byte

   Sub ScanForDevices()
   Dim addrs, error As Byte

   nDevices = 0 ' reset 

   For addrs = 0 To 126 Step 2
      I2C.Start()
      I2C.WriteByte(addrs)
      I2C.Stop()

      If (I2C.NotAcknowledged = true) Then
      	error = 1    ' no device
      Else
      	error = 0    ' device detected
      EndIf 

      If error = 0 Then   ' no error we have found a device.
         USART.Write("   $", HexToStr(addrs), 13, 10)
         Inc(nDevices)    ' found a device so add number of device.
      End If

      ' add a little delay betweens transactions for some slow slave devices
      DelayUS(100)
   Next

   USART.Write("   ",DecToStr(nDevices), " I2C device(s) found", 13, 10)
   End Sub

// init I2C... 
   I2C.Initialize(I2C_100_KHZ)

// start serial...
   USART.SetBaudrate(br19200)
   USART.Write("   I2C Scanner", 13, 10)
   USART.Write("   By Gavin Wiggett (Bitfogav)", 13, 10)

// main prog loop...
   While true 
   USART.Write("   Scanning for Devices..", 13, 10)
   ScanForDevices()
   DelayMS(5000)  ' 5sec delay between bus reads. 
   Wend
   

Jerry Messina
Swordfish Developer
Posts: 1486
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: i2c Does not want to show what's on the bus?

Post by Jerry Messina » Tue Apr 06, 2021 10:40 am

No, you didn't do anything stupid. What that example is missing is the IO pin setup to switch pins to digital mode.
Many of the IO pins default to analog mode at startup, and if they're in analog mode they always read '0'.
For I2C that would look like an ACK.

Add this to your '// import libraries' section

Code: Select all

// automatically call SetAllDigital at startup
#option DIGITALIO_INIT = true
include "setdigitalio.bas"
and that will add the call to SetAllDigital for you.

Also, one of the more recent features of the I2C.bas module is a new function

Code: Select all

{
****************************************************************************
* Name    : IsPresent                                                      *
* Purpose : Detect if a slave is present                                   *
*         ; returns true = slave acks addr (present)                       *
*         ;         false= slave nack (not present)                        *
****************************************************************************
}
public function IsPresent(addr as byte) as boolean
If you use that, you can shorten ScanForDevices() to

Code: Select all

Sub ScanForDevices()
    Dim addr As Byte

    nDevices = 0 ' reset total found

    // scan all 'write' addresses
    For addr = 0 To 127
       If (I2C.IsPresent(addr << 1)) then
          Inc(nDevices)    ' found a device so incr total found
          USART.Write("   $", HexToStr(addr<<1), 13, 10)
       Endif
       ' add a little delay between transactions for some slow slave devices
       DelayUS(100)
    Next

    USART.Write("   ",DecToStr(nDevices), " I2C device(s) found", 13, 10)
End Sub
By default, IsPresent() will only scan write addresses (it sets the lsb to 0).
If you wish to have it scan all addresses (write+read) then set '#option I2C_PROBE_RD_ADDR = true' before including I2C.bas
Last edited by Jerry Messina on Tue Apr 20, 2021 12:14 am, edited 2 times in total.
Reason: correct ScanForDevices to scan entire addr range properly

LEEDNH
Posts: 42
Joined: Fri Feb 03, 2017 8:44 pm

Re: i2c Does not want to show what's on the bus?

Post by LEEDNH » Wed Apr 07, 2021 3:08 am

THANKS Jerry!
I spent some time this past weekend trying to trouble shoot the problem. Even looked at the data pin to make sure it wasn't somehow shorted to ground - nope 10k to Vdd. I did notice the last "public" function in the i2c module " IsPresent(addrs) " and tried it as well. All of the code compiled fine. I finally gave up and came here... So I figured I had missed a setting. The include "setdigitalio.bas" and #option DIGITALIO_INIT = true are in ALL my code from now on!

I did notice other "new" for me i2c commands as Open(), Close(), CheckBus(), and ClearBus() - looks like more reading ahead...

Thanks again
Lee

bitfogav
Registered User
Registered User
Posts: 169
Joined: Sat Oct 09, 2010 1:39 pm
Location: United Kingdom

Re: i2c Does not want to show what's on the bus?

Post by bitfogav » Wed Apr 07, 2021 12:07 pm

Sorry LEEDNH that you had trouble with my sample code, and thank you Jerry for fixing the issue. I will update the sample code page, link to this topic for anyone else having any issues.. :)

Jerry Messina
Swordfish Developer
Posts: 1486
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: i2c Does not want to show what's on the bus?

Post by Jerry Messina » Wed Apr 07, 2021 12:19 pm

It's not really a bug in the original code... it all depends on which device you use.
Newer chips tend to have a lot more analog pins, so the risk of running afoul is greater now.

I'd change the default to switch them all to digital, but that would break a lot of existing code.
Plus, the chip powering up in analog mode is there for a reason.

LEEDNH
Posts: 42
Joined: Fri Feb 03, 2017 8:44 pm

Re: i2c Does not want to show what's on the bus?

Post by LEEDNH » Sat Apr 10, 2021 1:43 am

Hello Bitfogav
Bitfogav, please no need to be apologize for anything... If I had used the processor you specified, it would have worked great. I tend to use the k22 series because I've had relatively good luck with them. I very much appreciate your willingness to share your work, as I am sure many others do as well. I was already having trouble with my i2c program and used your routine to "see" if the i2c device was there.
And a particular thanks for the i2c display module!
best regards
Lee

Post Reply