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