ADXL375 maximum polling rate

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

ADXL375 maximum polling rate

Post by richpaul6806 »

I need to measure an impact and was hoping to use an adxl375 and my metro grand central and write the results to either the internal flash or an sd card to analyze later. My main worry is the polling rate/write speed. The impact is pretty short and if it measures on one side of the impact and then the other I will not get the data needed. What can I do to increase rate? Is there a setting a need to select? Should I save data to internal flash rather than the sd card? Should I forget circuitpython (which I am more comfortable with) and try to use arduino? Are there any other tricks to get this thing writing data as quickly as possible?

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ADXL375 maximum polling rate

Post by adafruit_support_bill »

The chip has a variable output data rate. This is the rate at which the data registers are updated and is independent of the rate at which your code polls the registers.

The fastest data rate for full resolution output is 800 Hz. 1600 & 3200Hz rates are also possible with reduced resolution. (See page 28 of the data sheet)

The chip also can be configured to capture data from 'shocks' in its internal buffers and generate an interrupt. This is described on page 13 and page 26 of the data sheet.

The libraries at this point support just basic polling at the default update rate of 100Hz. (the poll rate will depend on your code) To access the full functionality of the chip will require writing some code to write to the configuration registers.

I'd recommend reading through the datasheet to get an understanding of what the chip is capable of:
https://www.analog.com/media/en/technic ... dxl375.pdf

User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

Re: ADXL375 maximum polling rate

Post by richpaul6806 »

Thanks. I have not really dealt in register values, I mostly stick with libraries. So basically, I need to do something like this: https://docs.circuitpython.org/projects ... mples.html and set the BW_rate register (0x2C) to 00001101?

As far as other parameters, is it significantly faster to write to internal flash or is SD card fine?

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ADXL375 maximum polling rate

Post by adafruit_support_bill »

. . . and set the BW_rate register (0x2C) to 00001101?
The BW_RATE register also contains the LOW_POWER bit (bit 4). Setting that bit to zero will put the device in "Normal" mode - which is probably what you want.

In general, when you need to set just some of the bits in a register, you do what is called a "Read/Modify/Write". That means: read the whole register, modify the specific bits, and then write it back out.

SD card speeds vary widely, but writing to internal flash is typically faster. But flash memory has a finite number of write/erase cycles (typically about 100K). RAM is much much faster and does not have that limitation. It is also simpler to program (just allocate an array and write to it). I'd go for a processor with lots of RAM and buffer the data there.

User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

Re: ADXL375 maximum polling rate

Post by richpaul6806 »

Thanks. So basically what they were doing in the first example of the link I posted. Just flipping a couple necessary bits in the register. If default is 100Hz (1010) I assume I need to flip D2, D1, and D0.

As far as recording data, since I am measuring an impact, I really only need to record the 2 bytes at 0x36 and 0x37 and another couple to timestamp it (in case there is some variation in the rate which it is recording . If I assume a theoretical max of 800hz that would be 3.2kB/sec. Ten seconds for the test is generous so it should be around 32kB. (does that math sound right?). Once I have the array I should be able to unpack the bytes and multiply them by 0.049 g/LSB in a similar way the library does to get the decimal value for Z-axis g force.

Is there documentation for allocating an array in RAM and reading/writing to it?

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ADXL375 maximum polling rate

Post by adafruit_support_bill »

A circular or 'ring' buffer is probably what you want here. This lets you record continuously. When the buffer fills, the newest samples will begin over-writing the oldest samples. And when you detect the peak, you will have the last 'N' samples leading up to that peak.

There is an example of a circular buffer in Python here: https://stackoverflow.com/questions/415 ... lar-buffer

User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

Re: ADXL375 maximum polling rate

Post by richpaul6806 »

Ok thanks. I was able to log data to a ulab array. Now im trying to figure out setting the data_rate register. ring buffer will be next.

User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

Re: ADXL375 maximum polling rate

Post by richpaul6806 »

Do registers go from D0-D7 or from D7-D0? I ran this code to try changing the rate register (using my adxl343, adxl375 isnt in until tuesday but I want to have the code mostly ready):

Code: Select all

from board import SCL, SDA
from busio import I2C
from adafruit_bus_device.i2c_device import I2CDevice
from adafruit_register.i2c_bits import RWBits

DEVICE_ADDRESS = 0x53  # device address of APDS9960 board
rate_register = 0x2C  # a control register on the APDS9960 board

class DeviceControl:  # pylint: disable-msg=too-few-public-methods
    def __init__(self, i2c):
        self.i2c_device = i2c  # self.i2c_device required by RWBit class

    rate_set = RWBits(4, rate_register, 0)  # update bits 0,1,2,3


# The follow is for I2C communications
comm_port = I2C(SCL, SDA)
device = I2CDevice(comm_port, DEVICE_ADDRESS)
settings = DeviceControl(device)

# set the bits in the device
settings.rate_set = 13
But when I check it with:

Code: Select all

with device as bus_device:
    bus_device.write(bytes([rate_register]))
    result = bytearray(1)
    bus_device.readinto(result)

print("".join("{:02x}".format(x) for x in result))
I end up with 0D rather than DA (reset value is 00001010 so I should be at 11011010)

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ADXL375 maximum polling rate

Post by adafruit_support_bill »

It goes D7-D0 as shown in the datasheet register map. Bit 0 is the least significant bit, so it is at the far right.

User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

Re: ADXL375 maximum polling rate

Post by richpaul6806 »

OK, so when I do RWBits(4, rate_register, 0) I am changing bits D0-D3 going right to left, but when I run bus_device.write(bytes([rate_register])) I am reading the entire byte left to right?

User avatar
slight
 
Posts: 120
Joined: Wed Sep 12, 2012 2:23 am

Re: ADXL375 maximum polling rate

Post by slight »

hi richpaul6806,

just some thoughts on speed considerations:
i just created some speed tests for my board..
but it should be very easy to adapt to your board.
these tests are only to get a idea of the read-speeds of the sensor / writing data to the computer..
https://github.com/s-light/cp_magic_pai ... eedtest.py

i have written down some of my findings at
viewtopic.php?p=973417#p973417

Code: Select all

[1.003] 'lis3dh.acceleration[1] → 400Hz (2.5ms)                                              '  needs      2.879ms/call
[0.002] 'print(i * 3.14159)                                                                    '  needs      2.355ms/call
[0.001] 'print(lis3dh.acceleration[1]) 400Hz                                                   '  needs     20.312ms/call
[0.002] 'print(lis3dh.acceleration[1]) 400Hz no display                                        '  needs      3.383ms/call
[0.069] 'print(i * 3.14159)                                                                    '  needs      0.281ms/call
[0.002] 'print("{:10.3f}".format(lis3dh.acceleration[1])) 400Hz no display                     '  needs      3.852ms/call
[0.002] 'print("{:10.3f} {:10.3f} {:10.3f}".format(*lis3dh.acceleration)) 400Hz no display     '  needs      4.070ms/call
[1.000] done...
for me the i2c read speed was the limiting factor...
and in my case was fast enough :-)

