https://toitlang.org/ logo
State bug with I2C library
# help
z
I'm reading from an I2C sensor chip. when I use Toit, I am not getting the results I expect per the datasheet. When I use Arduino's
Wire
library, I get exactly what I expect. Here's the code comparison between the two of them. See the attachment for the box highlighted in Red - that's the Toit script causing the chip to misbehave. With toit, I always get exactly whatever the first value I read from the chip. With Arduino I can read different registers without issue. I am starting to suspect it may come down to the default state of GPIO pins, one system having it high and the other having it low, or something. I have a logic analyzer, an ESP32 dev kit WROOM-32D https://cdn.discordapp.com/attachments/1324156979479838791/1324156981329788979/image.png?ex=677720c9&is=6775cf49&hm=a7be63e7e325383fd8c54919d587a3a90527a9df3957fadcd14d2c48cf3a5d15&
Toit code:
Copy code
import gpio
import i2c

bus := i2c.Bus
  --sda=gpio.Pin 16
  --scl=gpio.Pin 26
  --frequency=80_000

device := bus.device 0x57

a0 := gpio.Pin 14 --output
motion := gpio.Pin 27 --input
// clock := gpio.Pin 26 --output
// iodev := gpio.Pin 16 --output
shutdown := gpio.Pin 17 --output
nrst := gpio.Pin 22 --output
vddio := gpio.Pin 21 --output


//For TWI:
// 1. Apply power. Refer timing diagram on power up
// sequence below.
// 2. Set SHTDWN and IO_SELECT pin low.
// 3. Set A0 and A1 according to the desired TWI slave
// address (from TWI slave address table in datasheet).
// 4. Drive NRST pin low then high. TWI slave address will
// only be valid and according to the address set in step
// 3 after a NRST toggle is applied.
// 5. Read Product ID (PID) to ensure sensor is powered up
// and communicating properly with host.
// 6. Write 0xE4 to address 0x60
// 7. Write 0xC9 to address 0x61

main:
  shutdown.set 0
  a0.set 1
  vddio.set 1

  // Drive NRST low, then high 
  nrst.set 0 // Do this last to turn on the chip?
  sleep --ms=80
  nrst.set 1

  sleep --ms=10

  // 6. Write 0xE4 to address 0x60
  // 7. Write 0xC9 to address 0x61
  // Read Product ID (PID) to ensure sensor is powered up
  // and communicating properly with host.

  device.write-reg 0x60 #[0xE4]
  device.write-reg 0x61 #[0xC9]

  value2 := device.read-reg 0 1
  print value2
  sleep --ms=50
 
  value := device.read-reg 0x3f 1
  print value
  sleep --ms=10

  sleep --ms=2000
  print "Done"
  device.close
f
Do you have the datasheet of the sensor?
see pg 7 "Notes on power up sequence"
The I2c is the "TWI" Two Wire Interface on the datasheet
f
I will have a look tomorrow. We did do an esp-idf upgrade recently, but if I2C works normally for my sensors it will be hard to debug. I might write a bit-banging library then, but that will take more time.
z
great! happy new year, enjoy your sleep 🙂
Happy new year to you too!
I have started looking into this. I started with one of my i2c devices and that one still works. At least it's not a general I2C issue. (Although that would have made it easier to debug...)
z
ok, thank you for confirming
further testing has be thinking this may be an issue with the way I am powering the sensor or the way I am pulling up/pulling down other control lines
f
Your logic analyzer seems to indicate that Arduino and Toit have the same "messages".
the start, stop, acks, ... all look the same.
z
I have been able to make the error state occur on both Arduino and Toit. And yes, I can also see that both have the same message
f
One thing I noticed: the sensor wants 100ms of "reset wait time after stable supply voltage".
That sleep seems to be missing.
z
I'll try adding it in. The datasheet is not super clear on whether they mean the
VDDIO
IO supply voltage or the
VDDA
analog supply voltage
f
The power-up diagram has t_vrt_nrst after vddio went up.
Either way: it can't hurt.
off-topic (out of curiosity): how do you communicate with the chip? 1.8v or 2.8v? how do you level-shift?
z
there's some sense here - I think the default state of GPIO output pins is different between arduino and toit. is that right? I feel like I remember one being GPIO default == off. I'm using one of the bidirectional logic shift breakout boards https://www.amazon.com/dp/B07LG646VS
f
In Toit: by default output pins are set to 0.
z
uses a MOSFET and pull up resistors so that either side can pull logic low
f
If you just allocate them (without
--output
) they are floating.
z
oh and it's at 1.8V for simplicity.
i think in my case Hi-Z implies it will be pulled up then
f
One thing you could try: When allocating the GPIO pins you can use
--value=...
to set the start value.
a0
is probably the most likely candidate.
It must be 1 at start.
I don't see any timing constraints on a0, but can't hurt to be set it directly to 1.
(alternatively, put a sleep before the
vddio.set 1
)
Actually: same applies for the nrst GPIO.
Probably a good idea to set it to 1 at allocation.