tedyapo / arduino-MLX90393

Arduino library for MLX90393 magnetometer sensor
MIT License
49 stars 26 forks source link

CJMCU-90393 noise problem & other issues #42

Closed SarwarN88 closed 5 years ago

SarwarN88 commented 5 years ago

Hi I been testing this new board for quite a while. I been using different code to communicate with arduino. I found your library to be much better as it has all the functions needed for setting-up the MLX90393 chip like Hull-config, oversampling, digital filtering..etc. The concerns I have here are noise level in the raw data and some other issues.

  1. I don't know how much of the 16bit ADC is usable when filtering all the noise from the board using digital filtering? and does that reduce resolution? In the data sheet no matter what OSR (over sampling) you use the noise level stay the same like in 10ms (conversion time) = 10 stdev and that if OSR = 1,2, or 3. they are all the same with little or no deference.

  2. When sitting DigitalFiltering = more than 0, OCR need to be 0 or you will not get any reading from the sensor. Can you explain why this happen? In the data sheet it says DIG, FILT and OCR related to each other. if HALL-CONF = 0x0C then DIG, FILT of 0 and 1 with OCR of 0 and 1 is not allowed but other are allowed. So how come when I increase DIG, FILT to 2 and OCR to 2 or 3 I still not get any reading?

  3. In the other code that I have downloaded from here ( http://arduinolearning.com/code/arduino-mlx90393-magnetic-field-sensor-example.php) the raw data goes from -2^15 to +2^15. Do you know how I can change your code reading from ut/LSB to the raw bits? I need to compare the noise level of your code vs the other one. As I feel your code somehow generate more noise while filtering setting is the same on both side.

  4. I am trying to use low-pass filtering using 10uf capacitor with 1kohm and 330 ohm resister using this setup (http://forum.arduino.cc/index.php?topic=527478.30) to reduce environment noise. Do you think it will be better to do hardware filtering or software filtering using the library code will also give the same results?

  5. The CJMCU-90393 board that I have has 2 pins of 3.3V one is VDD and the other one is VDD-IO. Do I have to connect both pins to 3.3V in order to supply requirement power? In the data sheet it says VDD is analog supply and the VDD-IO is digital supply. I do have reading when one 3.3V is connected but the board needs 3.6V power supply.

  6. If I want to connect multiple boards to the arduino how I can communicate with each one of them? In the data sheet is 0x0C, 0x0D, 0x0E... but I don't know how to use them with your library?

  7. Do you think a magnetic sensor like A1324LUA-T with external 16bits ADC like ADS1115 give more precision and low noise than the MLX90393? With this level of noise that I have, I think I need to map the raw data to 2^10 to get a stable reading. Is that mean only 10bits is usable?

  8. I think magnetic shape and size has effect in the way the sensor returning values in x,y and z axis when spinning the Nd magnet? correct me if I am wrong. I used a rectangular shape Nd magnet and when I spin it the values I get are different when I use a square magnet in the same level and distance.
    Finally, thanks for all your hard working and I hope I get some answers soon. Sarwar

tedyapo commented 5 years ago

I'll start out by saying that I have not done any thorough studies of the noise in the MLX90393 readings, but I have not noticed any obvious problems.

I don't know how much of the 16bit ADC is usable when filtering all the noise from the board using digital filtering? and does that reduce resolution? In the data sheet no matter what OSR (over sampling) you use the noise level stay the same like in 10ms (conversion time) = 10 stdev and that if OSR = 1,2, or 3. they are all the same with little or no deference.

I don't know, either. This sounds like a question for Melexis. Try contacting one of their application engineers. How do you know the noise (some or all) that you are seeing is not in the magnetic field itself? Maybe you are testing in an AC field created by motors, fans, transformers, etc? Have you plotted the results and looked for periodic signals, like at your power-line frequency?

When sitting DigitalFiltering = more than 0, OCR need to be 0 or you will not get any reading from the sensor. Can you explain why this happen? In the data sheet it says DIG, FILT and OCR related to each other. if HALL-CONF = 0x0C then DIG, FILT of 0 and 1 with OCR of 0 and 1 is not allowed but other are allowed. So how come when I increase DIG, FILT to 2 and OCR to 2 or 3 I still not get any reading?

Again, could be an issue with the part or datasheet. The driver doesn't do anything special for the prohibited combinations - the values are just written to the registers as usual. It's up to the caller to avoid setting invalid state.

In the other code that I have downloaded from here ( http://arduinolearning.com/code/arduino-mlx90393-magnetic-field-sensor-example.php) the raw data goes from -2^15 to +2^15. Do you know how I can change your code reading from ut/LSB to the raw bits? I need to compare the noise level of your code vs the other one. As I feel your code somehow generate more noise while filtering setting is the same on both side.

Look inside the function readData(). It calls startMeasurement(), waits for DRDY or a specified time, then calls readMeasurement(). readMeasurement() returns the raw data you want. Create your own function which does these same things and returns the raw txyz values.

I am trying to use low-pass filtering using 10uf capacitor with 1kohm and 330 ohm resister using this setup ( http://forum.arduino.cc/index.php?topic=527478.30) to reduce environment noise. Do you think it will be better to do hardware filtering or software filtering using the library code will also give the same results?

What exactly are you trying to filter with this low-pass? The forum you linked shows this filtering an analog signal line, which won't work here. Do you mean to filter the supply? That's probably a good idea - just make sure the resistors can supply the necessary current, and maybe use a large and small capacitor in parallel (in different size packages).

The CJMCU-90393 board that I have has 2 pins of 3.3V one is VDD and the other one is VDD-IO. Do I have to connect both pins to 3.3V in order to supply requirement power? In the data sheet it says VDD is analog supply and the VDD-IO is digital supply. I do have reading when one 3.3V is connected but the board needs 3.6V power supply.

Both pins need to be connected. Decoupling the analog and digital supplies might reduce noise. Try filtering the analog supply to isolate it from the digital.

If I want to connect multiple boards to the arduino how I can communicate with each one of them? In the data sheet is 0x0C, 0x0D, 0x0E... but I don't know how to use them with your library?

uint8_t begin(uint8_t A1 = 0, uint8_t A0 = 0, int DRDY_pin = -1, TwoWire &wirePort = Wire);

A0 and A1 are the address bits as specified in the datasheet. Set them as required to select the desired I2C address.

Do you think a magnetic sensor like A1324LUA-T with external 16bits ADC like ADS1115 give more precision and low noise than the MLX90393? With this level of noise that I have, I think I need to map the raw data to 2^10 to get a stable reading. Is that mean only 10bits is usable?

I don't have any experience with the A1234LUA-T. Again, double check that you're not actually trying to measure a noisy field. Also, what level of field are you measuring? Tens of uT? Hundreds? In the mT range?

I think magnetic shape and size has effect in the way the sensor returning values in x,y and z axis when spinning the Nd magnet? correct me if I am wrong. I used a rectangular shape Nd magnet and when I spin it the values I get are different when I use a square magnet in the same level and distance. Finally, thanks for all your hard working and I hope I get some answers soon.

I'm sure two different magnets will give different readings, especially if they are different shapes or sizes or strengths, since they probably produce very different fields.

SarwarN88 commented 5 years ago

Thanks for your quick respond

That's probably a good idea - just make sure the resistors can supply the necessary current, and maybe use a large and small capacitor in parallel (in different size packages).

What is the necessary current to run the board? It doesn't specified it in the data sheet that I have. It only shows 10mA current for the conversion during reading of xyzt

Try filtering the analog supply to isolate it from the digital.

So I don't need something like level shifter to produce two different voltage reference of 3.3V for analog and digital power?

A0 and A1 are the address bits as specified in the datasheet. Set them as required to select the desired I2C address.

In your code the A0 and A1 = 0. What value I need to put in order to use two boards? In your example code you just called MLX9039 mlx; and read data mlx.readData(data);. so how I can call the second board to take reading from? I am not connecting the boards in parallel using A0 A1 pins.

Also, what level of field are you measuring? Tens of uT? Hundreds? In the mT range?

No idea about the unit of measured filed. It goes from somewhere -500 to +3000 when rotating in clockwise and anticlockwise. Though the last two digits is noisy and unstable. I am using the board for a joystick project so my knowledge is limited. I started learned arduino for about 3 months. Thanks again

tedyapo commented 5 years ago

What is the necessary current to run the board? It doesn't specified it in the data sheet that I have. It only shows 10mA current for the conversion during reading of xyzt

I don't know what's on your board. It would be the sum of the current consumed by the sensor and anything else on there.

So I don't need something like level shifter to produce two different voltage reference of 3.3V for analog and digital power?

If you MLX90393 is running at s different supply voltage than whatever you are using to control it, you may need a level shifter to translate the signals. You use a level shifter to translate signal voltages, but not supply voltages.

In your code the A0 and A1 = 0. What value I need to put in order to use two boards? In your example code you just called MLX9039 mlx; and read data mlx.readData(data);. so how I can call the second board to take reading from? I am not connecting the boards in parallel using A0 A1 pins.

How are you connecting the boards to your microcontroller?

If they are on the same I2C bus, you use the A0 and A1 address bits to select which MLX90393 to talk to. See the datasheet section 8.4: I2C_ADDR[6:0] = {EE_I2C_ADDR[4:0],A1,A0} where you have selected A1 and A0 by tying the two lines to either Vdd or Vss.

If the boards are on separate I2C busses, select the appropriate interface for the wirePort parameter in the begin() call: uint8_t begin(uint8_t A1 = 0, uint8_t A0 = 0, int DRDY_pin = -1, TwoWire &wirePort = Wire);

SarwarN88 commented 5 years ago

How are you connecting the boards to your microcontroller? I want to connect both of the board's SCL and SDA to my arduino Leonardo SCL and SDA. So that mean same I2C bus? you use the A0 and A1 address bits to select which MLX90393 to talk to I looked at the data sheet but I am more confused now. It say you can connect up to 16 sensors on the bus, 4 ordering code and 4 hard-wired. The EE_I2C_ADDR[4:0] is = 0x03h by default. Can you explain in a simple way how I can use A0 and A1 address and how to call each board in a simple example? Thanks again

tedyapo commented 5 years ago

Devices connected to the same pair of SCL/SDA lines are on the same I2C bus.

I do not see where in the data sheet it says you can have 16 sensors on the same bus.

This library supports 4 sensors on the same bus. Here is an example:

MLX90393 mlx0, mlx1, mlx2, mlx3;
// mlx0 has the A1 pin tied to GND, the A0 pin tied to GND
mlx0.begin(0, 0);
// mlx1 has the A1 pin tied to GND, the A0 pin tied to VDD
mlx1.begin(0, 1);
// mlx2 has the A1 pin tied to VDD, the A0 pin tied to GND
mlx2.begin(1, 0);
// mlx3 has the A1 pin tied to VDD, the A0 pin tied to VDD
mlx3.begin(1, 1);
SarwarN88 commented 5 years ago

Thank for all your time and efforts to answer all of my beginner questions. For the 16 sensors on the bus that what this data sheet saying on page 21 ( https://www.melexis.com/en/documents/documentation/datasheets/datasheet-mlx90393). Its a 2017 version. Correct me if I am wrong as some of this staff written is not for a beginner like me. Thanks again;)

tedyapo commented 5 years ago

I'm glad to help. The datasheet can be confusing in places.

The I2C address is formed from a "fixed" part hard-coded inside the chip, and the two address pins you can configure by connecting to Vdd or GND as needed. When the part first came out, the fixed part of the address was always the same, so you could have up to 4 devices on the same I2C bus. This is supported by the library.

Now, Melexis has started selling versions of the parts with different hard-coded parts of the address. They sell four different versions, each with its own hard-coded value. You can still use the A1/A0 pins, so this allows you to use up to 16 devices on an I2C bus.

This library does not currently support versions of the chip with different hard-coded address parts. The change to allow it is not difficult, but would break existing code, so I have not made it. You can easily modify the library to support this if you need it. See I2C_BASE_ADDR in the code.