i just looked at the Adafruit Grand Central M4 Express featuring the SAMD51 -
with a Cortex M4 core running at 120 MHz.
for my tests i used a Adafruit ESP32-S3 Reverse TFT Feather -
with a ESP32-S3 Dual Core 240MHz Tensilica processor

so maybe this is running CP faster...

if you switch to arduino you are in another level of speed with this processors ;-)

sunny greetings
stefan

User avatar
slight
 
Posts: 120
Joined: Wed Sep 12, 2012 2:23 am

Re: ADXL375 maximum polling rate

Post by slight »

adafruit_support_bill wrote: Sun May 28, 2023 2:56 pm A circular or 'ring' buffer is probably what you want here. This lets you record continuously. When the buffer fills, the newest samples will begin over-writing the oldest samples. And when you detect the peak, you will have the last 'N' samples leading up to that peak.

There is an example of a circular buffer in Python here: https://stackoverflow.com/questions/415 ... lar-buffer
did you mean the answer with the deque example?
i found that the collections CP implementation does not exactly follow CPython yet - use

Code: Select all

q = collections.deque((), 10)
instead..
richpaul6806 wrote: Sun May 28, 2023 4:12 pm I was able to log data to a ulab array.
are you willing to share how you implemented the ring-buffer?
i would like to try similar things in my use-case...

sunny greetings
stefan

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ADXL375 maximum polling rate

Post by adafruit_support_bill »

You are setting the low-order 4 bits to (decimal) 13 -In binary, that is 1101 and in Hex it is 'D'.

Bits D5-D7 of that register are always 0 and D4 defaults to 0 at power up. So, "0D" is the expected value.

User avatar
richpaul6806
 
Posts: 16
Joined: Sun May 21, 2023 12:39 am

Re: ADXL375 maximum polling rate

Post by richpaul6806 »

slight wrote: Mon May 29, 2023 4:02 pm are you willing to share how you implemented the ring-buffer?
i would like to try similar things in my use-case...
I do not have it implemented yet. I wanted to make sure everything else is working properly before I waste time trying to figure that out. Right now everything is just being written to a 6000 row array (about 5 seconds worth of data). I currently need to work on some way to synchronize the clocks. The chip is running wild and updating some rows before the clock or i2c bus have a chance to update and there are a hundred or so repeated rows throughout the test (~2%). Also, ulab.numpy does not have a function to delete duplicates (that I have found) like the full python numpy library does so I have no easy way of removing them before the data is written to the SD card. Obviously I can remove them from a computer later but the goal of this project is to have an easy to understand manual that other engineers/techs can follow and have their data come out nice and neat (and accurate!) on the other side.
adafruit_support_bill wrote: Mon May 29, 2023 4:10 pm Bits D5-D7 of that register are always 0 and D4 defaults to 0 at power up. So, "0D" is the expected value.
Thanks. It makes a bit more sense now but the program reading right to left but inputting data left to right is confusing me. It seems like I should be putting in 176 rather than 13.

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ADXL375 maximum polling rate

Post by adafruit_support_bill »

I don't follow your confusion. You declared RWBits to map to the low-order 4 bits. The low order bits are always to the right -just as shown in the register map. You are reading back exactly what you are writing. 0x0D == 13.

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”