rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
as5600.h File Reference

The ams OSRAM AS5600: a 12-bit magnetic rotary position sensor on I2C (Inter-Integrated Circuit). More...

#include <stdbool.h>
#include <stdint.h>
#include "sense_bus.h"

Go to the source code of this file.

Data Structures

struct  as5600_t

Macros

#define AS5600_ADDR   0x36u
#define AS5600_REG_STATUS   0x0Bu
#define AS5600_REG_RAW_ANGLE   0x0Cu
#define AS5600_REG_ANGLE   0x0Eu
#define AS5600_REG_AGC   0x1Au
#define AS5600_REG_MAGNITUDE   0x1Bu
#define AS5600_STATUS_MH   0x08u
#define AS5600_STATUS_ML   0x10u
#define AS5600_STATUS_MD   0x20u
#define AS5600_STATUS_MASK   (AS5600_STATUS_MH | AS5600_STATUS_ML | AS5600_STATUS_MD)
 The bits STATUS defines; the other five are not read.
#define AS5600_COUNTS   4096u
 Counts in one turn: 12 bits.
#define AS5600_CDEG_TURN   36000
 Hundredths of a degree in one turn.

Functions

uint16_t as5600_u12 (const uint8_t *b)
 A 12-bit register pair, most significant byte first: RAW ANGLE, ANGLE or MAGNITUDE.
bool as5600_status_possible (uint8_t status)
 Whether status is one an AS5600 can give: not ML and MH together.
bool as5600_md (uint8_t status)
 The magnet bits of status.
bool as5600_ml (uint8_t status)
 Read the ML bit of a STATUS value.
bool as5600_mh (uint8_t status)
 Read the MH bit of a STATUS value.
int16_t as5600_delta (uint16_t a, uint16_t b)
 a minus b on the circle, -2048 to 2047 counts: the shortest way from b to a.
int32_t as5600_cdeg (int32_t counts)
 counts in hundredths of a degree, rounded to the nearest, halves away from zero.
void as5600_init (as5600_t *d, sense_bus_t *bus)
 A part on bus at AS5600_ADDR, not yet probed.
bool as5600_step (as5600_t *d, uint32_t now_ms)
 Every tick: probes the part when it is due – at the first call, and SENSE_RETRY_MS after it was found absent, wrong or offline.
sense_state_t as5600_state (const as5600_t *d)
 The part's state as of the last probe.
sense_err_t as5600_read_status (as5600_t *d, uint8_t *status)
 STATUS: 1 byte from 0x0B.
sense_err_t as5600_read_raw (as5600_t *d, uint16_t *raw)
 RAW ANGLE: 2 bytes from 0x0C, 0 to 4095; the same rule.
sense_err_t as5600_read_agc (as5600_t *d, uint8_t *agc)
 AGC: 1 byte from 0x1A; the same rule.
sense_err_t as5600_read_mag (as5600_t *d, uint16_t *magnitude)
 MAGNITUDE: 2 bytes from 0x1B, 0 to 4095; the same rule.
sense_err_t as5600_read_angle (as5600_t *d, uint8_t *status, uint16_t *raw)
 STATUS, then RAW ANGLE: two transactions.
sense_err_t as5600_read_magnitude (as5600_t *d, uint8_t *agc, uint16_t *magnitude)
 AGC, then MAGNITUDE: two transactions; the same rule.

Detailed Description

The ams OSRAM AS5600: a 12-bit magnetic rotary position sensor on I2C (Inter-Integrated Circuit).

The register codec and a driver that talks to one part through sense_bus.h.

Written from the datasheet, ams AS5600 DS000365 v1-06. The part sits at the fixed address 0x36 and sends the most significant byte first. A register pointer write followed by a repeated START reads one register or, with the pointer incrementing, the next ones.

Registers used:

