Serial communication with simulink - matlab

I'm trying to send and receive data through a serial port using simulink (matlab 7.1) and d-space. The values I want to send and receive are doubles. Unfortunately for me the send and receive blocks use uint8 values. My question is how can I convert doubles into an array of uint8 values and vice versa? Are there simulink blocks for this or should I use embedded matlab functions?

Use the aptly named Data Type Conversion block, which does just that.
EDIT following discussion in the comments
Regarding scaling, here's a snapshot of something I did a long time ago. It's using CAN rather than serial, but the principle is the same. Here, it's slightly easier in that the signals are always positive, so I don't have to worry about scaling a negative number. 65535 is the max value for a uint16, and I would do the reverse scaling on the receiving end. When converting to uint16 (or uint8 as in your case, it automatically rounds the value, and you can specify that behaviour in the block mask).

There are pack and unpack blocks in simulink, search for them in simulink library browser. You could need som additional product, not sure which.

Related

Simulink data types

I'm reading an IMU on the arduino board with a s-function block in simulink by double or single data types though I just need 2 decimals precision as ("xyz.ab").I want to improve the performance with changing data types and wonder that;
is there a way to decrease the precision to 2 decimals in s-function block or by adding/using any other conversion blocks/codes in the simulink aside from using fixed-point tool?
For true fixed point transfer, fixed-point toolbox is the most general answer, as stated in Phil's comment.
However, to avoid toolbox use, you could also devise your own fix-point integer format and add a block that takes a floating point input and convert it into an integer format (and vice versa on the output).
E.g. If you know the range is 327.68 < var < 327.67 you could just define your float as an int16 divided by 10. In a matlab function block you would then just say
y=int16(u*100.0);
to convert the input to the S-function.
On the output it would be a reversal
y=double(u)/100.0;
(Eml/matlab function code can be avoided by using multiply, divide and convert blocks.)
However, be mindful of the bits available and that the scaling (*,/) operations is done on the floating point rather than the integer.
2^(nrOfBits-1)-1 shows you what range you can represent including signeage. For unsigned types uint8/16/32 the range is 2^(nrOfBits)-1. Then you use the scaling to fit the representable bit into your used floating point range. The scaled range divided by 2^nrOfBits will tell you what the resolution will be (how large are the steps).
You will need to scale the variables correspondingly on the Arduino side as well when you go to an integer interface of this type. (I'm assuming you have access to that code - if not it'd be hard to use any other interface than what is already provided)
Note that the intXX(doubleVar*scale) will always truncate the values to integer. If you need proper rounding you should also include the round function, e.g.:
int16(round(doubleVar*scale));
You don't need to use a base 10 scale, any scaling and offsets can be used, but it's easier to make out numbers manually if you keep to base 10 (i.e. 0.1 10.0 100.0 1000.0 etc.).
As a final note, if the Arduino code interface is floating point (single/double) and can't be changed to integer type; you will not get any speedup from rounding decimals since the full floating point is what will be is transferred anyway. Even if you do manage to reduce the data a bit using integers I suspect this might not give a huge speedup unless you transfer large amounts of data. The interface code will have a comparatively large overhead anyway.
Good luck with your project!

Transfer Value via UDP between Simulink/Labview

I'm working on a project that requires a value be passed in real-time between Matlab's Simulink and Labview on networked systems (currently running Matlab 2010b and Labview 7.0). I've been trying to do this with UDP Send/Receive functions in either program, however Labview only seems to deal in Strings with UDP/TCP-IP. Simulink only reads int/double values from UDP ports.
Is there a way for me to convert these values AFTER the read-in operation, or otherwise get around the type restriction? Any advice (or alternative ways to pass a value between the two programs) would really be appreciated. Unfortunate, due to hardware restrictions, I'm stuck with these program versions.
Thanks!
The TCP/UDP functions in LV use strings because it's a convenient way to represent an array of bytes, which is what a TCP stream basically is. You can take the data and convert it so that it's usable. Assuming Simulink encodes values the same way (simple binary for ints, IEEE754 representation for floats), then you can simply use the type cast or flatten to/unflatten from string functions to convert the data. You might need to change the order of the bytes to account for endianess.
You can look at the TCP examples in LV and the documentation on flattened data to understand more on how this works.
As a side point, UDP is lossy and is mainly suitable if you need to broadcast or get data quickly, like when streaming video. If the data is important, you should use TCP.

Change default numeric type to float in matlab

