# MCU 'pico' shutdown: i2c timeout

**URL:** <https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848>\
**Category:** General Discussion\
**Created:** [September 17, 2024, 1:01am UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848 "2024-09-17T01:01:49Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![sith\_lord\_baku](https://avatars.discourse-cdn.com/v4/letter/s/b5e925/32.png) [@sith\_lord\_baku](https://klipper.discourse.group/u/sith_lord_baku)\
**Post date:** [September 17, 2024, 1:01am UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/1 "2024-09-17T01:01:49Z")

</div>

### Basic Information:

Printer Model: Mercury One.1  
 MCU / Printerboard: OctopusPro  
 Host / SBC: BITTPI + PiCO  
 klippy.log  
[klippy (14).log](https://klipper.discourse.group/uploads/short-url/ltnBR5FBZIRJamqyLS7bc94GDnN.log) (257.5 KB)

_Fill out above information and_ **_in all cases attach your_ `klippy.log` _file_** (use zip to compress it, if too big). _Pasting your_ `printer.cfg` _is **not** needed_  
_ **Be sure to check our “Knowledge Base” Category first. Most relevant items, e.g. error messages, are covered there** _

### Describe your issue:

SHT15/21 Temp Module Works on gpio pins of the BTTPI - ran into out of memory issues on really long prints, turned i2c off on the bttpi overlay, instaleld a second sensor on a pico, flashed klipper, got the sensor to be seen, but constantly encouters a i2c timeout. pico resources are all low. and i’ve played with the report time to try and pace the temp checks out. Racking ym brain trying to find the issue, figured a second / thrid / 50 sets of eyes might help

…

---

<div class="post-metadata">

**Author:** ![nefelim4ag](https://yyz2.discourse-cdn.com/free1/user_avatar/klipper.discourse.group/nefelim4ag/32/2387_2.png) [@nefelim4ag](https://klipper.discourse.group/u/nefelim4ag)\
**Post date:** [September 17, 2024, 1:22pm UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/2 "2024-09-17T13:22:17Z")

</div>

I will just show you something:

> <https://github.com/Klipper3d/klipper/pull/6674>
>
> I'm not a hardcore embedded guy - I can have wrong assumptions or understanding …here.
> 
> If I understood correctly.
> For now, SPI/I2C is working in synchronous mode, which may shift other events in the scheduler queue.
> I2C is slower in general because it is used with speeds: of 100kHz and 400kHz.
> According to #6141, we can easily calculate timings, 5us per pulse, 18 pulses per byte + ack.
> The average read request looks like 2 bytes write 6 byte read.
> 1 byte ~ 18 \* 5 = 90 us
> 8 byte ~ 90 \* 8 = 720 us
> 
> 400kHz is 4x faster, so 22.5us and 180us with same load.
> SPI is freaking fast, SW works as fast as pins go, HW looks like expected to run at 4Mhz.
> So, 10 times faster, 1 pulse per bit ~ 0.25us.
> 0.25 \* 8 = 2 us, scheduling per byte looks not so good here.
> 
> The toolhead moved at a speed of 200 mm/s, 40mm rotational distance and 32 micro steps should have 32us between steps: \`1 / ((200 / 40) \* 200 \* 32)) ~ 31.25 us\`
> 
> Because i2c is blocking it will affect other timings occasionally.
> It feels important to me to honor TSTEP timing for TMC because they are used for interpolation/thresholds (stealth/coolstep).
> I cannot argue that those timings create interpolation position lag or that is a reason why switching stealth/spread modes is unstable.
> 
> Current implementation often blocks and waits for each byte (HW)/bit(SW) just wasting CPU time.
> Those graphs when my machine is at a standstill:
> Current implementation BME680 on host, SHT3x on mcu. \*HW i2c decreased mcu load to ~5.6%
> !\[image\](https://github.com/user-attachments/assets/b5a6bd38-5f64-41af-a97f-54ea39d27f7a)
> Current implementation with disabled i2c sensors.
> !\[image\](https://github.com/user-attachments/assets/0ba2fb53-3554-4813-a537-90d9c2c24c10)
> Such a difference in load is unexpected for me. I can guess it is calculated from time drift.
> Because the actual Awake time difference is in the expected range (less than 1%).
> 
> Patched async I2C (MCU software):
> !\[image\](https://github.com/user-attachments/assets/f111d47f-1fda-48f9-bcc3-63b7ef25739b)
> mcu hw i2c bus:
> !\[image\](https://github.com/user-attachments/assets/5f2369e0-6f77-4e6f-83bb-8b6e7f3dfc55)
> Host MCU pthread:
> !\[image\](https://github.com/user-attachments/assets/5fb4f613-818f-4780-908b-f8a0d4f80eb4)
> 
> \---
> Current master SW: \`mcu\_awake=0.006 mcu\_task\_avg=0.000013 mcu\_task\_stddev=0.000114\`
> Async I2C SW: \`mcu: mcu\_awake=0.001 mcu\_task\_avg=0.000001 mcu\_task\_stddev=0.000001\`
> 
> \---
> !\[image\](https://github.com/user-attachments/assets/71061f4a-6ac1-4990-9176-cc4daaccdf6c)
> !\[image\](https://github.com/user-attachments/assets/73e120c3-1761-41a8-b02d-03b484563871)
> 
> New I2C SW timings with default 100k.
> It looks like 6-7 us per pulse originated to a safe way of switching.
> https://github.com/Klipper3d/klipper/pull/6141#discussion\_r1201492770
> 
> The transition between bytes is a little suboptimal.
> 
> \---
> !\[image\](https://github.com/user-attachments/assets/2868f12c-8f33-4643-bc75-566e696851cd)
> With bit time correction at 100kHz.
> I was able to drive the bus around 500kHz, it looks like there is a limit on the GPIO toggle speed.
> 
> \---
> The main question is it worth it?
> I tried different approaches, but for now, this is something more or less simple.
> 
> \*Current i2c\_read/write works as before.
> 
> The high-level Idea is to buffer klippy i2c requests and execute them in the background.
> There is a new infrastructure defined around it.
> Because i2c\_read is currently used in different places, there is the possibility of defining a callback for i2c\_async.
> There is the ability to change ldc1612 and mpu9250, to use it with the nonblocking API.
> 
> Correct nonblocking HW i2c is written for stm32f0\_i2c.c
> Others I didn't touch for now, but I can also rewrite them - the event loop is the same.
> Software i2c is tricky, I tried to not overcomplicate things and still emulate the bit-banging approach in tmcuart.c
> (I unintentionally reinvented it somehow, with function overrides :D)
> 
> For now, the event loop is stored in each HW i2p implementation because it is easier to overcome specific restrictions, like:
> \- Linux HW i2s can only be made in one ioctl.
> \- AVR can be slow and such a thing will not work, so there count of jumps can be reduced.
> 
> This is not ready for merge.
> TODO:
> \- ~~Make i2c\_modify\_bits async. There is Write-Read-Modify-Write cycle here.~~ - Done
> \- Write HW for other MCUs.
> \- i2c bus is shared, there is the possibility to send 2 async requests to the same bus - it will not work
> \- If there are decisions to get rid of old synchronous code here. I have a bad understanding of time measurements for i2c bulk data and how it will cooperate with async approach.
> \- ~~Does it make sense to have io pthread on Host MCU?~~ - that one reduce jitter
> \- ~~Commit mess should be fixed (I leave it for now as a history of thoughts).~~
> 
> \---
> MCU: Octopus Pro - stm32h723
> Host: RPI 5

> <https://github.com/Klipper3d/klipper/pull/6689>
>
> As mentioned: https://github.com/Klipper3d/klipper/pull/6674#issuecomment-234466…9008
> That would be nice to handle I2C errors, instead of the current shutdown approach.
> 
> First 4 patches, actually from: #6684, #6687
> Because one simplifies things, the other one adds actual errors instead of ignoring them.
> 
> Otherwise,
> There is a refactoring part to make things more obvious, where is the dev and where is the bus.
> 
> Errors handling works, but:
> \- Some MCUs do not clearly state what happens underneath.
> \- There should be a better way to define & pass errors to Klippy. I think it would be possible to reuse static\_stings\_id for that. But I didn't find a simple way for that.
> \- When klippy inits and I2C returns an error, it is an unhandled exception, so it only appears in logs. There should be a fix actually to show it to frontends as before with shutdown msg.
> \- Missing handling for ldc1612/mpu9250 - they just ignore errors in runtime.
> \- Most sensors for now do something like:
> \`\`\`
> def \_sample():
> try:
> \<code here\>
> except Exception:
> logging.exception(...)
> self.temp = self.humidity = .0
> return self.reactor.NEVER
> \`\`\`
> So, they stop updating data, if there is no heater for them, the machine will continue running.
> 
> \---
> About the code itself:
> \- Refactoring is done for clarity, it can be dropped or moved to separate PR.
> (I still somewhat think about non-blocking i2c, it feels right to store queue/buf at bus level),
> \- \`int ret\` looks a little dirty to me, maybe is a bad approach here, I will be glad to receive any feedback.
> 
> Thanks.

~~The basic issue with PICO, is that it lacks of any error reporting for I2C.  
There is patch, but I didn’t test it yet:~~  
Fixed, reproduced and tested, you can test and leave your result here:  
[rp2040/i2c.c: Check for NACK/Start NACK by nefelim4ag · Pull Request #6692 · Klipper3d/klipper · GitHub](https://github.com/Klipper3d/klipper/pull/6692) (thanks)

If it works, It can be merged to klipper which should give a more or less clear error message in general with RP2040 and I2C.

SHT15 and SHT21 are different sensors.  
SHT15 is not supported at all, I can’t find any code for it.

In general, dupon are loose and just making them tighter fit could help with I2C stability.  
You can use tweezers, and needle nose pliers, to make metal female dupon tighter.

---

<div class="post-metadata">

**Author:** ![sith\_lord\_baku](https://avatars.discourse-cdn.com/v4/letter/s/b5e925/32.png) [@sith\_lord\_baku](https://klipper.discourse.group/u/sith_lord_baku)\
**Post date:** [September 17, 2024, 2:21pm UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/3 "2024-09-17T14:21:18Z")

</div>

I will look at those and try out the patch after work. For the sht15 while not listed as supported it did work when connected to the BTTpi for months so the family of sensors is supported I believe this is a pico issue, however I am building a ercf and will have a climate controlled cabinet - and the wire lengths would be pushing the limits for i2c sensors. I guess I could always go with PI0’s but $4 vs $24 is a budget savings when using 2-3.

Thank you for the information it’s much appreciated

---

<div class="post-metadata">

**Author:** ![nefelim4ag](https://yyz2.discourse-cdn.com/free1/user_avatar/klipper.discourse.group/nefelim4ag/32/2387_2.png) [@nefelim4ag](https://klipper.discourse.group/u/nefelim4ag)\
**Post date:** [September 17, 2024, 6:57pm UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/4 "2024-09-17T18:57:00Z")

</div>

I use SHT31 with 1-meter cable, twisted it as I can 😃  
It works.

This will really depend on the cable, sensor, and HW devices on both sides.  
You can make the signal better by replacing 10k resistors with 4.7k.  
Or by the usage of level shifters and use 5V for the sensor (if it supports it) and 3.3V for MCU.  
Both things will make the signal edges steeper.

_BTW, I think my dirty async software I2C can also help with that, but I did not have issues, and haven’t an oscilloscope to directly reproduce and test that._

P.S. I tested RP2040 patch, and updated the link to the PR above.

---

<div class="post-metadata">

**Author:** ![sith\_lord\_baku](https://avatars.discourse-cdn.com/v4/letter/s/b5e925/32.png) [@sith\_lord\_baku](https://klipper.discourse.group/u/sith_lord_baku)\
**Post date:** [September 18, 2024, 11:11pm UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/5 "2024-09-18T23:11:14Z")

</div>

Didn’t seem to help, actually made it error out more, but I am going to go back to the basics. i have a second pico and sensor, some of my solder joints look cold, so im going to try and solder the second one up right, twist the i2c cables and try again. if all else fails i have sourced a pi0w and ill use that - it should\* be able to run multple sensors- also double checked the sensors are htu2d sht21 compatible replacments for sht15’s

---

<div class="post-metadata">

**Author:** ![sith\_lord\_baku](https://avatars.discourse-cdn.com/v4/letter/s/b5e925/32.png) [@sith\_lord\_baku](https://klipper.discourse.group/u/sith_lord_baku)\
**Post date:** [September 20, 2024, 12:44am UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/6 "2024-09-20T00:44:49Z")

</div>

Not sure if it’s the patch that fixed it or the new Pico and sensor that’s doing it but it’s back up and running it appears or at least it’s been 2 hours and no errors. Though it also occurred to me the Pico is small so I just wired the sensor on back of the Pico and I’ll just use a shielded USB cable to run it

 ![IMG_20240919_204202](https://global.discourse-cdn.com/free1/uploads/klipper/original/2X/c/cc5bf7d591a0a394a47100da68721ec5affd3a8e.jpeg)

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/free1/uploads/klipper/original/1X/64419bf2aac6639e6ef5cef200dcd456b0a01ac3.png) [@system](https://klipper.discourse.group/u/system)\
**Post date:** [October 20, 2024, 10:45am UTC](https://klipper.discourse.group/t/mcu-pico-shutdown-i2c-timeout/18848/7 "2024-10-20T10:45:43Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
