Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wants to merge 2 commits into from

Conversation

carlosperate
Copy link
Contributor

@carlosperate carlosperate commented May 4, 2016

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

.. py:function:: set_range()

Set the accelerometer sensitivity range, in Hz.

Copy link
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
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
Copy link
Member

dpgeorge commented May 4, 2016

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
Copy link
Contributor Author

carlosperate commented May 4, 2016

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
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
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
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
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
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
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
Contributor Author

@dpgeorge any feedback on this?

@dpgeorge
Copy link
Member

dpgeorge commented Jun 3, 2016

@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
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?


Get the accelerometer sensitivity range, in g's.

.. py:function:: set_range()
Copy link
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)


Get the accelerometer samping rate, in Hz.

.. py:function:: set_rate()
Copy link
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
Copy link
Contributor Author

carlosperate commented Sep 23, 2021

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

@dpgeorge
Copy link
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