Skip to content

Add acceleromter range and rate acccessors (in progress). #266

Closed
carlosperate wants to merge 2 commits into
bbcmicrobit:masterfrom
carlosperate:acc_rate_range
Closed

Add acceleromter range and rate acccessors (in progress). #266
carlosperate wants to merge 2 commits into
bbcmicrobit:masterfrom
carlosperate:acc_rate_range

Conversation

@carlosperate

@carlosperate carlosperate commented May 4, 2016

Copy link
Copy Markdown
Contributor

Didn't really get the chance last night, but I found some time this morning to play with this. I've encountered something a bit odd with my current implementation, so I'd though I'd create the PR for quick review (it is rather simple) in case I'm not setting something correctly.

When I set the range and rate it seems like it is heavily rounding up the final calculation. So to set a sampling frequency of 50hz, I need to set the value 45 or 46, anything higher sets it to 100hz. Similar thing happens with the range.

I'll see if I can replicate tonight the same behaviour using a simple Cpp program with just the DAL.

Resolves #264

Comment thread docs/accelerometer.rst
.. py:function:: set_range()

Set the accelerometer sensitivity range, in Hz.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably add more info about what changing the range actually does.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, include the possible values to set.

@dpgeorge

dpgeorge commented May 4, 2016

Copy link
Copy Markdown
Member

When I set the range and rate it seems like it is heavily rounding up the final calculation.

I think the accelerometer can only do specific rates/periods: 1.25ms, 2.5ms, 5ms, 10ms, 20ms, 80ms, 160ms, 640ms.

Also it's restricted to 2, 4 or 8 g's.

@carlosperate

carlosperate commented May 4, 2016

Copy link
Copy Markdown
Contributor Author

Yes, I meant when trying to set an exact accepted value, so let's say 20ms/50Hz, in that case it seems to actually set it to 10ms/100Hz, I have to do microbit.accelerometer.set_rate(45) for it to actually resolve to 50Hz. Same thing with the g sensitivity.

I had a quick look at the DAL code, but I didn't have enough time before work to actually think through it to ensure it works as I expected. I assume that using the ::setPeriod(20) would result in setting that exact value, so I need to find out if somehow I'm sending the wrong value to the DAL api, or if that works slightly differently than what I expected.