0x0B STATUS bit 5 MD (magnet detected), bit 4 ML (magnet too weak), bit 3 MH (magnet too strong); bits 7, 6, 2, 1 and 0 are blank in the register map and are masked off 0x0C RAW ANGLE bits 11-0 in 0x0C bits 3-0 and 0x0D: the angle before the zero position, the maximum angle and the filters 0x0E ANGLE the same 12 bits after them; equal to RAW ANGLE while ZPOS and MPOS are not burned 0x1A AGC automatic gain control, 0 to 255 at 5V and 0 to 128 at 3.3V; a magnet at the right distance reads near the middle of the range 0x1B MAGNITUDE bits 11-0 in 0x1B bits 3-0 and 0x1C: the CORDIC magnitude, a measure of the field

One count is 360 / 4096 = 0.0879 degrees. The count wraps from 4095 to 0; differences between two angles are taken on the circle (as5600_delta()).

Reads. Each register is read in a transaction of its own: the register address, a repeated START, then the register's bytes. The datasheet (ams AS5600 DS000365, I2C section, "Automatic Increment of the Address Pointer for ANGLE, RAW ANGLE and MAGNITUDE Registers") says: "These are special registers which suppress the automatic increment of the address pointer on reads, so a re-read of these registers requires no I2C write command to reload the address pointer. This special treatment of the pointer is effective only if the address pointer is set to the high byte of the register." Elsewhere it says the pointer "is incremented after each byte is transferred, except for certain read transactions to special registers". A read that runs from STATUS (0x0B) into RAW ANGLE, or from AGC (0x1A) into MAGNITUDE, arrives at a special register by the increment, and the code does not rely on what the part does then:

STATUS 0x0B 1 byte RAW ANGLE 0x0C 2 bytes, high byte first AGC 0x1A 1 byte MAGNITUDE 0x1B 2 bytes, high byte first

Bus time at 400kHz, 9 clocks a byte, the address byte written, the register byte and the address byte read, and 3 clocks for START, repeated START and STOP: 39 clocks (97.5us) for a 1-byte read, 48 clocks (120us) for a 2-byte read, without the controller's own time between transactions, which is not measured. as5600_read_angle() is 217.5us, as5600_read_magnitude() 217.5us.

The magnet bits. The datasheet's STATUS table (Figure 23) gives the state when each bit is high: MD (0x0B bit 5) "Magnet was detected", ML (bit 4) "AGC maximum gain overflow, magnet too weak", MH (bit 3) "AGC minimum gain overflow, magnet too strong". Under "Magnet Detection" it says: "the AS5600 indicates the absence of the magnet. If the measured magnet field strength goes below the minimum specified level (Bz_ERROR), the output is driven low, without regard to which output mode has been selected (analog or PWM) and the MD bit in the STATUS register is 0." Bz_ERROR is 8 mT at most. So with MD clear RAW ANGLE is not a position and is not used as one (as5600_md()). For ML and MH the datasheet states no effect on the angle or the output: the gain control has reached the end of its range, and the noise figures (0.015 and 0.043 degrees RMS) are specified for a field of 30 to 90 mT only. An angle read with MD set and ML or MH set is used, and its noise is not specified.

Identity. The part has no identity register, and the five blank STATUS bits are no identity: the register map's note says "Blank fields may contain factory settings", so what they read is not guaranteed. A probe reads STATUS and takes any answer as the part, with one exception: ML and MH both set say the gain is at its maximum and its minimum at once, which no AS5600 reports and a device answering 0xFF does (as5600_status_possible()); that answer is not used (SENSE_PART_WRONG_ID). The datasheet does not state the exception; it follows from the two bits' meanings. An AS5600L answers at 0x40 by default and is not addressed here.

Pure C, no SDK (software development kit): host-tested in test_as5600.

SPDX-License-Identifier: MIT

Function Documentation

◆ as5600_cdeg()

int32_t as5600_cdeg ( int32_t counts)

counts in hundredths of a degree, rounded to the nearest, halves away from zero.

Any int32_t is accepted. Above |counts| 244,335,917 the result saturates at +-2,147,483,647.

Parameters
countsAngle in counts; 4096 counts make a turn.
Returns
The angle in hundredths of a degree.

◆ as5600_delta()

int16_t as5600_delta ( uint16_t a,
uint16_t b )

a minus b on the circle, -2048 to 2047 counts: the shortest way from b to a.

Both are taken modulo 4096.

Parameters
aAn angle, in counts.
bAn angle, in counts.
Returns
a - b in counts, -2048 to 2047.

