[SOLVED] AS5600 magnetic rotary position sensors and Arduino Nano board communication issue

Hello.

I need to measure two angles and I’m trying to do that with two AS5600 magnetic rotary position sensors connected to an Arduino Nano board.

Each of the sensors works fine via I2C when connected alone to the board but they can’t be both connected because they have the same I2C address and the address can’t be changed on this sensor model.

A good replacement would be the AS5600L magnetic rotary position sensor: it appears to be as good as the AS5600, has a different I2C address than the AS5600 (it could be connected alongside a AS5600 with no address conflict) and its I2C address can be changed (two AS5600Ls could be connected instead with no address conflict).

The problem is I can’t find the sensor and its adapter at a convenient price.

I’d rather not to jump to different sensors for the moment as the AS5600 appears to work fine and exploring other sensors would mean investing more time and effort, so for now I’m sticking to a two AS5600s scenario.

Using a multiplexer isn’t probably feasable: I need to keep the system as small and lightweight as possible and, as far as I understood, a multiplexer is at least as big as an Arduino Nano board.

The AS5600 has an analog/PWM output other than I2C, so it could be possible to use one sensor via I2C and the other sensor via analog or PWM.

Since I need to detect angles with a resolution of at least half a degree, I need a sensor resolution of at least 10 bits (0 to 1023).

As far as I understood, a PWM signal has a resolution of 8 bits (0 to 255), clearly not enough.

I’ve read on the Internet it could be possible to increase the PWM resolution but the solutions explained look very complicated and untested.

The AS5600’s DAC has a resolution of 12 bits (0 to 4095) while the Arduino Nano’s ADC has a resolution of 10 bits (0 to 1023) it should be fine to connect sensor and board this way.

So I connected the sensor’s pin 3 (OUT) to the board’s pin A0 while the sensor’s output is set to analog.

Here’s a very basic sketch (a very short version of the sketch I’m using) which I used to test the system:

#include <AS5600.h>

AS5600 sensor;

void setup() {
  sensor.begin(4);
  sensor.setDirection(AS5600_CLOCK_WISE);
  Serial.begin(115200);
}

void loop() {
  Serial.println(analogRead(A0));
  delay(1000);
}

Since the board’s ADC resolution, I would expect all the range values (0 to 1023) while I rotate the magnet through all 360 degrees.

Instead, the values change by few units.

My guess is there’s some kind of mismatch between sensor’s DAC and board’s ADC since they have different resolutions but I couldn’t find an answer.

Is there any other way to make the sensors operate via I2C with the same address that I didn’t considered?

Is it possible to safely increase the PWM resolution to 10 bits?

Why the results via analog signal aren’t correct?

Any help would be very appreciated.

Thank you very much.

[sterretje edit]
Fixed code tags
[/edit end]

I've fixed your code tags. For a block of code, use ``` (three backticks) before and after the code; they need to be on their own line.


Have you considered a bitbanged I2C (soft I2C) for your second sensor?

You have probably only seen the tca9548 8-channel model. This tca9546 4-channel model is somewhat smaller:

According to the AD5600 datasheet, it is 12 bits.

If it were possible to increase the PWM resolution, I'm sure it would be mentioned in the datasheet. It does mention that a choice of several PWM frequencies can be selected, but the resolution is always 12 bits.

It is always 12 bits as far as I can see. You have to program the AS6500 to get the PWM signal because it defaults to analog output. Have you done this, or attempted to do it?

I don't know, it should work. Post your schematic and some bright, clear photos.

Did you check the AS5600's output with a voltmeter?

1 Like

Thank you for your reply!

Just to make sure I understood correctly, with “bitbanged/soft I2C” you mean choosing two GPIO pins on the board, make them the SDA and SCL lines, and simulate a signalling transaction (send the start bit, send the slave address, send the read/write bit, wait for/send the acknowledge bit, send/receive the data byte, expect/send the acknowledge bit, send the stop bit) between sensor and board via the sketch and/or libraries?

If that is the case, would you suggest a good library for the task?
I found “SoftI2C” library by Yasir Shahzad which appears to include all the required functions to emulate an I2C transaction...

Thank you for your reply!

