News:

;) This forum is the property of Proton software developers

Main Menu

Strange I2CIN values on unconnected ports

Started by Frizie, Apr 26, 2026, 11:09 AM

Previous topic - Next topic

Frizie

I have two (I2C) MLX90614 temperature sensors on a PIC18F45K22 (or 18F46K22).
The clocks of both sensors are connected to PORTB.7 using a 4k7 pull-up resistor.

One sensor is connected to PORTB.6 and the other to PORTB.4.

When I connect the sensors, they measure temperatures perfectly.

But when I disconnect them (so only the 4k7 pull-up resistors remain on the ports), I get a different value for each port that shows a certain ratio.
Port:  -  SensorValue:  -  Celsius:
PORTB.0 = 65268 = 257
PORTB.1 = 65273 = 514
PORTB.2 = 65283 = 1028
PORTB.3 = 65304 = 2056
PORTB.4 = 65345 = 4112
PORTB.5 = 65427 = 8224
PORTB.6 = 16448 = 55

If you look closely, you will see that the "random" values of the ascending ports have doubled each time.

I would like to detect that a sensor is not connected.
For PORTB.4 , that is not a problem: If Celsius > 1000, then no sensor is connected.
For the sensor on PORTB.6 , this is a problem, because 55 is a temperature that can be reached if the sensor is connected.

My question is, where do those "random" values come from if only 4k7 resistors are connected to the ports?


DEVICE = 18F46K22             ;PIC18F45K22 has the same result
 
CONFIG_START
  FOSC = INTIO67              ;Internal oscillator block
CONFIG_END
 
DECLARE XTAL      = 16        ;Internal clock on 16MHz
 
DECLARE LCD_ENPIN = PORTD.2   ;\
DECLARE LCD_RSPIN = PORTD.3   ;| Alternate PORT pins for the LC-Display (LCD)
DECLARE LCD_DTPIN = PORTD.4   ;/
 
OSCCON  = %01110000           ;16MHz internal oscillator
 
DIM Celsius         AS WORD   ;Calculate MLX90614 value to Celsius
DIM SensorTempRaw   AS WORD   ;Measured temperaturesensor-value from a MLX90614 temperatuursensor
DIM PIC_RunControl  AS BYTE   ;Counter on display to control if PIC runs
 
CLEAR
DELAYMS 250
 
DO
  I2CIN PORTB.4, PORTB.7, 0, $07, [SensorTempRaw.LOWBYTE, SensorTempRaw.HIGHBYTE]
  Celsius  = (SensorTempRaw / 50) - 273  ;Formula measured sensor value to Celsius
  DELAYMS 250
  INC PIC_RunControl
  PRINT AT 1, 1, ">>", DEC Celsius, "<<  ", AT 2, 10, DEC PIC_RunControl, "  "
  PRINT AT 2, 1, ">>", DEC SensorTempRaw, "<<   "
LOOP
(*
4k7 pull-up resistors on all PORTB ports (incl. PORTB.7)
b.0 = 65268 =  257
b.1 = 65273 =  514
b.2 = 65283 = 1028
b.3 = 65304 = 2056
b.4 = 65345 = 4112
b.5 = 65427 = 8224
b.6 = 16448 =   55
*)

Frizie.
Ohm sweet Ohm | www.picbasic.nl

trastikata

Hi Frizie,

with I2C command and no connected device the command remains in a loop (from my past experience) because there's no valid address or command to acknowledge, so it is very strange how it exists the loop?

I guess teh data pin is also pulled high by a 4k7 resistor?

RGV250

Hi,
I doubt it makes a difference but it uses SMBus, not I2C which is similar.
why do you not give each of them a slave address and then you can have them both on the same BUS. You can poll each device and if you do not get a response it is disconnected.
Again, probably no difference but the datasheet shows 3.3k pull ups.

Regards,
Bob

Frizie

#3
Bob, the sensor works fine when it is connected.
The issue here is when no sensor is connected, so the MLX90614 has nothing to do with this problem.

Tratikata, for the test, I have 4k7 pull-up resistors on all ports.
If I do not apply a pull-up resistor to the relevant ports, I2CIN returns the value 0.

I have now also tested the other ports one by one by entering PORTA.0...A.6, PORTC.0...C.6, and PORTD.0...D.6 for the SDA_pin.

The result is the same as for PORTB.0...B.6.

Only if the SDA_pin bit 7 of a port is filled in, then the result is correct, namely the value 0
So:
Ports:                           Value:    Celsius:
a.0 = b.0 = c.0 = d.0 = 65268 =     257
a.1 = b.1 = c.1 = d.1 = 65273 =     514
a.2 = b.2 = c.2 = d.2 = 65283 =   1028
a.3 = b.3 = c.3 = d.3 = 65304 =   2056
a.4 = b.4 = c.4 = d.4 = 65345 =   4112
a.5 = b.5 = c.5 = d.5 = 65427 =   8224
a.6 = b.6 = c.6 = d.6 = 16448 =       55
a.7 = b.7 = c.7 = d.7 =         0 = 65263  << Bit 7 from the ports seems ok

