|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The ams OSRAM AS5600: a 12-bit magnetic rotary position sensor on I2C (Inter-Integrated Circuit). More...
Go to the source code of this file.
Data Structures | |
| struct | as5600_t |
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. | |
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
| 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.
| counts | Angle in counts; 4096 counts make a turn. |
| 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.
| a | An angle, in counts. |
| b | An angle, in counts. |
| void as5600_init | ( | as5600_t * | d, |
| sense_bus_t * | bus ) |
A part on bus at AS5600_ADDR, not yet probed.
| d | The driver. |
| bus | The sensor bus the part sits on. |
| bool as5600_md | ( | uint8_t | status | ) |
The magnet bits of status.
RAW ANGLE is a position only with MD.
| status | The STATUS byte. |
| bool as5600_mh | ( | uint8_t | status | ) |
Read the MH bit of a STATUS value.
| status | The STATUS byte. |
| bool as5600_ml | ( | uint8_t | status | ) |
Read the ML bit of a STATUS value.
| status | The STATUS byte. |
| sense_err_t as5600_read_agc | ( | as5600_t * | d, |
| uint8_t * | agc ) |
AGC: 1 byte from 0x1A; the same rule.
| d | The driver. |
| agc | Receives the AGC byte. |
| 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.
| d | The driver. |
| status | Receives the STATUS byte. |
| raw | Receives the angle, 0 to 4095. |
| sense_err_t as5600_read_mag | ( | as5600_t * | d, |
| uint16_t * | magnitude ) |
MAGNITUDE: 2 bytes from 0x1B, 0 to 4095; the same rule.
| d | The driver. |
| magnitude | Receives the magnitude, 0 to 4095. |
| sense_err_t as5600_read_magnitude | ( | as5600_t * | d, |
| uint8_t * | agc, | ||
| uint16_t * | magnitude ) |
AGC, then MAGNITUDE: two transactions; the same rule.
| d | The driver. |
| agc | Receives the AGC byte. |
| magnitude | Receives the magnitude, 0 to 4095. |
| sense_err_t as5600_read_raw | ( | as5600_t * | d, |
| uint16_t * | raw ) |
RAW ANGLE: 2 bytes from 0x0C, 0 to 4095; the same rule.
| d | The driver. |
| raw | Receives the angle, 0 to 4095. |
| 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.
| d | The driver. |
| status | Receives the STATUS byte. |
| sense_state_t as5600_state | ( | const as5600_t * | d | ) |
The part's state as of the last probe.
| d | The driver. |
| 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.
| status | The STATUS byte. |
| 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.
| d | The driver. |
| now_ms | The current time, in ms. |
| 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.
| b | The two bytes, high byte first. |