Code Monkey home page Code Monkey logo

Comments (14)

gfwilliams avatar gfwilliams commented on June 16, 2024 1

Hi - I don't believe the problem is with the Puck.js accelerometer speed - it's just that Bluetooth LE isn't capable of sending the data that fast the way you are attempting to do it

Bluetooth works on a connection interval, and the fastest this can be is 7.5ms (130Hz) according to the spec. While you can trigger more than one notification per connection interval I think the max might be around 5, and since you're updating multiple characteristics that will really eat into it.

What I'd suggest is:

  • Send the data as raw binary - sending it as human readable text is needlessly wasting data bandwidth
  • Send it all in one characteristic
  • Send multiple samples in each update - so to get 1kHz you'd have to send maybe 8 samples worth at once

As @mariusGundersen says, the best way to do all the above is really just to use the built-in UART since Espruino will automatically batch updates into the minimum amount of packets required.

Something along the lines of:

Puck.on('accel', function(a) {
  Bluetooth.write((new Int16Array([a.acc.x,a.acc.y,a.acc.z,a.gyro.x,a.gyro.y,a.gyro.z])).buffer);
});

is probably all you need. I wouldn't send the battery level 1000 times a second as you're just wasting time and bandwidth again (you could keep doing that with a characteristic as you were, but update it once a minute)

If I want to modify the existing firmware what are the steps to do this? I believe the code base is here? https://github.com/espruino/Espruino

Yes - there are some READMEs in the repo about how to build it, as well as some tutorials on the website about adding functionality. But as above it's not really an issue with Espruino at this point, it's to do with what you're trying to do with Bluetooth.

from espruino.

gfwilliams avatar gfwilliams commented on June 16, 2024 1

Ok, thanks! So we should ideally not set those low power mode flags above 52Hz? I could make a change for that...

from espruino.

mariusGundersen avatar mariusGundersen commented on June 16, 2024

I seriously doubt you can get 1khz through Bluetooth, especially using only service advertising. You could perhaps try to send it through the uart, streaming the data over Bluetooth as fast as possible.

from espruino.

mariusGundersen avatar mariusGundersen commented on June 16, 2024

You could have a look at this example code, it used the Bangle but should work with the Puck as well: https://www.espruino.com/Bangle.js+Data+Streaming

from espruino.

gfwilliams avatar gfwilliams commented on June 16, 2024

Just to add, in the example I send the data as 16 bit values, but if you were able to do with just 8 bits (losing a bit of precision) that would halve the amount of data you needed to send and so would make life a lot easier.

from espruino.

mihir-chauhan avatar mihir-chauhan commented on June 16, 2024

Thank you @mariusGundersen and @gfwilliams for your input. I will try these out and let you know! Appreciate your help.
Edit: closing issue for now

from espruino.

mihir-chauhan avatar mihir-chauhan commented on June 16, 2024

Also for others who may stumble upon this...I found out after reading the datasheets of the accelerometer and digging into the Espruino code for acceleration on the puck and it seems to be that the Puck's accelerometer is being put into low-power consumption mode which has a max polling rate of only 52Hz, but by doing the following two lines after Puck.accelOn(interval):

    Puck.accelOn(1660);
    Puck.accelWr('0x15', '0x00');
    Puck.accelWr('0x16', '0x00');

It should put the accelerometer chip into "high-performance operating mode enabled" which can allow up to 6.66kHz, but the max the puck can handle (based on documentation) is 1.66Hz. Note that battery consumption will be more, however.

I believe this (setting accel/gyro to low power) happens here in the Espruino code:

unsigned char buf[2];
buf[0] = 0x15; buf[1]=0x10; // CTRL6-C - XL_HM_MODE=1, low power accelerometer
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);
buf[0] = 0x16; buf[1]=0x80; // CTRL6-C - G_HM_MODE=1, low power gyro
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);
buf[0] = 0x18; buf[1]=0x38; // CTRL9_XL Acc X, Y, Z axes enabled
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);
buf[0] = 0x10; buf[1]=reg | 0b00001011; // CTRL1_XL Accelerometer, +-4g, 50Hz AA filter
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);
buf[0] = 0x11; buf[1]=gyro ? reg : 0; // CTRL2_G Gyro, 250 dps, no 125dps limit
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);
buf[0] = 0x12; buf[1]=0x44; // CTRL3_C, BDU, irq active high, push pull, auto-inc
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);
buf[0] = 0x0D; buf[1]=3; // INT1_CTRL - Gyro/accel data ready IRQ
jsi2cWrite(&i2cAccel, ACCEL_ADDR, 2, buf, true);

