reading int16 data in matlab - matlab

I read this set of hex values from an accelerometer datalogging:
35AC,2889,1899,0C4A,058B,FD46,F620,F001,EE44,EF08,EF46,F750,007F,0814,1369,21F3,34F0,45CE,5992,6D05,7C12,7FEF,7FF8,7FF8,7FF8,7FF8,7FD9,7F27,74A7,67D8,5826,468F,3621,2573,1326,0441,F88F,F1BF,F082,EADB,EAEE,EE04,F190,F89E,01F5,0B0C,155A,2721,3A20,48DC,5985,676A,721E,7C20,7FF8,7FEE,7F1B,
It should somehow draw a sinusoide curve, but I could not find the right import method for signed int16 and the curve jumps from 0 to 65535.
Could you please help me?
I have tried sscanf(...,'%4x')

The sscanf format for a signed hex int16 is just '%4i'. Unfortunately it expects that hex values will begin with 0x, which yours clearly don't. One possibility is for you to scan it in as you are, and then manually convert it to a signed int16. One possible way of doing this would be the following:
input = sscanf(...,'%4x');
input16 = typecast(uint16(input),'int16');
The values are being read in as a uint32 and automatically converted to double by the sscanf function. So we convert it to a uint16, then typecast it to a 16-bit int (note that just using int16(input) doesn't work, as it doesn't convert values over INT16_MAX to negative values).

string = '35AC,2889,1899,0C4A,058B,FD46,F620,F001,EE44,EF08,EF46,F750,007F,0814,1369,21F3,34F0,45CE,5992,6D05,7C12,7FEF,7FF8,7FF8,7FF8,7FF8,7FD9,7F27,74A7,67D8,5826,468F,3621,2573,1326,0441,F88F,F1BF,F082,EADB,EAEE,EE04,F190,F89E,01F5,0B0C,155A,2721,3A20,48DC,5985,676A,721E,7C20,7FF8,7FEE,7F1B';
%// Your data as a string
string = [string ',']; %// add ending comma to reshape into groups of five chars
strings = reshape(string,5,[]).';
strings = strings(:,1:4); %'// each row is 4 chars representing a hex number
numbers = hex2dec(strings); %// convert each row to a number
ind = numbers>=32768;
numbers(ind) = numbers(ind)-65535; %// get rid of jumps
plot(numbers)

thank a lot
Both previous answer were there too.
sscanf alternative assumed to be faster.

Related

Apply MATLAB sscanf to convert from hex to dec for multiple elements in a column vector

