Incorrect documentation of mbl_mw_dataprocessor_multi_comparator_create() - Float handled as UInt8
Hey there, wanted to report what I believe to be an issue. I am using the most updated firmware on my MetaMotionR, using the swift API wrapper. Specifically, I use the .comparatorCreate command (calls mbl_mw_dataprocessor_multi_comparator_create() in C++)
I set up a comparator to trigger when a timer has fired 538 times with this code:
cycleCounter.comparatorCreate(op: MBL_MW_COMPARATOR_OP_EQ, mode: MBL_MW_COMPARATOR_MODE_ABSOLUTE, references: [Float(536)]).continueOnSuccessWith { monitor in
However, this comparator fires around 26 cycles, which happens to be: 536 - (255*2) = 26
Another comparator is set to fire after 596 cycles. In practice, it fires after 86 cycles: 596 - (255*2) = 86
In the C++ documentation for mbl_mw_dataprocessor_multi_comparator_create(),
METAWEAR_API int32_t mbl_mw_dataprocessor_multi_comparator_create (
MblMwDataSignal * source,
MblMwComparatorOperation op,
MblMwComparatorMode mode,
float references[],
uint8_t references_length,
void * context,
MblMwFnDataProcessor processor_created )
Setting the float: references[] value to anything above 255 loops the value back to 0.
I believe the Float inside this call is being treated as a UInt8, and not a float.
Comments
Two things.
1. Post your code so I can make sure its correct.
2. Look at the CPP code to check that its a Uint8 and not a Float (can you step through the code and check with a debugger)?
Thanks Laura - really appreciate the time you give to everyone on this forum.
(1) Here's a simplified version of the code, I've confirmed the problem still exists (granted, I reduced the loop period to 1000ms for expedition)
(2) This is my first time working with C++, so take the following with a grain of salt:
My code enters switch case 1 of dataprocessor_config.cpp (line 238), when I'd expect it to enter case 4 instead. I suspect this may be the problem.
I am guessing this code finds the lowest bit-size int type it can use for the given input, then assigns the value. The SCALE_MULTI_COMP_REFERENCE function (line 217, dataprocessor_config.cpp) is where I believe there is some faulty logic - the float is preserved through. Not sure what the issue could be here...
The task interface:
It clearly shows that references is [Float] type. Only the count is UInt8.
I went further into the CPP lib:
Again the reference is Float type.
What do you fire the comparator on?
Alright. Dug some more and ran your code (a version of anyways).
Everything ends up typecasted to:
Which is unit8. You are right it's a mistake. You have to chain counters back to back in up to 255 increments to count higher numbers.
I guess it must be a limitation of the chip in the old MetaWear boards and it's always stayed that way. I will see about changing the API call from float to uint8 in the next release.
Hey @Ben_R
I had more time to look this weekend and actually it's not a mistake at all.
If you see in the CPP lib:
The reference is type-casted based on the source size.
You should never chain a timer with a comparator. You should chain a counter and a comparator instead.
So basically there is no bug in the APIs.
Very interesting @Laura, thanks for the details. I currently have a timer that iterates a counter and checks a comparator. Would a comparator fire asynchronously, even if it is called outside of the timer? This is likely a fundamental misunderstanding on my part.
Yes, it can be used with a sensor data signal directly.
PS: My bad for not seeing that earlier.