The fact is I don’t have room to add any more hardware, no matter how compact it is.

I never had to use it so have no experience with it.

I suggest that you try it.

Thank you for your reply!

I haven’t tried yet. Now I’m investigating the issue and I’ll include this test as well if the issue still lingers.

I’ve attached two pictures of the system.

As you can see, the system is made by the board, the sensor (in an aluminium case I made for my tests, paired with a “lid” which can rotate and where the magnet is embedded), a button used to set the sensor’s zero position and the conncections.

Any idea on why the sketch doesn’t work as expected?

I’m sorry but I don’t have a background in electronics and, to be honest, the concept of PWM isn’t completely clear to me.

I read the intro about PWM on the Arduino website but it doesn’t explain much.

I assumed there were two PWM resolutions (sensor’s and board’s) which had to match but maybe it’s not the case...

I did a test using the same previous sketch (the one used for analog signaling) and adding a line which makes the sensor’s output a PWM signal but the result is quite the same as the one where an analog output was used.

Should I treat the receiving pin as digital? What am I missing? Would you mind sending me a very basic sketch for handling PWM signalling?


This is exactly what I’m on: learning how I2C works and emulating a transaction. :slight_smile:

No. PWM is not like UART communications where both sender and receiver must use the same baud rate.

PWM is much simpler. It is simply a series of pulses. The frequency is fixed but the duty cycle changes. To read the PWM signal, the receiving Arduino simply needs to measure the length of the pulses. Knowing the frequency and length of pulses, the duty cycle can be calculated.

Pulse lengths can be measured using the pulseIn() function. However, there is a limit to how small the pulses can be and how accurately the Arduino can do measure them. On most Arduino I think the limit is 4us.

We need a schematic also. We cannot see which pins are used on the "Nano", and it does not look like any model of Nano I am familiar with. We cannot see which wires are connected to which pins of the sensor.

We cannot see the code which contains the line you said changes the sensor to PWM mode.

If your code is still using analogRead, it won't be able to measure the duty cycle of a PWM signal (unless you include a low-pass filter circuit, which you will not have room for, I think).

The problem is I still don’t know how PWM works in practice. Seeing a thorough example sketch would help me a lot. Could you refer me to a good online tutorial to learn how PWM practically works? And, above all, would I be able to get the information from the sensor in the original resolution (12 bits)?

PWM is a very simple. It's a digital signal which means that it is always either HIGH or LOW, for example, 5V or 0V. It has a fixed frequency/period, which can be anything you want, but it remains at that frequency. What changes, allowing a value to be encoded into the signal, is the "duty cycle". All the duty cycle is, is the percentage of time that the signal is HIGH within each period. At 50% duty cycle, it is a perfect square wave. At 100%, the signal is HIGH at all times. At 0% duty cycle, it is LOW at all times.


There's a choice of frequencies. The lowest is 115Hz. That's a period of about 8700us. But only duty cycles between about 3% and 97% are used to represent the sensor angle, so the duty cycle varies from 260us to 8430us. 12 bits of precision would mean around 4000 values inside that range, each value being only about 2us more or less than neighbouring values.

So most Arduino won't be able to achieve 12 bits using pulseIn(). Maybe 11 bits. However, by using the Input Capture feature of the AVR chip, I think the full 12 bits could be achieved.

Having seen pictures of your chosen hardware now, this seems to be a problem partly of your own making. That Nano board with the built-in OLED is significantly larger than a normal Nano, and Pro Mini and Pro Micro Arduino are smaller still. Using those would make room for that small i2c multiplexer I suggested. Then you could get the 12 bit readings in a much simpler way.


I think you could keep your current hardware and use I2C for both AS5600 and still fit in a hardware solution using little logic and some soldering skills.

It looks like there is room for a small daughter board. On it mount a decoderand route the SCL signal through it. Select which AS5600 sees the SCL with a separate digital output.

Image for example only, not to scale.

YMMV

Hello everyone! In the end I resorted to implement a bit-banged I2C solution with the library BitBang_I2C. The system works well so I made both sensors communicate via bit-banged I2C, so I have free choice on the pins I use.
The problem is solved.
Thank you very much for you advice!

1 Like