Guide by Michael; PiicoDev 3-Axis Accelerometer LIS3DH - Getting Started Guide

I have just shared content in Guides > PiicoDev: “PiicoDev 3-Axis Accelerometer LIS3DH - Getting Started Guide”





Read more

6 Likes

Loving the new unified guide format to match the unified python libraries. Super handy if you might be prototyping on one device before switching to another.

2 Likes

Hi @Michael
A suggestion for the shake demo code to make the output more ‘visible’

The original loop

while True:
    if motion.shake(threshold=15):
        print("shaken!")
    else:
        print("")
    # shake() is blocking, so can be used instead of sleep_ms() to delay a loop.

my updated loop

while True:
    if motion.shake(threshold=15):
        print("shaken!")
    else:
        print(".", end="")
    # shake() is blocking, so can be used instead of sleep_ms() to delay a loop.

and some sample output

...............shaken!
.......shaken!
.........shaken!
....................................shaken!
..shaken!

cheers
Murray

p.s. been playing with new toys from the Borg article credit note - thanks

4 Likes

Hi Murray,

It’s not the conventional scroll most people are used to seeing from a terminal window, but I like it!
I’ll probably use your format in my own projects even if it doesn’t become the PiicoDev example standard.
Glad to hear there’s already a new project in the works after the Borg cube, keen to see what you make next.

2 Likes

Hi Trent,

I added that bit because with the scrolling, and practicing to get the right amount of ‘shake’ I wasn’t sure what was happening. Fast scrolling ‘blank’ lines and trying to catch a activity message drove me slightly bats…t :bat: I don’t mind seeing ‘null report’ mesages - it at least lets me know that the process is doing something!

Murray

2 Likes

Hi, I had some questions regarding the code in the PiicoDev 3-Axis Accelerometer LIS3DH - Getting Started Guide.

We are using a Raspberry Pi Pico and for some reason whenever we try to run the acceleration function the serial connection gets interrupted for some reason and it returns that the connection is taken.

Does anyone have any advice on how to troubleshoot this? Thanks!

2 Likes

Hey @Kyden271126,

Would you be able to link us to the code you are running for this as well as the exact error message you are getting?

I see you have followed the above tutorial, have you copied the code example exactly or have you made some modifications for your specific project?

Thanks,
Sam

2 Likes

1 Like

Hi Kyden,

When I’ve typically seen this error with other microcontrollers it usually meant the device was in use. This may not be the case here.

I can see there is quite a bit of code there so it would be great if you could upload that for us to have a look at,

1 Like

Hi Kyden,

It looks like you may have also selected the Pyboard in tools instead of the Pico

1 Like

hello there!
I’ve been making a data logger of your code example with lis3dh and also mpu6050 (another tutorial). I have problem with sampling. Here is modified code:
main
If I understand it right, I should get 400 samples per second, but I’m not getting them. It doesn’t matter if I change sampling on lis3dh (e.g.from 400Hz to 200Hz), nor if I change frequency of i2c (e.g from 400_000 Hz to 100_000 Hz) problem stays the same - not enough data samples per time.
What could be the source of a problem? Maybe there are some faster ways to save data to a file than file.write() method, or maybe I am using the file.flush() method wrong?
Best regards!

String functions are very slow. If you want a maximum logging rate then it would be preferable to write the data to file as numeric values, and convert it into strings for display as a separate reporting procedure. Similarly for the print - printing numerics only will simpify string operations but for fastest performance you should get rid of the print entirely.

However, you have a delay of sleep_ms(100) in the loop! To increase the logging rate the first thing to do would be to remove the delay.

flush() will take some time out of the loop but it has to happen at some stage anyway so the overall difference of including it is not large. Having a flush at each iteration adds some overhead but reduces the occurrence of longer delays as the OS writes a full buffer to disk.

4 Likes

Thank you for your answer.
Could you please show me how to write numerics into a txt file not using str()? I am finding only examples with using file.write() method, that needs to have str() to write a data.

You can’t write numerics into a text file (other than as text) but you can write numerics into a binary file as bytes. In your case you will be writing exactly the same set of numeric values each time, so you are using ‘fixed length records’. This means that you can read them back sequentially into the same set of three variables in order to format as text and print for reporting.

To create a binary file open it using ‘wb’ to indicate writeable binary.

