Numerical Issues unpacking binary data string

5 views (last 30 days)
Hi,
Iam using the "Packet Input" block to receive data from an Arduinoa Due via serial connection. The device sends a binary data packet consisting of 13 bytes, where the first byte is a header and the other 12bytes represent 3 float values of 4bytes each.
I am using the following matlab function inside a matlab function block to reorder the 12 bytes and compose the 3 single values (single values are equivalent to float values here). Afterwards I cast this single to a double to work with it:
function singleV = uint8ToSingle(uintArray)
% initilize some variable to avoid matching size errors
singleV = zeros(1,3);
uintArray_1 = zeros(1,4);
uintarray_2 = zeros(1,4);
uintarray_3 = zeros(1,4);
% split the 12bytes uint8 data array into the 4byte arrays
uintArray_1 = uintArray(1:4);
uintArray_2 = uintArray(5:8);
uintArray_3 = uintArray(9:12);
% cast the 4 uint8 values to one single value each
uint8Value_1 = typecast(uint8(uintArray_1),'single');
uint8Value_2 = typecast(uint8(uintArray_2),'single');
uint8Value_3 = typecast(uint8(uintArray_3),'single');
% cast the single value to double values
singleV_1 = double(uint8Value_1);
singleV_2 = double(uint8Value_2);
singleV_3 = double(uint8Value_3);
%combine the 3 values into one array
singleV = [singleV_1,singleV_2,singleV_3];
A simulink example is attached to this post.
Now to the problem: This algorithm seems to be working fine for almost all the time, but sometimes the numerical value I am extracting explodes from a range of ~[-2 , 2] to something in the order of >10^10, which causes problems for the rest of the program:
when you zoom in:
when you zoom out:
Does anyone know how to "remove the outliers" in real time or how to handle this problem otherwise?
Thanks in advance.
Best regards,
Max

Accepted Answer

Jan Houska
Jan Houska on 20 Aug 2021
Hi Max,
first, you may be missing a very useful feature of the Packet Input block that allows it to output the signals directly as the data types you need. This is done using the Block Output Data Types parameter. Currently, you are likely using '13*uint8' to get a vector of 13 bytes that you later convert by the MATLAB function. Instead, you can use {'uint8', '3*single'} and the block will now have two data output ports, the first one returning the first byte and the second one returning the three single values as a vector. This feature should allow you to eliminate the MATLAB function completely. And, if you prefer to have three separate ouput ports for each of the single values, you can use {'uint8', 'single', 'single', 'single'} .
As to the outliers, these may be caused by an undetected error in the received data or by converting incomplete data. So they actually may be eliminated or reduced by using the built-in conversion present in the Packet Input block. If they are not, the solution depends on what you want to do with such an outlier value. E.g., if you are fine with limiting it to the range -2 to 2, the Saturation block will do that. If you want some other handling, like replacing it with the value read in the previous step, this can be also done, but will require several blocks to do that.
Good Luck, Jan
  1 Comment
Maximilian Becker
Maximilian Becker on 23 Aug 2021
Edited: Maximilian Becker on 23 Aug 2021
Hello Jan,
and yet thanks again for your answer! I feel obliged to atleast buy you a coffee some time.. The feature to output single values directly was indeed useful and reduced the orrcurence of these errors by a lot. But sadly it does not solve my problem completely which is why I need some error handling. I already thought about implementing a saturation but fear that this might harm my system's dynamics if it tries to track a step from -2 to 2 in one time step.
For your other idea about replacing false values I yet have no solution to this. A suitable algorithm should consist of two parts: 1) detect the false value and 2) replace the false value with the last resonable one. About the detection I thought about comparing each value with the average of the last 10 values or so, but this will be corrupted if at some point there was a false value and I do not know how to actually remove such a false value from my data stream.
Do you have something in mind, that could do this?

Sign in to comment.

More Answers (1)

Jan Houska
Jan Houska on 24 Aug 2021
Hi Max,
saturation is by far the simplest method, although I understand it has its limitations. The next simplest method is to repeat the previous value if the current value is out of range. Please find attached a simple model that does this using an Enabled Subsystem that passes its input to the output when enabled and holds its output when disabled. The enable signal is generated according to the requested condition, this time the signal being in the range -2 to 2.
Good Luck, Jan
  1 Comment
Maximilian Becker
Maximilian Becker on 24 Aug 2021
Thank you very much for your help, this did the trick for me!
I don't know what I would do without your wisdom!

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!