from espruino.

mihir-chauhan avatar mihir-chauhan commented on June 16, 2024

Yes that would be great because in low power mode, as per the accelerometer/gyro datasheet it will only go up to 50Hz, which was what I was originally receiving even if I did Puck.accelOn(1660);. Thanks

from espruino.

gfwilliams avatar gfwilliams commented on June 16, 2024

I did have a quick try and:

n=0;
Puck.on("accel", ()=>{"jit" n++});
setInterval(function() {
  console.log(n);
  n=0;
},1000);
Puck.accelOn(208)

With firmware 2v17 it does give you 208Hz as expected, but for me any higher and it tops out at ~350Hz even at very high sample rates. Setting the register values as you have done had no effect for me.

Looking again at Table 52. Accelerometer ODR register setting and the one for Gyro it's actually fine as it was. It's saying that actually with that low power flag set it'll automatically set the correct operation mode depending on what frequency is requested.

Digging into it further, with it topping out at ~350Hz, around 80% of the time is spent in the accel_read routine which literally does nothing except read the data via I2C from the accelerometer, so about the only way to actually make it go faster would be to switch to using hardware I2C (currently we use software)

I've had a quick play around and have swapped it to hardware I2C, and that gets us to ~740Hz with only about 25% of the time spent on I2C, so it's definitely an improvement, but it's still not 1kHz - and I'm not sure if it's worth putting that code in as some users will be upset that the only available hardware I2C device disappears if they use the accelerometer. I've pushed it as a PUCKJS_HW_I2C_ACCEL branch though.

Potentially it could be added conditionally - if the poll rate is above 50Hz it starts using hardware I2C or something like that...

from espruino.

mihir-chauhan avatar mihir-chauhan commented on June 16, 2024

The 740Hz is a great improvement, I will try out the hardware I2C. One question I had is if I was storing n amount of the data in a list and then sending all the data through Bluetooth when it was full, would the Bluetooth send function be "blocking" in the sense that I won't be able to handle any of the new data during the send time period and lose that data? Or would there be a way to still store the data while sending through Bluetooth. Thanks for your help

from espruino.

gfwilliams avatar gfwilliams commented on June 16, 2024

If you use Bluetooth.write (with the UART) then the function only blocks when the output buffer is full, otherwise it returns right away. The output buffer is around 1kB I think so even if you just do Bluetooth.write with the data as it comes in (without worrying about buffering) as I'd done in #2349 (comment) you should be fine.

from espruino.

mihir-chauhan avatar mihir-chauhan commented on June 16, 2024

Thanks. When I try to build on WSL (Windows Subsystem for Linux), I am able to get bootloader_espruino_2v17_puckjs.elf and bootloader_espruino_2v17_puckjs.hex. I am not sure what exactly to do in order to package these as it says to upload a ZIP for nRF52 boards. Also, what are all the parameters and respective values I need in the following command line action?: nrfutil pkg generate --application bootloader_espruino_2v17_puckjs.hex puckjs_bootloader.zip, such as hardware version, etc?

from espruino.

gfwilliams avatar gfwilliams commented on June 16, 2024

Hi - you don't need to flash the bootloader firmware - I'm not sure quite how you ended up with only that built.

You could try DFU_UPDATE_BUILD=1 BOARD=PUCKJS RELEASE=1 make and that will automatically spit out a DFU zip for the application that you can then use with the normal 'DFU' app on iOS/Android.

However, GitHub automatically builds the firmware if github actions is enabled (it is on the main repo). That used to be only for the 'master' branch, but I've just enabled it for all new branches, so you should now be able to download via:

https://github.com/espruino/Espruino/actions?query=branch%3APUCKJS_HW_I2C_ACCEL

For instance in https://github.com/espruino/Espruino/actions/runs/4784020729 scroll right down to Artefacts and click PUCKJS and you should get the DFU zip built for you.

from espruino.

mihir-chauhan avatar mihir-chauhan commented on June 16, 2024

Thanks for your help @gfwilliams, I was able to update the firmware through the iOS app (Web IDE and other Web Bluetooth Secure DFU had error at last step). Just FYI: I am able to get a max of 833Hz when there is just the counter, but when I do the Bluetooth.write((new Int16Array([a.acc.x,a.acc.y,a.acc.z,a.gyro.x,a.gyro.y,a.gyro.z])).buffer); it drops down to 348Hz.

from espruino.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.