Once again, the question is:
Where do those values (increasing per port.bit) come from if only a pull-up resistor is connected to the relevant port?

(I'm running V.4.0.5.7)
Ohm sweet Ohm | www.picbasic.nl

streborc

I don't have an immediate answer for the odd progression of values that are appearing on PortB, but as far as detecting a disconnected sensor, you should be able to detect this when the sensor fails to respond to the read command with an expected ACK pulse.  I don't know if Positron's I2CIn has an ACK error detection mechanism -- Les can comment here -- but it's simple enough to bit-bash the read command and check for the ACK.  (I think there's an I2C pinger somewhere on the forum that sends sequential I2C read addresses and looks for an ACK reply as a means of checking a device's I2C address.)

There are some subtle differences between I2C and SMBus -- the TI app note https://www.ti.com/lit/an/sloa132/sloa132.pdf?ts=1777161822437 might shed some light on what's going on (if you've not already seen this).

Frizie

Thanks for the answer Streborc, but:

Quote from: streborc on Apr 26, 2026, 03:13 PM...odd progression of values that are appearing on PortB...
Not only for PORTB, it applies to all ports (see post #3)


Quote from: streborc on Apr 26, 2026, 03:13 PM...There are some subtle differences between I2C and SMBus...
This has nothing to do with my question, because the problem occurs when the sensor is not connected.
So the discussion about whether it is I2C or SMbus is irrelevant here.


Quote from: streborc on Apr 26, 2026, 03:13 PM...it's simple enough to bit-bash the read command and check for the ACK...
This may be the case, but again, it's not the question.

My only question is:
Where do those values (increasing per port.bit) come from if only a pull-up resistor is connected to the relevant port?
I am purely interested in knowing where those values come from.

Unfortunately, my assembler knowledge is poor, so I can look at the produced assembler, but I can't get much out of it.
Ohm sweet Ohm | www.picbasic.nl

RGV250

Hi,
Have you tried it without the pull ups?, I wonder if there is some analog thing going on?

Looking at your code, what happens if you clear SensorTempRaw at the start of the loop?

Bob

RGV250

#7
Hi,
I am not sure why but I ran it in a VSM and as there is no device it appears to clock the port in so if pins 0 & 7 are used they will be 1 so it clocks in 0000000100000001 which is 256 + 1 = 257.
if it is 1 & 7 it clocks in 000000100000010 which is 512 + 2 = 514
if it is 2 & 7 it clocks in 000001000000100 which is 1024 + 4 = 1028
and so on.

It does not seem to matter what clock pin is used but I think it is still to do with above.

Bob

streborc

Not included in your code listing are ANSEL and TRIS initializations.  Has ANCELB been set to %00000000 and TRISB set to %01111111?

Frizie

Have tested it on a 16F648A and there is the same problem.
The 16F648A has no analog ports.
Configuring TRIS is normally not necessary here because the I2CIN instruction sets it automatically.

The only difference compared to an 18F45K22 is that this device gives the value 0 at PORTA.7, while the 16F648A gives the value 32896.
The other ports give the same "strange" values.

@Bob,
The program starts with CLEAR, so all variables are cleared at the start.
The values you are comparing are the Celsius values, not the values that I2CIN provides...
To avoid confusion, I am going to rephrase my question with as little background information as possible.
Ohm sweet Ohm | www.picbasic.nl

Frizie

#10
R E S E T  Q U E S T I O N


I2CIN SDA_Pin, PORTE.0, 0, $07, [MyVariable.LOWBYTE, MyVariable.HIGHBYTE]


If there is no pull-up resistor on the SDA_Pin, I2CIN returns the value 0 in 'MyVariable'

If I connect a 4k7 pull-up resistor to the SDA_Pin (nothing else), then each PORT.bit returns a different value in 'MyVariable', see table:

PORTx.0 returns 65268
PORTx.1 returns 65273
PORTx.2 returns 65283
PORTx.3 returns 65304
PORTx.4 returns 65345
PORTx.5 returns 65427
PORTx.6 returns 16448
PORTx.7 returns 0         on a 18F4xK22
PORTx.7 returns 32896 on a 16F648A

It does not matter whether x is PORTA, PORTB, PORTC, or PORTD; the return values are the same for all ports.
I expect that if the SDA_Pin of I2CIN is high (due to a pull-up resistor), a value of 0 or 65535, not another value.

This is a serious problem, and to find a solution to this problem, we first need to know where those values come from.
Ohm sweet Ohm | www.picbasic.nl

RGV250

#11
Hi,
QuoteThe values you are comparing are the Celsius values, not the values that I2CIN provides...
The values I am referring to are what is in SensorTempRaw which is the variable clocked in with the I2C command.

QuoteThe only difference compared to an 18F45K22 is that this device gives the value 0 at PORTA.7
I tested this on the 18F26K22 and it gives 32896 (1000000010000000), the same as on portB.7

QuoteThe program starts with CLEAR, so all variables are cleared at the start.
You use clear before the loop and I have found sometimes it is required to clear the variable before the calculation but that does not help in my sim.

Bob