PPS is the system where peripherals can be moved to any RP pin. It is this that #PIN SELECT drives.
The I2C, only supports two sets of pins, and these are selected in the fuses.
Just use the fuse ALTI2C2, and then don't specify the pins in the setup. Use:

#use i2c(I2C2,FAST=400000)

Using the device name automatically selects 'FORCE_HW'.

daveh

Joined: 30 Aug 2013Posts: 17

Posted: Mon Dec 04, 2017 10:14 am

Thanks for your feedback Ttelmah, I'm still having some problems. I tried to simplify the program as basic as possible (see below). When I compile with the FORCE_SW line I can see the clock on B6 and data on B5. When I compile with hardware I see the clock high and data low.

I noticed with hardware I2C enabled, if I remove my I2C device I can then see both data and clock (sw can communicate with the device fine). My supply is 3.3v. Initially my pull-ups were 1k, I also tried 2k. My device spec shows a SCL clock frequency of 100-400kHz (I also tried 200).

The chip specifically says it needs 60mSec after power on, before it can be used. The PIC will also probably start earlier than the chip does, so try 100mSec as shown.

daveh

Joined: 30 Aug 2013Posts: 17

Posted: Mon Dec 04, 2017 12:48 pm

Thanks Ttelmah, I tried adding the delay as you suggested and I'm getting the same thing.

When I unplug the sensor I can see clk/data on the scope. The levels look the same as when I switch to SW. Interestingly, if I remove either the CLK or the DATA line to the sensor the HW will send, if both are connected then CLK goes to 3.3v and DATA to 0v.

temtronic

Joined: 01 Jul 2010Posts: 6805Location: Greensville,Ontario

Posted: Mon Dec 04, 2017 1:28 pm

hmm...basic question

Have you compiled and run PCM P's I2C Scanner program from the code library ?

With EVERY program using I2C devices this is the FIRST program to run ! It'll confirm basic hardware and device access.

I'm not sure it would be helpful with my current problem. If I compile my code with FORCE_SW it works fine (and my more complete program is able to get valid data from the I2C device w/o a problem). However when I attempt to compile the basic program shown above with the hardware I2C module the SCL simply stays at 3.3v and never moves and the SDA stays at 0v and never moves.

If I disconnect the SDA line to the sensor the hardware module starts sending data, or, if I disconnect the SCL line from the sensor the hardware module starts sending data. If both are connected nothing changes.

temtronic

Joined: 01 Jul 2010Posts: 6805Location: Greensville,Ontario

Posted: Mon Dec 04, 2017 2:15 pm

hmm I'm wondering if the batch of PICs you're using have an 'errata' as it sounds like you've narrowed down to PIC I2C hardware.
Any chance you've got another PIC to try ? Maybe yours is damaged ??

Ttelmah

Joined: 11 Mar 2010Posts: 14603

Posted: Mon Dec 04, 2017 2:33 pm

Looking at the data, I'm not actually sure it is legal to read without first having triggered an acquisition. The sensor is 'powered down' until this is sent.
Now the software I2C might well 'plough through' an invalid state after the I2C command....

Quote:

By default, the digital output humidity sensor performs humidity
measurement and temperature measurement conversions
whenever it receives a Measurement Request (MR) command;
otherwise, the digital output humidity sensor is always powered
down. The results are stored after each measurement in output
registers to be read using a Data Fetch (DF) command.

Reading the sheet, the chip doesn't respond as a normal I2C device is meant to. The write is used as a trigger to start the chip, not as a flag for the actual write, and then the read has to be repeated till the status bytes are 00, before the data is legitimate. Given the 'sleep' comment I don't think it will respond correctly without the initial write.
The software is allowing the invalid response, but with the hardware it hangs the port...

There have been threads in the past where people have tried doing things like this, and found the hardware I2C doesn't like it.

Starting with both the SDA & SCL high, when the PIC sends HU01ADDR8 I'll see data on the scope. If I reset the PIC before it sends HU01ADDR8|1 it will continue to send the address after each reset(visible on the scope). If however I allow it to send the second address 'HU01ADDR8|1' then the HU sensor holds SDA low and won't release it. It will continue to hold SDA low until I remove the HU sensor and SDA goes high.

Any thoughts on why it would be holding SDA low and never release it?

Also I think with the software enabled I'd actually only get an 'ACK' every other read, so maybe it would push the write out even if SDA was held low?

I've seen I2C code where before they start writing they toggle the SCL while watching for the SDA line to go high. Is this good practice? I'm guessing it's for a situation like this. Can I do something like this while using the hardware module?

Ttelmah

Joined: 11 Mar 2010Posts: 14603

Posted: Tue Dec 05, 2017 12:07 am

Before doing anything else, stop, and triple check your connections. The clock is clocked once for the ACK. The only line that is _held_, is the SCL, which the slave will hold low till it is is ready.

daveh

Joined: 30 Aug 2013Posts: 17

Posted: Tue Dec 05, 2017 10:56 am

I checked connections again, everything seems good. To verify, I re-loaded my software I2C program and with the same connections I can read valid data from the sensor.

Ok, I think I figured out the problem. So when a read is requested from this particular sensor an i2c_read MUST take place, and the last read MUST be followed with a NACK before the STOP or else it will hold the SDA line low!

Apparently with the hardware I2C module it will not attempt to write or clock if the SDA is held low. With the software it seems it will write even if the SDA is held low.

If the data line (SDA) is stuck LOW, the master should send nine clock pulses. The device
that held the bus LOW should release it sometime within those nine clocks. If not, then
use the HW reset or cycle power to clear the bus.

With software I2C this can happen but it doesn't seem possible with the hardware I2C module. It appears that once the I2C slave holds the SDA low the hardware module will no longer output anything.

Any suggestions?

Ttelmah

Joined: 11 Mar 2010Posts: 14603

Posted: Tue Dec 05, 2017 11:31 am

The hardware will accept the SDA being held low.

You need to test the SDA line after the command, and if it is held low (the error), clock nine pulses out the clock line (disable the port and send these), then re-enable the port.
The software doesn't care that the line is held, so sends 9 clocks when you next transmit a byte. the hardware stops because it knows the bus shouldn't be in this state, waiting for you to fix it....