I have connected AS5048A magnetic encoder to ESP32 dev board (VSPI/SPI3 bus: CS=5, CLK=18, MISO=19, MOSI=23). Using ESP IDF version 4.0.1. Arduino library: https://github.com/espressif/arduino-esp32/tree/idf-release/v4.0
I tested two versions of SPI transmission: a) with and b) without Arduino ESP-IDF library
Arduino version generally works very well with different speeds. Pure IDF struggles a lot to properly receive data. Weirdly, pure IDF version manages to send 0x0000 and 0xFFFF (read angle command with parity and r/w) in SPI mode 3 (Arduino works with mode 1) but other commands fail. Also 0x0000 (null command) returns some trash (0x6000 or something similar instead of 0x00000). So pure IDF version can read properly the angle (?!) with SPI mode 3, but anything else fails (I guess it's some accident since read angle command is 0xFFFF).
I tried every mode and a lot of timing configurations. Trying to look inside Arduino library SPI it uses a different approach to SPI than IDF itself.
Any help/idea? Below are codes.
Arduino implementation is pretty straightforward:
this->settings = SPISettings(3000000, MSBFIRST, SPI_MODE1);
pinMode(this->_cs, OUTPUT);
SPI.begin();
SPI.beginTransaction(this->settings);
digitalWrite(this->_cs, LOW);
uint16_t response = SPI.transfer16(command);
digitalWrite(this->_cs, HIGH);
Pure IDF follows:
spi_host_device_t spi_host = SPI3_HOST;
spi_device_handle_t spi;
esp_err_t ret;
spi_bus_config_t buscfg;
memset(&buscfg, 0, sizeof(buscfg));
buscfg.mosi_io_num = pinMOSI;
buscfg.miso_io_num = pinMISO;
buscfg.sclk_io_num = pinCLK;
buscfg.quadwp_io_num = -1;
buscfg.quadhd_io_num = -1;
buscfg.max_transfer_sz = 1;
buscfg.flags = SPICOMMON_BUSFLAG_MASTER ; /*| SPICOMMON_BUSFLAG_IOMUX_PINS ;*/
buscfg.intr_flags = 0;
spi_device_interface_config_t devcfg;
memset(&devcfg, 0, sizeof(devcfg));
devcfg.command_bits = 0;
devcfg.address_bits = 0;
devcfg.dummy_bits = 0;
devcfg.mode = (uint8_t) 1; //SPI_MODE;
devcfg.duty_cycle_pos = 0;
devcfg.cs_ena_pretrans = 0;
devcfg.cs_ena_posttrans = (uint8_t) 0; //CS_ENA_POSTTRANS;
devcfg.clock_speed_hz = 300 * 1000; //SPI_HZ;
devcfg.input_delay_ns = 50; // INPUT_DELAY_NS;
devcfg.spics_io_num = pinCS;
devcfg.flags = SPI_DEVICE_NO_DUMMY ;
devcfg.queue_size = 1;
devcfg.pre_cb = 0;
devcfg.post_cb = 0;
ret = spi_bus_initialize(spi_host, &buscfg, 0); // No DMA
ESP_ERROR_CHECK(ret);
ret = spi_bus_add_device(spi_host, &devcfg, &spi);
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "AS5048 device initialized on SPI with MISO=%d, MOSI=%d, CLK=%d, CS=%d, HZ=%d", pinMISO, pinMOSI, pinCLK, pinCS, SPI_HZ);
and transfer (cmd is uint16_t with parity and r/w bits) :
esp_err_t ret;
spi_transaction_t t;
spi_device_acquire_bus(spi, portMAX_DELAY);
memset(&t, 0, sizeof(t));
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA ;
*((uint16_t*)t.tx_data) = SPI_SWAP_DATA_TX(cmd, 16);
t.length = 16;
//ret = spi_device_transmit(spi, &t);
ret = spi_device_polling_transmit(spi, &t);
if(ret != ESP_OK)
ESP_LOGE(TAG, "spi_device_transmit() failed");
spi_device_release_bus(spi);
uint16_t response = SPI_SWAP_DATA_RX(*((uint16_t*)t.rx_data), 16);