Concatenate 3 bytes array of real time serial data into single precision

26 views (last 30 days)
Mariam Hassib
Mariam Hassib on 27 Jun 2014
Answered: Andreas on 9 Jan 2015
Hi all,
So in a nutshell. I have a continuous stream of data from 4 sensors through one USB (i did not build the hardware so I cannot make any changes there). I have 20 bytes packets, 4 start bytes that I don't need, a 4 byte time stamp, then 3x4 bytes of data (3 bytes from each sensor).
I use currentBuffer=fread(s1,20)
I then manually get the 3x4 bytes of data, e.g.: sensor1[ currentBuffer(9) currentBuffer(10) currentBuffer(11)]
Now I want to convert this 3 byte array into one single precision number...
Can anyone please help me with this??
Thank you

Answers (2)

James Tursa
James Tursa on 27 Jun 2014
Edited: James Tursa on 27 Jun 2014
How is the data/number formatted in the 3-bytes? Is it a 24-bit signed integer using 2's complement encoding? Is it a 24-bit unsigned integer? Is it some type of floating point format?
You might see this related thread for converting 24-bit 2's complement strings:
E.g., if you have a 24-bit 2's complement integer to deal with, then basically you simply need to sign-extend the 24-bits into an equivalent 32-bit 2's complement integer format, then typecast & type conversion will finish the job.
But first we need to know what format the 3x4 bytes are in.
Also, note that since you don't specify the precision with fread, it will be doing 'uint8=>double' by default ... i.e., converting all of the uint8 bytes to double. My guess is you probably don't really want to do that if you have downstream byte manipulation to do. So I would suggest you use '*uint8' or '*int8' explicitly instead.
James Tursa
James Tursa on 9 Jul 2014
'int8' is listed as an acceptable PRECISION string in the help doc, so I don't understand the error. However, maybe back off and try a more brute force approach just to see if we can recover the original bit pattern:
currentBuffer = fread(s1,20); % this apparently already works for you
currentBuffer = typecast(uint8(currentBuffer),'int8'); % brute force

Sign in to comment.

Andreas on 9 Jan 2015
Hey, I have the same problem right now and I'm interested in how you solved it in the end.
The data I get is three bytes each (24 bit two's complement). The ADC has 8 channels, so after every fread I get 24 bytes (as a row vector). It is stored in a Nx24 array, where N is the number of samples. So the data for channel 1 is stored in adc(:,1:3) (1 is MSB; 3 is LSB), channel 2 is stored adc(:,4:6) and so on. I read the data with
The way I do it now is very cumbersome and takes a lot of time to process.
for i=1:8
hex = [dec2hex(adc(:,1+(i-1)*3)) dec2hex(adc(:,2+(i-1)*3)) dec2hex(adc(:,3+(i-1)*3))];
bin = dec2bin(hex2dec(hex),24);
bin32 = [bin(:,[1 1 1 1 1 1 1 1]) bin ]; % add 8 bits depending on sign -> 32bits
val = double(typecast(uint32(bin2dec(bin32)),'int32'));
% do something with val
where i is the index for the current channel. I couldn't figure out a way to do it for all channels simultaneously.
This proposed solution does not work for me. For example
k = typecast([int8(-(adc(1,1)<0)) adc(1,1:3)],'int32');
where adc(1,1:3) = [0,9,10]. This should result in 154, but I get 168361984. After swapbytes(k) I get 2314. Also, when I try to compute this for the whole dataset
k = typecast([int8(-(adc(:,1)<0)) adc(:,1:3)],'int32');
I get
Error using typecast. The first input argument must be a vector.
Can someone help me out here? Thanks, Andy

Community Treasure Hunt

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

Start Hunting!