Matlab by default uses double as the numeric type. I am training a GMM and running out of memory, so I want to change the default numeric type to float which takes half the memory as double. Is it possible?
I know that single(A) converts a double precision element A to single precision but we need to allocate double precision storage for A first which runs out of memory. Also, I cannot use single() around all my matrix allocation as various functions in many toolboxes are called which I cannot change manually.
So is there a way that calling zeros(n) will allocate a matrix of floats by default instead of double ?
No, there is currently no way to change the default numeric type to float / single. See these informative posts on MathWorks forums:
http://www.mathworks.com/matlabcentral/answers/8727-single-precision-by-default-lots-of-auxiliary-variables-to-cast
http://www.mathworks.com/matlabcentral/answers/9591-is-there-a-way-to-change-matlab-defaults-so-that-all-workspace-floating-point-values-to-be-stored-i
Also, quoting John D'Errico on the first link I referenced - a formidable and legendary MATLAB expert:
This is not possible in MATLAB. Anyway, it is rarely a good idea to work in single. It is actually slower in many cases anyway. The memory saved is hardly worth it compared to the risk of the loss in precision. If you absolutely must, use single on only the largest arrays.
As such, you should probably consider reformulating your algorithm if you are using so much memory. If you are solving linear systems that are quite large and there are many zero coefficients, consider using sparse to reduce your memory requirements.
Besides which, doing this would be dangerous because there may be functions in other toolboxes that rely on the fact that double type allocation of matrices is assumed and spontaneously changing these to single may have unintended consequences.
As #rayryeng said, there's no way in MATLAB to "change the default numeric type" to single. I'm not even entirely sure what that would mean.
However, you asked a specific question as well:
So is there a way that calling zeros(n) will allocate a matrix of floats by default instead of double?
Yes - you can use zeros(n, 'single'). That will give you an array of zeros of type single. zeros(n) is just a shorthand for zeros(n, 'double'), and you can ask for any other numeric type you want as well, such as uint8 or int64. The other array creation functions such as ones, rand, randn, NaN, inf, and eye support similar syntaxes.
Note that operations carried out on arrays of single type may not always return outputs of type single (so you may need to subsequently cast them to single), and they may use intermediate arrays that are not of type single (so you may not always get all the memory advantages you might hope for). For example, many functions in Image Processing Toolbox will accept inputs of type single, but will then internally convert to double in order to carry out the operations. The functions from Statistics Toolbox to fit GM models do appear to accept inputs of type single, but I don't know what they do internally.

Simulink: Bit extraction from 1-Byte Hex

I'm relatively new to Simulink and I am looking for a possibility to extract 1-3 specific bits from one byte.
As far as I know the input format (bin, dec, hex) of the constant is irrelevant for the following!? But how can I say that the constant "1234" is hex and not dec?
In my model I use the "Constant Block" as my source (will be parametrised by a MATLAB variable which comes from a m-file).
A further processing with the "Extract Bits Block" causes an error on incompatible data types.
Can someone help me to deal with this issue?
Greets, poeschlorn
You should probably do the conversion hex->dec in your .m initialization file and use this value in Simulink.
Maybe this is not the most elegant solution, but I converted my input to decimal and then created a BCD representation of it via OR and AND logic blocks for further use.
If you have the Communications Toolbox/Blockset then you can use the Integer to Bit Converter block to do a conversion to a vector of binary digits then just extract the "bits" that you want. The Bit to Integer Converter block will do the reverse transformation.
If you don't have the Communicatins Blockset then it wouldn't be hard to do a similar thing to this using a plain MATLAB Function block.

Simulink: type consistency errors

Using this Simulink model file as a reference, I'm trying to figure out the two following errors:
alt text http://imagebin.ca/img/dSV8YO.png
alt text http://imagebin.ca/img/OXDf0v.png
I have no idea what has gone wrong with the data type consistency/conversion problems. Do you know what the error messages mean exactly in the context of a model? It would be great to get an interpretation of the problem to solve it. Thanks in advance.
Is the block 'Inner Loop/e^(-s)' driving the block 'Inner Loop/Sum'? It looks like the 'e^(-s)' block is trying to set the Sum block to be double, but the Sum block is already set to some other data type. I'm not sure why that's happening, but here's a snippet from the help for the Sum block documentation,
Inherit: Inherit via internal rule
Simulink chooses a combination of output scaling and data type that requires the smallest amount of memory consistent with accommodating the calculated output range and maintaining the output precision of the block and with the word size of the targeted hardware implementation specified for the model. If the Device type parameter on the Hardware Implementation configuration parameters pane is set to ASIC/FPGA, Simulink software chooses the output data type without regard to hardware constraints. Otherwise, Simulink software chooses the smallest available hardware data type capable of meeting the range and precision constraints. For example, if the block multiplies an input of type int8 by a gain of int16 and ASIC/FPGA is specified as the targeted hardware type, the output data type is sfix24. If Unspecified (assume 32-bit Generic), i.e., a generic 32-bit microprocessor, is specified as the target hardware, the output data type is int32. If none of the word lengths provided by the target microprocessor can accommodate the output range, Simulink software displays an error message in the Simulation Diagnostics Viewer.
You can try forcing the output data type to be double, if that's what you really want, or you can try putting a Data Type Conversion block in front of the Sum block. One other thing that can help is to try turning on Port Data Types from the Format menu. It should show you all the propagated data types when the error happens.