I ported my first library! MCP9600

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
Curly Tale Games
Posts: 10
Joined: Sat May 29, 2021 5:32 am

I ported my first library! MCP9600

Post by Curly Tale Games » Sat Jun 05, 2021 3:26 am

This is my first post! I've been playing with Micropython for a few months now and love it.

I've been working on an open source web based kiln controller that runs on an ESP32 with Micropython and I couldn't find a library for the MCP9600 i2c temperature sensor. There was a CircuitPython one, so I went through it and ported all the dependencies and used some built in Micropython libraries.

It's all python, so it wasn't too difficult once I got started. I forked the Adafruit Github repo and added my changes to it. You can check it out here:
https://github.com/CurlyTaleGamesLLC/Ad ... on_MCP9600

I'm sure I missed something, or didn't do something the most efficient way, but I tested it out in salted ice water and held it between my fingers and it seems to be working. I checked it with a infrared thermometer and it seemed to match the readings.

Enjoy!
-Ben

Curly Tale Games
Posts: 10
Joined: Sat May 29, 2021 5:32 am

Re: I ported my first library! MCP9600

Post by Curly Tale Games » Fri Jul 02, 2021 4:59 am

So I've been playing with this library for a little while now and for some reason it would only work for me at lower frequencies. I was trying to send the signal over a medium length CAT6 cable so I figured it must be related to that but after a lot of troubleshooting I figured out the problem.

The documentation for setting up an I2C device is unclear. From the documentation you would think you would need to include the hardware I2C bus ID when you are creating an instance of the I2C class:

https://docs.micropython.org/en/latest/ ... re-i2c-bus
https://docs.micropython.org/en/latest/ ... e.I2C.html

However once I removed it from my code I could all of a sudden talk to the MCP9600 at 100khz over a 50 foot ethernet cable.

Code: Select all

# This what I had before, and it doesn't work:
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)

# This works:
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=100000)
I've pushed an update with that fix to the Github repo.

Does anyone know why removing the I2C bus ID makes it work? Is the documentation wrong?

Thanks,
-Ben

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

I2C over 50 feet of cable?

Post by pythoncoder » Fri Jul 02, 2021 11:46 am

I'm astounded that I2C works over 50 feet of cable. The fact that it relies on pullup resistors implies a limit to the capacitance that can be driven. My understanding is that I2C was designed for communication between chips on the same PCB.
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: I ported my first library! MCP9600

Post by Roberthh » Fri Jul 02, 2021 2:19 pm

The capacitance value I find for cat6 cable are 40-50 nF/km. At 50 feet, that is less than 0.6 - 0.75 nF, which is pretty low. With low value pull-up (<4.7K) that could work at 100000 baud.

User avatar
mattyt
Posts: 410
Joined: Mon Jan 23, 2017 6:39 am

Re: I ported my first library! MCP9600

Post by mattyt » Mon Jul 05, 2021 3:43 am

Curly Tale Games wrote:
Fri Jul 02, 2021 4:59 am

Code: Select all

# This what I had before, and it doesn't work:
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)

# This works:
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=100000)
I've pushed an update with that fix to the Github repo.

Does anyone know why removing the I2C bus ID makes it work? Is the documentation wrong?
I'll take a guess; Using the 0 for the ID instantiates an I2C object supported by microcontroller hardware. Without that ID a software - ie, bitbanged - I2C object is created. My guess is that the hardware I2C object is running at the requested frequency and the software I2C object is actually running slower than 100KHz. The slower rate will mean the signal isn't attenuated so much and longer distances may be possible.

By the way, I2C transmission lengths are usually measured in cm not feet! Longer distances require great care to ensure signal integrity.

Note that this subtle difference when creating the I2C (and SPI) objects is slowly being deprecated in favour of explicit declarations.

Curly Tale Games
Posts: 10
Joined: Sat May 29, 2021 5:32 am

Re: I ported my first library! MCP9600

Post by Curly Tale Games » Sun Jul 11, 2021 6:30 pm

Hmm if that's the case why would software I2C be faster and more reliable than hardware I2C on the ESP32? The fastest frequency I could get working with the I2C Bus ID was 15khz.

Also according to the documentation there is another class called "SoftI2C" which is used for software I2C. I'm not importing that class in my code.
https://docs.micropython.org/en/latest/ ... re-i2c-bus

As a test to see if I was truly getting 100khz I sampled it with a logic analyzer and it looks like I'm only getting 85khz, I tested it with a 1 foot long CAT6 cable and got the same speed so I don't think it's related to cable length.
i2c-freq.png
i2c-freq.png (101.75 KiB) Viewed 4120 times
code-smaller.png
code-smaller.png (183.67 KiB) Viewed 4120 times

Curly Tale Games
Posts: 10
Joined: Sat May 29, 2021 5:32 am