In MATLAB, I'm trying to convert hex (2’s complement) to decimal for a column vector using the sscanf function. While I have successfully converted using the hex2dec function, however I am unsuccessful converting multiple elements (hex values) in a column vector with sscanf. Yet when I have only one element (hex value) in the column vector the hex to dec conversion is successful. How do you convert a column vector with multiple elements (hex values), using sscanf function, to hexadecimal, 2’s complement?
colx = ['FEEE'; 'FFFF'; 'FDDD']
conversion = typecast(uint16(sscanf(colx, '%x')), 'int16')
My output is:
conversion = -1
However the output should be:
conversion = -274
-1
-547
sscanf will linearize the char array into a vector before attempting the conversion.
You need to add some spaces, otherwise it will simply try to convert a big value. Also, the char array should be transposed since Matlab stores arrays in column major order. In your example, what sscanf actually tries to convert is the string FFFEFDEFDEFD which overflows into the maximum value represented by an uint16 (0xFFFF), which itself is the signed integer representation of -1.
Try:
colx2 = [colx' ; repmat(' ',1,size(colx,1))]
conversion = typecast(uint16(sscanf(colx2, '%x')), 'int16')
The result is:
conversion =
-274
-1
-547

Single-precision float to byte array in MATLAB

Say I have the following single-precision floating point number in Matlab
a = single(-2.345)
I would like to represent the number as an array of 4 bytes, following IEEE 754. The correct representation should be
b = [123, 20, 22, 192]
Currently, I am using fread and fwrite to do the conversion, as in
fid = fopen('test.dat','wb')
fwrite(fid,a,'float')
fclose(fid)
fid = fopen('test.dat','rb');
b = fread(fid)'
which well enough, but I suspect there is a much easier and faster way to do the conversion without reading/writing from a file.
There have been a few posts about converting a byte array to a float (such as here), but I'm unsure how to proceed to go in the opposite direction. Any suggestions?
You can use the typecast function to cast between datatypes without changing the underlying data, i.e. reinterpret data using another type. In your case, you will want to cast from single to uint8 (byte) datatype. This is done by
a = single(-2.345);
typecast(a,'uint8')
ans =
123 20 22 192
as required.

How to represent double type number in binary form?

How can I represent double type number in binary form, for example:
dec = 3.14159
to an array consists of its IEEE 754 Double precision binary representation as binaryconvert.com does it
bin = 0100000000001001001000011111100111110000000110111000011001101110
in Matlab? I know there is a similar question, but not for Matlab.
You can do the following:
hexdec = num2hex(dec);
bin = hexToBinaryVector(hexdec);
Example:
hexToBinaryVector(num2hex(pi))
ans =
1100000000001001001000011111101101010100010001000010110100011000
This can be done with typecast(...,'uint8') to get invididual bytes; then fliplr to change byte endianness (at least that's needed on my machine); then converting each byte to binary with dec2base(...,2,8); and finally reshape'ing to a single row:
bin = reshape(dec2base(fliplr(typecast(dec,'uint8')),2,8).',1,[]);

Combine matrix elements into a hexadecimal number on Matlab

For example I have a matrix command = ['01';'03';'0B';'00';'00';'02';'C6';'2F']. I want to combine its elements in a hexadecimal number 01030C000002C62F. I have tried a lot of different methods but haven't figured it out.
So, this is a char array:
A = ['01';'03';'0B';'00';'00';'02';'C6';'2F'];
Convert it to cell, then to string:
B = strjoin(cellstr(A))
01030B000002C62F
Now convert from hexadecimal to decimal:
hex2dec(B)
ans =
7.2914e+16

32 bit hex to 32 bit floating point (IEEE 754) conversion in matlab

How can I change the 32 bit hex-value to a floating point value according to the IEEE 754?
EDIT:
...
data = fread(fid,1,'float32');
disp(data);
...
I get this answer:
4.2950e+009
1.6274e+009
...
But how do I get 32 bit floating point (IEEE 754) numbers?
Based on one of your comments it appears that your hexadecimal values are stored as strings of characters in a file. You first want to read these characters from the file in groups of 8. Depending on the specific format of your file (e.g. each set of 8 characters is on its own line, or they're separated by commas, etc.), you could use functions like FSCANF or TEXTSCAN to do this. For example, if your data file looks like this:
409BFFFF
3B3C0000
85E60000
Then you can read the data into a character array like so:
fid = fopen(fileName,'r'); %# Open the file
data = textscan(fid,'%s'); %# Read the data
charArray = char(data{1}); %# Create a character array
fclose(fid); %# Close the file
Now you need to convert these 32-bit hexadecimal strings to single-precision representations. The easiest way by far is to use the function HEX2DEC to convert the strings to integers (stored as double-precision values), convert them to unsigned 32-bit integers using the function UINT32, then cast the 32-bit integers to single-precision representations using the function TYPECAST. Applying this to the sample data I have above gives these results:
>> values = typecast(uint32(hex2dec(charArray)),'single');
>> fprintf('% 1.42f\n',values); %# Display the values
4.874999523162841800000000000000000000000000
0.002868652343750000000000000000000000000000
-0.000000000000000000000000000000000021629096
You can confirm that these results are correct using this online hexadecimal-to-floating-point converter.
In case anyone is interested, you can do the above type conversion yourself using the function HEX2DEC to first convert the string to an integer representation, then the function BITGET to extract and process the bits for the sign, exponent, and fraction of the single-precision number. For example:
>> a = '409BFFFF'; %# A sample hexadecimal value
>> b = hex2dec(a); %# Convert to an integer
>> sign = bitget(b,32); %# Compute the sign
>> exponent = bitget(b,24:31)*2.^(0:7).'; %'# Compute the exponent
>> fraction = bitget(b,1:23)*2.^(-23:-1).'; %'# Compute the fraction
>> value = (-1)^sign*(1+fraction)*2^(exponent-127); %# Compute the value
>> fprintf('%1.7f\n',value) %# Display the value
4.8749995