Skip to content

Commit 8624656

Browse files
committed
Merge branch 'contrib/github_pr_382' into 'master'
AS5048A encoder support (GitHub PR) Closes AEGHB-725 See merge request ae_group/esp-iot-solution!1049
2 parents d4f0c73 + 6064126 commit 8624656

File tree

7 files changed

+210
-3
lines changed

7 files changed

+210
-3
lines changed

components/motor/esp_simplefoc/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# ChangeLog
22

3+
4+
## v0.2.0 - 2024-7-5
5+
### Enhancements:
6+
* FOC:
7+
* Support for as5048a encoder added
8+
39
## v0.1.2 - 2023-12-11
410
### Bug Fix:
511
* FOC:

components/motor/esp_simplefoc/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ set(SRC_FILES
66
"port/esp/esp_app_fmath.cpp"
77
"port/esp/esp_app_print.cpp"
88
"port/angle_sensor/as5600.cpp"
9-
"port/angle_sensor/mt6701.cpp")
9+
"port/angle_sensor/mt6701.cpp"
10+
"port/angle_sensor/as5048a.cpp")
1011

1112
set(INC_FILES "port/esp/include/" "port/angle_sensor")
1213
set(IGNORE_FILES "port/esp/esp_hal_adc.cpp" "port/esp/esp_hal_mcpwm.cpp"
13-
"port/esp/esp_hal_bldc_3pwm.cpp" "port/angle_sensor/mt6701.cpp")
14+
"port/esp/esp_hal_bldc_3pwm.cpp" "port/angle_sensor/mt6701.cpp" "port/angle_sensor/as5048a.cpp")
1415

