Go Down

Topic: I2C oscilloscope (Read 539 times) previous topic - next topic

aapatil

Aug 09, 2018, 10:46 pm Last Edit: Aug 09, 2018, 10:56 pm by aapatil
Hi!

I hooked up an oscilloscope to the SDA and SCL lines of an Arduino Pro Mini to observe the data sent since my sensor is not behaving as expected. Can anyone explain the small fluctuations?




bos1714

Hello there!

Can you post a screen shot from your oscilloscope with some arrows to indicate what you mean by fluctuations?
Time line? Time isn't made out of lines. It is made out of circles. That is why clocks are round.

Koepel

#2
Aug 10, 2018, 12:55 am Last Edit: Aug 10, 2018, 01:07 am by Koepel
The explanation is that something is terribly wrong :smiley-eek:
It seems to be a problem with the ACK by the sensor. Perhaps your pullup resistors are too strong or the sensor gets the wrong voltage.

Please tell us everything. What kind of Pro Mini do you use (5V or 3.3V). Is there a level shifter ? How long are your wires ? Can you make a photo of your wiring ? Which sensor is it ? How is the sensor powered ? What kind of pullup resistors do you use ? Are other things connected to the I2C bus ? Was the I2C Scanner able to detect the sensor ?

aapatil

I am using the Arduino Pro Mini (3.3V 328p). There is no level shifter and I did try to minimize most of the wires. The sensor is an AK09970N hall magnetic sensor.

The I2C scanner does detect the device at 0x0C. In the image, you will see an extra resistor for if/when I decide to connect the ODINT pin for interrupts. I have attached the datasheet to see the recommended wiring in the last few pages. I followed that.

The sensor is powered through a USB where the programmer is.


Koepel

Can you measure the value of both pullup resistors for SDA and SCL with a multimeter ? I can't see the color coding in the photo :(
Can you try without those pullup resistors ?

What you have can be explained by:
  • Pullup resistors for SDA and SCL that are very low, for example 300 ohms.
  • A breadboard with bad contacts. For example the 3.3V or GND for the sensor. Can you measure the voltage of the sensor? and the GND connection to the sensor?
  • A broken sensor. When a chip is broken, it might work only half. It often does not completely stop working.
  • ... other causes

Smajdalf

I think the step on SDA signal when the device pulls down indicate a very poor GND connection. I will try to explain it but I am not sure if it will be understandable:
Sensor's GND is like 1V higher than Arduino's GND. When Arduino pulls SCL DOWN sensor supply current goes via SCL protection diode instead of GND and so the device is able to pull SDA to ~0.7V (1 diode drop over Arduino's GND/SCL level). When SCL goes HIGH the supply current must go via the device's GND pin. So the device is only able to pull SDA to 1V (it's own GND).
In other word the device pulls the SDA to its own internal GND. The GND is min("voltage on GND pin","SCL voltage + 1 diode drop").

aapatil

Both of the resistors are 3.3KOhm (a resistor I used because it was the recommended pull-up resistor). The voltage of the sensor is 3.3V (does this mean that the intern GND is fine?).

All of the connections seem fine, especially since endTransmission() returns 0. The issue is that when I read preset registers, I do not get the values that I expect to get.

Should I post my code as well?

Koepel

Did you measure the resistors with a multimeter ? Did you try without the pullup resistors ?

The pictures from the oscilloscope are scary. It could be a bad GND or shortcut or something like that.

Do you have another I2C device ? If possible a device that runs at 5V and 3.3V. If you run a I2C Scanner with a normal I2C device, you should see normal level on the oscilloscope.
If nothing else is wrong, the sensor might be broken.

aapatil

I cleaned up the signal, and so now it looks like this:


I see three bytes on the SDA line, 0x18, 0x19, and 0x21. However, my code says:
Code: [Select]
i2c.beginTransmission(0x0C);
    i2c.write(0x19);
    i2c.write(0x21);
    i2c.endTransmission();

So I would expect there to be two bytes on the SDA line, 0x19 and 0x21.

I am using the SoftI2CMaster language.

ron_sutherland

#9
Aug 15, 2018, 08:29 am Last Edit: Aug 15, 2018, 08:30 am by ron_sutherland
The first byte is the 7-bit address with a read (or write) bit (e.g. 0x18 == 0x0c << 1).

I use an R-Pi Zero on an RPUpi shield to have a tool-chain at the network edge.

Koepel

Those are normal signals for I2C. I don't understand why it was not normal in the first pictures.
Can you try the normal Arduino Wire library ? I don't know which version of the SoftI2CMaster library you use and if you use it correctly.

When you encounter a problem, get rid of as many things that can influence it and try a minimal setup to find the problem. Assume that everything can be wrong.

The Arduino Wire library can not cause a shortcut on the I2C bus, so I did not ask to see your sketch. But now that you don't use the Arduino Wire library, perhaps the SoftI2CMaster is the problem. I am also wondering what else could be going on and you have not confirmed that you have actually measured the value of the pullup resistors.

There are two or three libraries that are called SoftI2CMaster: https://github.com/Testato/SoftwareWire/wiki/Arduino-I2C-libraries.

aapatil

I understand how that works, so I would expect that when I send 0x19 (a read instruction) and then 0x21 (the register I would like to read) that would be it. However, it is sending an extra 0x18 which would be the write instruction.

I am using: https://github.com/todbot/SoftI2CMaster

I got the same extra byte when I used the I2C library.

Smajdalf

No offence meant but you do not understand how this works. beginTransmission(0x0C) command says "Start write session to device with address 0x0C". So the Arduino send START condition and (0x0C<<1 == 0x18) byte (address and write bit). By .write(x) command you add bytes you want to write to the device.
To read from common I2C look at examples in Arduino IDE, it is named something like master receiver. You need to use beginTransmission to set address where to read and than requestFrom to actually read the data.

ron_sutherland

#13
Aug 15, 2018, 10:34 am Last Edit: Aug 15, 2018, 10:36 am by ron_sutherland
hmm... let's have a look at that code

https://github.com/todbot/SoftI2CMaster/blob/f1374d853db7265453fae840d3094129760baef1/SoftI2CMaster.cpp#L107



so...

Sounds like you have a I2C device that will take commands and probably need a repeated start. It will have two transactions, the first transaction is a write and does not send a stop, the second transaction is a read and has a stop. If a stop is placed between the write and read some devices will not respond, it is known as an atomic transaction, another way to see it is that the master has locked the bus and it alone can start the next transaction.

Code: [Select]
i2c.beginTransmission(0x0C); //i2c shows a start and (addr<<1)+w byte
    i2c.write(0x21); // i2c shows a byte, e.g. an i2c slave device can use this as a command
    // do not send a stop
    uint8_t byte =i2c.requestFrom(0x0C); // i2c shows a repeated start and (addr<<1)+r byte and a byte from a slave if present
    i2c.endTransmission(); // send a stop
   
// byte should have the value from whatever the command caused
I use an R-Pi Zero on an RPUpi shield to have a tool-chain at the network edge.

aapatil

No offense taken considering how confused I am.

I don't think I understand how all the starts and stops work. I think I understand how the write function works and it looks like it would follow the image from the datasheet. However, for the read instruction, it seems to me as though there would be a stop condition before any data is sent back.

Can you please explain this to me?


Go Up