◆ as5600_init()

void as5600_init ( as5600_t * d,
sense_bus_t * bus )

A part on bus at AS5600_ADDR, not yet probed.

Parameters
dThe driver.
busThe sensor bus the part sits on.

◆ as5600_md()

bool as5600_md ( uint8_t status)

The magnet bits of status.

RAW ANGLE is a position only with MD.

Parameters
statusThe STATUS byte.
Returns
true when MD (magnet detected) is set.

◆ as5600_mh()

bool as5600_mh ( uint8_t status)

Read the MH bit of a STATUS value.

Parameters
statusThe STATUS byte.
Returns
true when MH (magnet too strong) is set.

◆ as5600_ml()

bool as5600_ml ( uint8_t status)

Read the ML bit of a STATUS value.

Parameters
statusThe STATUS byte.
Returns
true when ML (magnet too weak) is set.

◆ as5600_read_agc()

sense_err_t as5600_read_agc ( as5600_t * d,
uint8_t * agc )

AGC: 1 byte from 0x1A; the same rule.

Parameters
dThe driver.
agcReceives the AGC byte.
Returns
SENSE_OK, or the bus error.

◆ as5600_read_angle()

sense_err_t as5600_read_angle ( as5600_t * d,
uint8_t * status,
uint16_t * raw )

STATUS, then RAW ANGLE: two transactions.

On anything but SENSE_OK both are left as they were.

Parameters
dThe driver.
statusReceives the STATUS byte.
rawReceives the angle, 0 to 4095.
Returns
SENSE_OK, or the bus error.

◆ as5600_read_mag()

sense_err_t as5600_read_mag ( as5600_t * d,
uint16_t * magnitude )

MAGNITUDE: 2 bytes from 0x1B, 0 to 4095; the same rule.

Parameters
dThe driver.
magnitudeReceives the magnitude, 0 to 4095.
Returns
SENSE_OK, or the bus error.

◆ as5600_read_magnitude()

sense_err_t as5600_read_magnitude ( as5600_t * d,
uint8_t * agc,
uint16_t * magnitude )

AGC, then MAGNITUDE: two transactions; the same rule.

Parameters
dThe driver.
agcReceives the AGC byte.
magnitudeReceives the magnitude, 0 to 4095.
Returns
SENSE_OK, or the bus error.

◆ as5600_read_raw()

sense_err_t as5600_read_raw ( as5600_t * d,
uint16_t * raw )

RAW ANGLE: 2 bytes from 0x0C, 0 to 4095; the same rule.

Parameters
dThe driver.
rawReceives the angle, 0 to 4095.
Returns
SENSE_OK, or the bus error.

◆ as5600_read_status()

sense_err_t as5600_read_status ( as5600_t * d,
uint8_t * status )

STATUS: 1 byte from 0x0B.

On anything but SENSE_OK status is left as it was.

Parameters
dThe driver.
statusReceives the STATUS byte.
Returns
SENSE_OK, or the bus error.

◆ as5600_state()

sense_state_t as5600_state ( const as5600_t * d)

The part's state as of the last probe.

Parameters
dThe driver.
Returns
The sense_state_t of the part.

◆ as5600_status_possible()

bool as5600_status_possible ( uint8_t status)

Whether status is one an AS5600 can give: not ML and MH together.

Bits 7, 6, 2, 1 and 0 are not looked at.

Parameters
statusThe STATUS byte.
Returns
false when ML and MH are both set, else true.

◆ as5600_step()

bool as5600_step ( as5600_t * d,
uint32_t now_ms )

Every tick: probes the part when it is due – at the first call, and SENSE_RETRY_MS after it was found absent, wrong or offline.

Returns whether it is online.

Parameters
dThe driver.
now_msThe current time, in ms.
Returns
true when the part is online.

◆ as5600_u12()

uint16_t as5600_u12 ( const uint8_t * b)

A 12-bit register pair, most significant byte first: RAW ANGLE, ANGLE or MAGNITUDE.

0 to 4095.

Parameters
bThe two bytes, high byte first.
Returns
The 12-bit value, 0 to 4095.