I2C does not work after save (Espruino Pico) #1554
Replies: 13 comments
-
Posted at 2021-06-12 by jgw When I use the software I2C (I2C1 in the code above replaced with i2c1 = new I2C() ), everything works fine. This proves my hardware setup is fully operational. It is of course not a real solution. When hardware I2C is available, I want to use it and not let the humble CPU consume bit-banging cycles for that... |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-12 by Robin Sat 2021.06.12 Appears to be a timing issue.
Is a full power off, power on cycle being performed? There doesn't appear to be any SDA logic high detection after uP reset.
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-12 by @MaBecker Check this module http://www.espruino.com/DS3231 |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-13 by Robin and corresponding module source http://www.espruino.com/modules/DS3231.js Thanx @MaBecker missed that tutorial option, . . . always an easier way . . . |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-14 by jgw Thanks for the tips. I went through the DS3231.js source and see nothing fundamentally different as compared to my test script. The situation remains at complete power down - power up. This puts the DS3231 in a known state. The 'init()' runs after 2 seconds, eliminating any power upt timing issues. I'm quiet experienced with I2C communications and added the usual generate-clock-until-SDA-high, followed by an I2C Stop. This puts any connected I2C device in a bus-free state. The next 'readFrom()' will/should then generate the I2C start for each transfer, does it not ? Anyhow, the thing I still do not understand is the lack of pulses on either SDA or SCL on the oscilloscope at B6 and B7. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-14 by @MaBecker Hmm, please share a link to that DS3231 you use. Got some Pico and some DS3231 and can run later a quick test. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-14 by @gfwilliams I guess it's possible you are hitting issues because B6/B7 are used for the default serial console when USB is disconnected. While I don't think that should really happen, you could try How easy would it be for you to try using different pins for the hardware I2C and see if that fixes it? |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-14 by jgw OK, I'll look into your suggestions. Will be tomorrow until I can try them though. OK |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-14 by jgw Moved UART1 away from B6/B7. Good point - I overlooked that... Then, did some further testing (full test script source below) :
Consider the attached scope waveforms : CH1 = SCL, CH2 = SDA. Top = the 'freeI2Cbus()' waveform, Middle = the same with slower timebase. No signals for the next 500ms (or more, no matter how long I wait). Looks like 'init()' does not generate any signal on SCL or SDA ! The bottom waveform is the result of using the software 'new I2C()' class : everything perfect, proving the hardware is OK.
Hardware is a DS3231 chip, not a module, with a direct connection with a 2x 2cm PCB trace and 2 3k3 pullups. DS3231 gets its power from the 3V3 output of the Pico, everything properly decoupled. Moving B6/B7 to B3/B10 is difficult since the design is already using the pins for other stuff... But if that is the only solution... All of this testing was done with the Pico connected to the IDE (over USB). So my comment about problems 'after save()' do not hold true anymore I'm afraid. Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-15 by @gfwilliams So you're saying that middle waveform (with just the small spike) is the one from running the onInit code? And you have hardware pullups on the I2C bus - if not that can be an issue since I don't think Espruino is able to use the internal pullup on STM32s, and software I2C can. I can try checking with an I2C device on B6/B7 here and see if I can reproduce it. What happens if you do:
Just a note on hardware vs software I2C though - when using hardware, the software kicks off the I2C transmission, but then just busy-waits until it's finished - so you're not really saving many CPU cycles by going hardware vs software - it just means the waveform is a bit more regular (and it can be easier to hit 400kHz). |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-15 by jgw The middle waveform is identical to the first, but with a slower timebase. This to illustrate the lack of activity on the bus for a 'long' time. Delaying the I2C1.setup() solves the issue. On several power down/up cycles I only had 1 failure. So you can consider this as solved - it works, but does not feel very robust though... As for the software I2C : it would of course be nice to extend the I2Cx objects with a 'transfer complete' event. The background operation of the hardware I2C controller could then be started and generate an interrupt when ready. JavaScript can then continue to do other work until I2Cx.on("complete",... ) triggers. But of course you already knew that... Thank you for the support. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-16 by @gfwilliams
Ok, thanks - that's interesting.... So just to be sure I'm understanding from the traces you've put up:
How did you save your code - with Either way something is odd with Espruino - I wonder if it's trying to restore pin state, and it's doing so after
Yes, absolutely. The vast majority of I2C transactions do tend to be just a few bytes though, so given the execution speed of Espruino you're probably not saving too much time (in most cases - I2C OLED is the one I know is a pain). A quick addition that would have a noticable impact in most cases would actually be just adding a From my point of view adding an async SPI function is probably more of a priority, although it's not to say I2C won't get added as well. Once there's more of a framework in place for it, adding to different peripherals (ADC as well) wouldn't be such a big deal. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2021-06-16 by jgw Your understanding of the waveforms is correct. I used save() : when I'm done debugging, I (again) download the code from the IDE and immediately issue a 'save()'. I assume that puts the Espruino JavaScript engine in a 'virgin' state without too much debug history left behind. I agree with your comment that there may not be much time gained implementing an I2C event (except for large data chunks such as displays). I find it always a challenge to take into account the lower speed of a small CPU compared to the desktop beasts we use to develop our hardware/firmware :). A combined 'writeTo - readFrom' might be an easier cycle-saver : an I2C read transaction almost always starts with write-register-address - but that's only something to add to the whish-list...
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Posted at 2021-06-12 by jgw
Consider the I2Ctest script below. After a 'send to Espruino' and running 'onInit()' everything works fine. After a 'save()', I2C fails.
My hardware is OK, I have 2 pullups on B6 and B7 and a single DS3231 on the bus. An oscilloscope does not show any activity on either SDA or SCL, so how can a timeout is detected...
The behaviour is the same after power off/power on (with the console.logs removed). What am I doing wrong ?
Beta Was this translation helpful? Give feedback.
All reactions