ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
as5600.cpp
Go to the documentation of this file.
1#include "as5600.h"
2#include "esphome/core/log.h"
3
4namespace esphome::as5600 {
5
6static const char *const TAG = "as5600";
7
8// Configuration registers
9static const uint8_t REGISTER_ZMCO = 0x00; // 8 bytes / R
10static const uint8_t REGISTER_ZPOS = 0x01; // 16 bytes / RW
11static const uint8_t REGISTER_MPOS = 0x03; // 16 bytes / RW
12static const uint8_t REGISTER_MANG = 0x05; // 16 bytes / RW
13static const uint8_t REGISTER_CONF = 0x07; // 16 bytes / RW
14
15// Output registers
16static const uint8_t REGISTER_ANGLE_RAW = 0x0C; // 16 bytes / R
17static const uint8_t REGISTER_ANGLE = 0x0E; // 16 bytes / R
18
19// Status registers
20static const uint8_t REGISTER_STATUS = 0x0B; // 8 bytes / R
21static const uint8_t REGISTER_AGC = 0x1A; // 8 bytes / R
22static const uint8_t REGISTER_MAGNITUDE = 0x1B; // 16 bytes / R
23
25 if (!this->read_byte(REGISTER_STATUS).has_value()) {
26 this->mark_failed();
27 return;
28 }
29
30 // configuration direction pin, if given
31 // the dir pin on the chip should be low for clockwise
32 // and high for counterclockwise. If the pin is left floating
33 // the reported positions will be erratic.
34 if (this->dir_pin_ != nullptr) {
36 this->dir_pin_->digital_write(this->direction_ == 1);
37 }
38
39 // build config register
40 // take the value, shift it left, and add mask to it to ensure we
41 // are only changing the bits appropriate for that setting in the
42 // off chance we somehow have bad value in there and it makes for
43 // a nice visual for the bit positions.
44 uint16_t config = 0;
45 // clang-format off
46 config |= (this->watchdog_ << 13) & 0b0010000000000000;
47 config |= (this->fast_filter_ << 10) & 0b0001110000000000;
48 config |= (this->slow_filter_ << 8) & 0b0000001100000000;
49 config |= (this->pwm_frequency_ << 6) & 0b0000000011000000;
50 config |= (this->output_mode_ << 4) & 0b0000000000110000;
51 config |= (this->hysteresis_ << 2) & 0b0000000000001100;
52 config |= (this->power_mode_ << 0) & 0b0000000000000011;
53 // clang-format on
54
55 // write config to config register
56 if (!this->write_byte_16(REGISTER_CONF, config)) {
57 this->mark_failed();
58 return;
59 }
60
61 // configure the start position
62 this->write_byte_16(REGISTER_ZPOS, this->start_position_);
63
64 // configure either end position or max angle
65 if (this->end_mode_ == END_MODE_POSITION) {
66 this->write_byte_16(REGISTER_MPOS, this->end_position_);
67 } else {
68 this->write_byte_16(REGISTER_MANG, this->end_position_);
69 }
70
71 // calculate the raw max from end position or start + range
72 this->raw_max_ = this->end_mode_ == END_MODE_POSITION ? this->end_position_ & 4095
73 : (this->start_position_ + this->end_position_) & 4095;
74
75 // calculate allowed range of motion by taking the start from the end
76 // but only if the end is greater than the start. If the start is greater
77 // than the end position, then that means we take the start all the way to
78 // reset point (i.e. 0 deg raw) and then we that with the end position
79 uint16_t range = this->raw_max_ > this->start_position_ ? this->raw_max_ - this->start_position_
80 : (4095 - this->start_position_) + this->raw_max_;
81
82 // range scale is ratio of actual allowed range to the full range
83 this->range_scale_ = range / 4095.0f;
84}
85
87 ESP_LOGCONFIG(TAG, "AS5600:");
88 LOG_I2C_DEVICE(this);
89
90 if (this->is_failed()) {
91 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
92 return;
93 }
94
95 ESP_LOGCONFIG(TAG,
96 " Watchdog: %d\n"
97 " Fast Filter: %d\n"
98 " Slow Filter: %d\n"
99 " Hysteresis: %d\n"
100 " Start Position: %d",
101 this->watchdog_, this->fast_filter_, this->slow_filter_, this->hysteresis_, this->start_position_);
102 if (this->end_mode_ == END_MODE_POSITION) {
103 ESP_LOGCONFIG(TAG, " End Position: %d", this->end_position_);
104 } else {
105 ESP_LOGCONFIG(TAG, " Range: %d", this->end_position_);
106 }
107}
108
109bool AS5600Component::in_range(uint16_t raw_position) {
110 return this->raw_max_ > this->start_position_
111 ? raw_position >= this->start_position_ && raw_position <= this->raw_max_
112 : raw_position >= this->start_position_ || raw_position <= this->raw_max_;
113}
114
116 uint8_t status = this->reg(REGISTER_STATUS).get() >> 3 & 0b000111;
117 return static_cast<AS5600MagnetStatus>(status);
118}
119
120optional<uint16_t> AS5600Component::read_position() {
121 uint16_t pos = 0;
122 if (!this->read_byte_16(REGISTER_ANGLE, &pos)) {
123 return {};
124 }
125 return pos;
126}
127
129 uint16_t pos = 0;
130 if (!this->read_byte_16(REGISTER_ANGLE_RAW, &pos)) {
131 return {};
132 }
133 return pos;
134}
135
136} // namespace esphome::as5600
uint8_t status
Definition bl0942.h:8
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:272
virtual void pin_mode(gpio::Flags flags)=0
virtual void digital_write(bool value)=0
optional< uint16_t > read_position()
Definition as5600.cpp:120
AS5600MagnetStatus read_magnet_status()
Definition as5600.cpp:115
optional< uint16_t > read_raw_position()
Definition as5600.cpp:128
bool in_range(uint16_t raw_position)
Definition as5600.cpp:109
void setup() override
Set up the internal sensor array.
Definition as5600.cpp:24
EndPositionMode end_mode_
Definition as5600.h:98
InternalGPIOPin * dir_pin_
Definition as5600.h:86
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:240
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition i2c.h:249
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:152
bool write_byte_16(uint8_t a_register, uint16_t data) const
Definition i2c.h:267
uint8_t get() const
returns the register value
Definition i2c.cpp:84
Range range
Definition msa3xx.h:0
@ END_MODE_POSITION
Definition as5600.h:23
@ FLAG_OUTPUT
Definition gpio.h:28
size_t size_t pos
Definition helpers.h:1038