mp_obj_t microbit_accelerometer_set_range(mp_obj_t self_in, mp_int_t g) {
microbit_accelerometer_obj_t *self = (microbit_accelerometer_obj_t*)self_in;
return mp_obj_new_int(self->accelerometer->setRange(g));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to change this to return mp_const_none;

@carlosperate

Copy link
Copy Markdown
Contributor Author

The using the DAL on a plain Cpp application sworks as expected on version 2. I tried also using version 1.4.15 and I've had some issues getting the program to create a microbit-combined.hex file. Had to convert my main() application to the old app_main(), and while it compiled fined, it only produced the microbit.hex file (and after loading that one nothing really happens). Is there any old documentation somewhere where I could check what exactly I might need to do?

@carlosperate

Copy link
Copy Markdown
Contributor Author

Okay, so I was finally able to spend a bit more time on this. So I went back and fixed the issue I had building the C++ program using the 1.4.15 version of the DAL, and as expected, that works well.

I looked at the data being sent to the DAL accelerometer instance and noticed that it was basically the user input >> 1 | 1, so I started looking around and noticed that's how the mp objects for integers are formed. Looks like the function arguments in the line before were passed as mp_obj_t instead of mp_int_t

mp_obj_t microbit_accelerometer_set_rate(mp_obj_t self_in, mp_int_t hz)

Is that always the case? I saw a few cases around using mp_int_t and I just assumed the data would be formated as integers. Is there any information online that describes some or any of this stuff? Googling I only found a rather small entry in the micropython wiki about creating new modules.

Anyway, it is working now, however because we are doing integer arithmetic with the frequency conversion to a period value in miliseconds, which is then converted in the DAL to microseconds, we do lose some accuracy. For the rate values configured in the accelerometer, we will read them as:

const MMA8653SampleRateConfig MMA8653SampleRate[MMA8653_SAMPLE_RATES] = {
    {1250,      0x00},       // Read as 1000Hz, supposed to be 800Hz
    {2500,      0x08},       // Read as 500Hz, supposed to be 400Hz
    {5000,      0x10},       // Read as 200Hz, correct
    {10000,     0x18},       // Read as 100Hz, correct
    {20000,     0x20},       // Read as 50Hz, correct
    {80000,     0x28},       // Read as 12Hz, supposed to be 12.5Hz
    {160000,    0x30},       // Read as 6Hz, supposed to be 6.25Hz
    {640000,    0x38}        // Read as 1Hz, supposed to be 1.5625Hz
};

Apart from that, if the user tries to set the rate to 0Hz, it will be configure to the 1250 us / 800Hz value.

@carlosperate

Copy link
Copy Markdown
Contributor Author

Apart from the extra info needed in the documentation, is the implementation correct based on what you had in mind with #264?

@markshannon

Copy link
Copy Markdown
Collaborator

OOI why is the API in terms of rate, rather than period?
Given that only a fixed set of rate/periods are available would it make sense to make a set of symbolic constants available?

@carlosperate

Copy link
Copy Markdown
Contributor Author

OOI why is the API in terms of rate, rather than period?

I was implementing the suggested API from #264 , but period in ms or us would be easier to pass through.

Given that only a fixed set of rate/periods are available would it make sense to make a set of symbolic constants available?

I'm not a big fan of having constants for these, but maybe we should return the configured value? So (using still rate) it would look like this:

> microbit.accelerometer.set_rate(10)
12

@carlosperate

Copy link
Copy Markdown
Contributor Author

@dpgeorge any feedback on this?

@dpgeorge

dpgeorge commented Jun 3, 2016

Copy link
Copy Markdown
Member

@carlosperate it's very clean.

But now that we have the discussion in #296 about setting/getting the I2C frequency, I realise that configuring the accelerometer is similar, and maybe it should use an init() method to set the rate and range?

@carlosperate

Copy link
Copy Markdown
Contributor Author

Well, the accelerometer object gets constructed by the DAL, so it would be a bit odd to have an init method if we are able to successfully execute any of the other methods without calling it first, no?

I guess this is already the case for UART, SPI, and now I2C, but those are internal peripherals which, generally speaking, are a bit more advanced and in most cases have to be "set up" before use. From my perspective the display, buttons, accelerometer, and compass are more like "pre-packaged" components, for which we are facilitating their use, but are ready out of the box. Having a init function suggests that they need to go through a process of initialisation, that we are completely bypassing in most situations, and I would personally find that slightly confusing.

On the other hand having that init would continue a general convention, which could be good. So I don't mind that much either way.

Which way should we go?

Comment thread docs/accelerometer.rst Outdated

Get the accelerometer sensitivity range, in g's.

.. py:function:: set_range()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be set_range(value)

Comment thread docs/accelerometer.rst Outdated

Get the accelerometer samping rate, in Hz.

.. py:function:: set_rate()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove the get/set rate methods, there is no such functionality in MakeCode

To save memory we need to keep the additions to a minimum. The
sampling rate is not exposed in MakeCode and has never been
requested yet in MakeCode nor MicroPython.

set_range is available in MakeCode and has been requested in
MicroPython to be able to create equivalent programmes and lessons.
get_range has not been requested, is not available in MakeCode,
and there is not a lot of cases where it would be useful, so it's
been also removed to save memory.
@carlosperate

carlosperate commented Sep 23, 2021

Copy link
Copy Markdown
Contributor Author

Rebased and updated to remove the rate methods, and in the end I also removed get_range to save memory.

@dpgeorge

Copy link
Copy Markdown
Member

Squashed and merged in 3148254

@dpgeorge dpgeorge closed this Oct 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow to configure range (and rate?) of accelerometer

3 participants