1516
idf_component_register(
1617
SRCS

components/motor/esp_simplefoc/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 0.1.1
1+
version: 0.2.0
22
targets:
33
- esp32
44
- esp32s2
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include "as5048a.h"
7+
#include "esp_log.h"
8+
#include "esp_check.h"
9+
10+
#define AS5048A_REG_ANGLE 0x3FFF
11+
#define PI 3.14159265358979f
12+
13+
static const char *TAG = "AS5048a";
14+
15+
AS5048a::AS5048a(spi_host_device_t spi_host, gpio_num_t sclk_io, gpio_num_t miso_io, gpio_num_t mosi_io, gpio_num_t cs_io)
16+
{
17+
_spi_host = spi_host;
18+
_sclk_io = sclk_io;
19+
_miso_io = miso_io;
20+
_mosi_io = mosi_io;
21+
_cs_io = cs_io;
22+
is_installed = false;
23+
}
24+
25+
AS5048a::~AS5048a()
26+
{
27+
if (is_installed) {
28+
deinit();
29+
}
30+
}
31+
32+
void AS5048a::deinit()
33+
{
34+
esp_err_t ret;
35+
ret = spi_bus_remove_device(spi_device);
36+
ESP_RETURN_ON_FALSE(ret == ESP_OK,, TAG, "SPI remove device fail");
37+
ret = spi_bus_free(_spi_host);
38+
ESP_RETURN_ON_FALSE(ret == ESP_OK,, TAG, "SPI free fail");
39+
is_installed = false;
40+
}
41+
42+
void AS5048a::init()
43+
{
44+
esp_err_t ret;
45+
46+
/*!< Configuration for the spi bus */
47+
spi_bus_config_t buscfg = {
48+
.mosi_io_num = _mosi_io,
49+
.miso_io_num = _miso_io,
50+
.sclk_io_num = _sclk_io,
51+
.quadwp_io_num = -1,
52+
.quadhd_io_num = -1,
53+
.max_transfer_sz = 1000,
54+
};
55+
ret = spi_bus_initialize(_spi_host, &buscfg, SPI_DMA_CH_AUTO);
56+
ESP_RETURN_ON_FALSE(ret == ESP_OK,, TAG, "SPI bus init fail");
57+
58+
spi_device_interface_config_t devcfg = {
59+
.command_bits = 0,
60+
.address_bits = 0,
61+
.dummy_bits = 0,
62+
.mode = 1,
63+
.cs_ena_pretrans = 1,
64+
.clock_speed_hz = 4 * 1000 * 1000,
65+
.spics_io_num = _cs_io,
66+
.queue_size = 1,
67+
};
68+
69+
ret = spi_bus_add_device(_spi_host, &devcfg, &spi_device);
70+
ESP_RETURN_ON_FALSE(ret == ESP_OK,, TAG, "SPI bus add device fail");
71+
72+
is_installed = true;
73+
}
74+
75+
uint8_t AS5048a::calculateParity(uint16_t value)
76+
{
77+
uint8_t count = 0;
78+
for (int i = 0; i < 16; i++) {
79+
if (value & 0x1) {
80+
count++;
81+
}
82+
value >>= 1;
83+
}
84+
return count & 0x1;
85+
}
86+
87+
uint16_t AS5048a::readRegister(uint16_t reg_address)
88+
{
89+
uint16_t command = 1 << 14; // PAR=0 R/W=R (Read command)
90+
command |= reg_address; // Command to read angle
91+
command |= ((uint16_t)calculateParity(command) << 15); // Adding parity bit
92+
93+
uint8_t cmd_high = (command >> 8) & 0xFF;
94+
uint8_t cmd_low = command & 0xFF;
95+
uint8_t tx_buffer[2] = {cmd_high, cmd_low};
96+
spi_transaction_t t = {};
97+
t.length = 16; // 16 bits
98+
t.tx_buffer = tx_buffer;
99+
t.rx_buffer = NULL;
100+
spi_device_transmit(spi_device, &t);
101+
102+
uint8_t rx_buffer[2] = {};
103+
t.length = 16; // 16 bits
104+
t.tx_buffer = NULL;
105+
t.rxlength = 16; // 16 bits
106+
t.rx_buffer = rx_buffer;
107+
spi_device_transmit(spi_device, &t);
108+
109+
uint16_t reg_value = (rx_buffer[0] << 8) | rx_buffer[1];
110+
return reg_value & 0x3FFF; // Masking to get 14 bits angle value
111+
}
112+
113+
uint16_t AS5048a::readRawPosition()
114+
{
115+
return readRegister(AS5048A_REG_ANGLE);
116+
}
117+
118+
float AS5048a::getSensorAngle()
119+
{
120+
uint16_t raw_angle = readRawPosition();
121+
float angle = (((int)raw_angle & 0b0011111111111111) * 360.0f / 16383.0f) * (PI / 180.0f);
122+
return angle;
123+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include "common/base_classes/Sensor.h"
10+
#include "driver/spi_master.h"
11+
#include "driver/gpio.h"
12+
13+
class AS5048a : public Sensor {
14+
public:
15+
/**
16+
* @brief Construct a new AS5048a object
17+
*
18+
* @param spi_host
19+
* @param sclk_io
20+
* @param miso_io
21+
* @param mosi_io
22+
* @param cs_io
23+
*/
24+
AS5048a(spi_host_device_t spi_host, gpio_num_t sclk_io, gpio_num_t miso_io, gpio_num_t mosi_io, gpio_num_t cs_io);
25+
/**
26+
* @brief Destroy the AS5048a object
27+
*
28+
*/
29+
~AS5048a();
30+
/**
31+
* @brief Init spi for AS5048a
32+
*
33+
*/
34+
void init();
35+
/**
36+
* @brief Deinit spi for AS5048a
37+
*
38+
*/
39+
void deinit();
40+
/**
41+
* @brief Get the output of AS5048a
42+
*
43+
* @return float
44+
*/
45+
float getSensorAngle();
46+
47+
private:
48+
uint16_t readRegister(uint16_t reg_address);
49+
uint16_t readRawPosition();
50+
static uint8_t calculateParity(uint16_t value);
51+
52+
private:
53+
spi_host_device_t _spi_host;
54+
gpio_num_t _sclk_io;
55+
gpio_num_t _miso_io;
56+
gpio_num_t _mosi_io;
57+
gpio_num_t _cs_io;
58+
spi_device_handle_t spi_device;
59+
bool is_installed;
60+
61+
};

components/motor/esp_simplefoc/port/esp/include/esp_simplefoc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@
1515
#include "current_sense/LowsideCurrentSense.h"
1616
#include "../../angle_sensor/as5600.h"
1717
#include "../../angle_sensor/mt6701.h"
18+
#include "../../angle_sensor/as5048a.h"

components/motor/esp_simplefoc/test_apps/main/test_esp_simplefoc.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,21 @@ TEST_CASE("test mt6701", "[sensor][mt6701]")
4242
mt6701.deinit();
4343
}
4444

45+
TEST_CASE("test as5048a", "[sensor][as5048a]")
46+
{
47+
#if CONFIG_IDF_TARGET_ESP32C3
48+
AS5048a as5048a = AS5048a(SPI2_HOST, GPIO_NUM_2, GPIO_NUM_1, (gpio_num_t) -1, GPIO_NUM_3);
49+
#else
50+
AS5048a as5048a = AS5048a(SPI2_HOST, GPIO_NUM_2, GPIO_NUM_1, (gpio_num_t) -1, GPIO_NUM_42);
51+
#endif
52+
as5048a.init();
53+
for (int i = 0; i < 10; ++i) {
54+
ESP_LOGI(TAG, "angle:%.2f", as5048a.getSensorAngle());
55+
vTaskDelay(1000 / portTICK_PERIOD_MS);
56+
}
57+
as5048a.deinit();
58+
}
59+
4560
TEST_CASE("test esp_simplefoc openloop control", "[single motor][openloop][14pp][ledc][drv8313][c3]")
4661
{
4762
BLDCMotor motor = BLDCMotor(14);

0 commit comments

Comments
 (0)