ESP32 ADXL345 (accelerometer) SPI

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
aleskeyfedorovich
Posts: 28
Joined: Mon Aug 27, 2018 4:43 pm

ESP32 ADXL345 (accelerometer) SPI

Post by aleskeyfedorovich » Wed Oct 21, 2020 5:00 pm

I'm trying to write and read **ADXL345** (but ADXL accelerometers are all pretty similar) through **SPI**; there are many posts on this topic but none that uses **ESP32** based device.

List of related topics I've found:
* viewtopic.php?f=6&t=1743&p=10020&hilit= ... spi#p10020
* viewtopic.php?f=2&t=6539&p=51710&hilit= ... spi#p51710
* viewtopic.php?f=20&t=8076&p=46416&hilit ... sor#p46416
* viewtopic.php?f=18&t=8717&p=49172&hilit=spi#p49172
* https://github.com/dzheng256/adxl345spi ... adxl345.py

First thing I don't understand reading others code is why and when while reading and writing to the device the buffers must be compared with 0x40 and 0x80. Is this an SPI rule? It seems to me every piece of code have a different approach to this.
Last edited by aleskeyfedorovich on Thu Oct 22, 2020 7:09 am, edited 1 time in total.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: ESP32 ADXL345 (accelerometer) SPI

Post by jimmo » Wed Oct 21, 2020 10:53 pm

aleskeyfedorovich wrote:
Wed Oct 21, 2020 5:00 pm
First thing I don't understand reading others code is why and when while reading and writing to the device the buffers must be compared with 0x40 and 0x80. Is this an SPI rule? It seems to me every piece of code have a different approach to this.
Just looking at a snippet from one of the threads you linked to: viewtopic.php?f=6&t=1743&p=10020#p10022

Code: Select all

READWRITE_CMD = const(0x80)
MULTIPLEBYTE_CMD = const(0x40)
It looks like this tells the sensor what sort of command it is, so the code can tell how to interpret the remaining bytes.

aleskeyfedorovich
Posts: 28
Joined: Mon Aug 27, 2018 4:43 pm

Re: ESP32 ADXL345 (accelerometer) SPI

Post by aleskeyfedorovich » Thu Oct 22, 2020 6:44 am

Ok I found on the [datasheet](https://www.analog.com/media/en/technic ... DXL345.pdf), in the SPI paragraph that:
* first bit of the transmission must be 1 if reading and 0 if writing
* second bit must be 1 if reading or writing multiple bytes, 0 otherwise

Still after this clarification I get some strange results

In order to test if the comunication is working properly I'm reading the id of the device, setting the frequency and then reading back the frequency:

Code: Select all

from machine import Pin, SPI
from micropython import const

# addresses
regaddr_id = const(0x00)
regaddr_freq = const(0x2C)

# SPI definitions
READ_MASK = const(0x80)
MULTIBYTE_MASK = const(0x40)

# set up
spi = SPI(2, sck=Pin(18, Pin.OUT), mosi=Pin(23, Pin.OUT), miso=Pin(19), baudrate=2000000, polarity=1, phase=1, bits=8,
          firstbit=SPI.MSB)
CS = Pin(5, Pin.OUT, value=1)


def read(regaddr, nbytes):
    wbuf = regaddr | READ_MASK
    if nbytes > 1:
        wbuf = wbuf | MULTIBYTE_MASK
    CS.value(0)
    value = spi.read(nbytes, wbuf)
    CS.value(1)
    return value


def read_into(rbuf, regaddr):
    wbuf = bytearray(len(rbuf))
    wbuf[0] = regaddr | READ_MASK | MULTIBYTE_MASK
    CS.value(0)
    spi.write_readinto(wbuf, rbuf)
    CS.value(1)
    return rbuf


def write(regaddr, bt):
    CS.value(0)
    spi.write(bytearray(regaddr | MULTIBYTE_MASK, bt))
    CS.value(1)


# device id
devid = read(regaddr_id, 1)
if devid == b'\xE5':
    print('OK devid')
else:
    print('Not OK: devid = ' + str(devid))

# set frequency 3.2 kHz
write(regaddr_freq, 0x0F)
freq = read(regaddr_freq, 1)
if freq == b'\x0F':
    print('OK frequency')
else:
    print('Not OK: freq = ' + str(freq))

spi.deinit()
The first time I run this after turning on the device I get the proper id of the device that is 0xe5, BUT I get 0xe5 also reading the frequency I just set to 0x0f!
In the second run I get always 0x00 for both the reading, what am I doing wrong?

aleskeyfedorovich
Posts: 28
Joined: Mon Aug 27, 2018 4:43 pm

Re: ESP32 ADXL345 (accelerometer) SPI

Post by aleskeyfedorovich » Wed Oct 28, 2020 7:54 pm

The key is the SPI diagram in the datasheet (figure 37, figure 38).
It's necessary to read at least 2 bytes and the first must be ignored.

Code: Select all

def read(regaddr, nbytes):
    wbuf = regaddr | READ_MASK
    if nbytes > 1:
        wbuf = wbuf | MULTIBYTE_MASK
    CS.value(0)
    value = spi.read(nbytes + 1, wbuf)[1:]
    CS.value(1)
    return value
This way I get correct results

aleskeyfedorovich
Posts: 28
Joined: Mon Aug 27, 2018 4:43 pm

Re: ESP32 ADXL345 (accelerometer) SPI

Post by aleskeyfedorovich » Mon Nov 02, 2020 2:17 pm

I decided to put the final library on github at this [link](https://github.com/AlekseyFedorovich/ADXL345_spi)

Post Reply