file_acc_lis3DH=open("file_acc_lis3dh.bin", wb"

To write a record of 3 numeric values:

num=[aX2, aY2, aZ2]
arr=bytearray(num)
f.write(arr)

If the variables were already array elements rather than distinct variables that first step to create an array would not be needed and that would speed things up a bit more.

You would read each value back using code like this (courtesy of Python Forum):

with open("file_acc_lis3dh.bin", rb") as file:
# Read a float (4 bytes)
float_value = struct.unpack('f', "file_acc_lis3dh.bin"(4))[0]
print(f"Float: {float_value}")
2 Likes

Thx for your help, but unfortunately problem still occurs. Below code from Thonny:

motion2 = PiicoDev_LIS3DH(bus=1, freq=400_000, sda=Pin(6), scl=Pin(7), range=16, rate=400, asw=1)

while True:
    aX, aY, aZ = motion2.acceleration
                    
    with open('exampleZ.bin', 'ab') as plikZ:
        plikZ.write(struct.pack('f', aZ))

And the result in matlab looks like this:


sampling rate is about 30Hz :frowning: with saving only 1 axis.
I’am importing values from bin file to maltab in matlab ide - code below:

plik = 'C:\Users\3mis\OneDrive - Politechnika Warszawska\mgr_EmilWacławik\thonny_matlab\dzialajace\240605\exampleZ.bin';
id = fopen(plik); 
az = fread(id, 'float'); 
fclose(id);

n = length(az); 
fs = 400;
tstop = 1/fs*n; 
tstart = 1/fs; 
t = linspace(tstart, tstop, n); 

figure, set(gcf, 'Position',  [800, 250, 1500, 1000]), sgtitle('vector Z only');
subplot(2,1,1), hold on, 
plot(az), xlabel('samples [n]'), 
hold off, grid on, grid minor; 
subplot(2,1,2), hold on, 
plot(t, az), xlabel('time [s]'), 
hold off, grid on, grid minor; 

Do you have any ideas why this fs is so slow?

Did you remove the delay from the loop?

You are opening the file each time the loop is executed - that’s not needed. Instead open the file before the main loop starts and only close it after the main loop finishes.

Yes, delay has been removed from the loop in the moment you mentioned about it.
It’s working with the proper sampling frequency after I have changed the moment of opening the file - before loop. :slight_smile:
Here are the results from maltab:


And final code for descendants:

from PiicoDev_LIS3DH import PiicoDev_LIS3DH
from machine import *
import utime
import struct 

motion2 = PiicoDev_LIS3DH(bus=1, freq=400_000, sda=Pin(6), scl=Pin(7), range=16, rate=400, asw=1)

with open('exampleZ.bin', 'ab') as plikZ:
    while True:
        aX, aY, aZ = motion2.acceleration
        plikZ.write(struct.pack('f', aZ))

Thanks a lot for your help @Jeff105671 !

2 Likes

That’s a great result that is sure to be helpful for anyone trying to get a high sampling rate for the sensor. Thanks for letting us know that you got it sorted out.

3 Likes

You are writing three variables to three different files. This will make each iteration of the loop nearly three times as long as your previous example.

Instead, use an array for your three variables and write the array to a single file, as in the original code listed above.

If you must have three files you could write code to unpack the single file into the three separate files after the logging period completes.

Polling the button state is slowing the loop to some extent. If reducing the file operations to a single file does not enable 400 Hz sampling, then you could try using interrupts to detect the button-up state change. I am not sure about how efficient interrupt handling is, but it is usually better than polling a GPIO port.

2 Likes

Problem occurs only on MPU6050. On LIS3DH I have approx. twice the sampling frequency that I’ve set (for fs=400Hz I get 800Hz) - frequency set now on LIS3DH in line below:

motion2 = PiicoDev_LIS3DH(bus=0, freq=400_000, sda=Pin(4), scl=Pin(5), range=16, rate=400, asw=1)

And before, on MPU6050 I have used this:

motion1 = PiicoDev_MPU6050(bus=0, freq=400_000, sda=Pin(4), scl=Pin(5))
motion1.set_accel_range = 0x18

And below is the result on LIS3DH, with set fs=400Hz in Thonny (motion2 object), and also while plotting in matlab with the same fs=400Hz set. The first two shake events should be at interval 10sec.


Strange for me, but overall I am going to test what you have mentioned and than get back to you. Thx!