Re: I ported my first library! MCP9600

Post by Curly Tale Games » Sun Jul 11, 2021 7:12 pm

Alright I think I figured it out. The documentation says you can use any pins you want.
https://docs.micropython.org/en/latest/ ... re-i2c-bus
hardware-i2c-pins.png
hardware-i2c-pins.png (66.86 KiB) Viewed 4115 times
And since most of the examples I found online, as well as the ESP32 pinouts diagrams used pins 21 and 22 for i2c, that's what I was using:
ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated.jpg
ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated.jpg (120.35 KiB) Viewed 4115 times
When I switched my code to be:

Code: Select all

i2c = I2C(0, freq=100000)
# I2C bus ID 0 default pins:
# scl = 18
# sda = 19
code-working.png
code-working.png (244.98 KiB) Viewed 4115 times
I got 100khz for the frequency:
100khz.png
100khz.png (98.36 KiB) Viewed 4115 times
I think there must be an issue with the I2C class and specifying the I2C bus ID and I2C pins. I feel like that's a bug in Micropython, or at the very least the documentation should be updated so people know that you will get slower speeds if you don't use the default bus i2c pins, and you will get very slow speeds if you define both the bus ID and the I2C pins.

I posted this as an issue on the Github repo:
https://github.com/micropython/micropython/issues/7524

chrismas9
Posts: 152
Joined: Wed Jun 25, 2014 10:07 am

Re: I ported my first library! MCP9600

Post by chrismas9 » Mon Jul 12, 2021 12:06 am

750pF / 4k7 has a cutoff frequency of 45kHz which is low for 100 kHz clock rate. The MCP9600 spec is 1000 ns, 300 ns for rise and fall and 250 ns setup time. It would be better to use an oscilloscope than a logic analyser and check the rise, fall and setup times.

There may be differences in timing, eg setup time, between the soft and hard implementation. There may be differences in drive strength. These will show up on. CRO.

From memory the recommended pull-up for 3.3V is 1k8 although higher values are often used for short distances.

Are you running SCL and SDA on separate pairs with a twisted GND for each? If you run them both on one pair the clock edges can couple into the data and create a false value just when the data is sampled.

Try posting some oscilloscope pictures here

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: I ported my first library! MCP9600

Post by pythoncoder » Tue Jul 13, 2021 10:44 am

Roberthh wrote:
Fri Jul 02, 2021 2:19 pm
The capacitance value I find for cat6 cable are 40-50 nF/km. At 50 feet, that is less than 0.6 - 0.75 nF, which is pretty low. With low value pull-up (<4.7K) that could work at 100000 baud.
Possibly, although a ~3μs risetime isn't great. But capacitance isn't the only issue when driving an unterminated transmission line. The low going edge will be fast. There could be reflections with ringing. When driving lines of that length I would advocate line driver chips and appropriate termination.

Failing that, for a one-off amateur project, stick a scope on it and have a close look at what's actually going on. I certainly wouldn't rely on blind faith...

As @mattyt said
I2C transmission lengths are usually measured in cm not feet!
Peter Hinch
Index to my micropython libraries.

Curly Tale Games
Posts: 10
Joined: Sat May 29, 2021 5:32 am

Re: I ported my first library! MCP9600

Post by Curly Tale Games » Wed Jul 14, 2021 12:46 am

Thanks for the responses. Yeah I definitely know I'm pushing I2C well beyond what it was originally meant for. But I've been testing with a short 1 foot long CAT6 cable and I'm getting the same results so I feel like I can safely rule out cable length as the problem here.

Unfortunately I don't have an oscilloscope. This is honestly the first time I've really needed one before. The logic analyzer seems to be giving me roughly the data I need to see if I'm making improvements or not. I can see consistent results to the I2C frequency changing when I change the parameters used in the instantiation of the I2C object

I actually had another thread going on the Adafruit forum. I originally thought my issues were stemming from an LTC4311 module not functioning correctly with a long ethernet cable. If you're curious you can read through and see all the fun screenshots of the signals here:
https://forums.adafruit.com/viewtopic.p ... 11#p880126

My current wiring for the twisted pairs in the ethernet cable is:

Code: Select all

3V/3V
SDA/SDA
SCL/GND
SCL/GND
In the Adafruit thread Mike recommended adding a 100 ohm resistors in series with the SDA and SCL wires at the far end of the cable. And also pairing up 3V/SDA. I haven't tested that yet. I'm sure it'll improve the signal even more, but it won't fix the frequency issue I was running into before.

The frequency issue seems to be fixed now that I figured out the correct parameters to pass.

I posted that issue to the MicroPython github repo, is there a way to post an issue with the documentation as well? It took me a while to figure out what the problem was and I'd like to help make sure other people don't run into the same issue.

Thanks!
-Ben

Post Reply