Reading ADC data from MSP430 to Matlab via serial port
6 次查看(过去 30 天)
显示 更早的评论
My situation is
1. external ADC samples from one channel and transmit to Serial port Via Uart and then switches over to second channel to do same and then third.
2. I manage to view data in Hterm and it looked quite fine.
3. I want to plot it live in matlab- I know there are ways to do it but can someone here explain me a basic step by step to achieve my objective?
I have basic idea of what i should be doing
- setup serial communication.
- create array to store uart values
- calculate voltage values
- plot live values
It would be nice if someone points out me for where to look for point 2 and 4 specifically.
19 个评论
Walter Roberson
2022-6-15
Is there a maximum number of samples to be saved? A maximum number at one time? For example, plot the most recent 1024 samples?
Hiril Patel
2022-6-16
Actually I dont have answer to that for following reason
- I haven't yet experimented this circuit on the workbench where i will apply known strain to test my circuit so I don't think I have limit to specific number of samples needed. Lets assume I will be watching matlab data and plot while experimenting so I have not clear answer for this.
Walter Roberson
2022-6-16
编辑:Walter Roberson
2024-7-17
If you do not have a maximum size for the array, then you need to grow the array dynamically, which can kill the performance if you do not plan for it. See for example John's https://www.mathworks.com/matlabcentral/fileexchange/8334-incremental-growth-of-an-array-revisited?s_tid=blogs_rc_4
Walter Roberson
2022-6-16
plotting as data comes in also needs some thought as you do not want to keep creating new graphics objects. I recommend using animatedline(), possibly with the maximum points limit turned on.
Hiril Patel
2022-6-16
ok I understand the memory limitations here. So if I resort to recording the data first and later analyzing it on matlab, still I could not find any example of grouping data coming from serial port in following way( i am not looking for direct answer):
- the data from adc is sampled channel by channel so I am taking data from ads as 1 sample per channel and then proceding to next channel.
- this means that i am trasnferring data to serial port in above mentioned way.
- If i want to record it i first have to seperate data which UART is pushing out as 8 bit(adc samples 24 bit of data for single sample) hence I would have to record 4 byte and sort it into 1 row and then switch to another row to record one more sample ..........
Can you advice me for this question?
Walter Roberson
2022-6-16
Read from each channel. Then
counter = counter + 1;
all_data(:, counter) = samples;
I used columns instead of rows because that is more efficient.
Hiril Patel
2022-6-17
Thank you for the suggestion but I didn't quite understood it well so I have proceeded with following code:
clear all;
clc;
%USB port config
delete(instrfind);
s = serial('COM11','BaudRate',115200,'databits',8,'stopbit',1);
fopen(s);
data = fscanf(s);
adc_data = split(data,"/"); %I have inserted "/" in my microcontroller code to send that at beginning of channel 1 so I can have data seperation in matlab.
%Closing port
fclose(s);
I haven't yet designed loops yet but the problem is how should i convert them into hex values since the split command make a cell to store the data.
Walter Roberson
2022-6-17
Could you show an example of what is being sent? And is it binary or character?
Hiril Patel
2022-6-17
Walter Roberson
2022-6-18
编辑:Walter Roberson
2024-7-17
You have binary, and it looks like you have a different number of bytes at times. You just might be sending a space after each / but that is not clear. If that is / space then it is generally followed by 8 bytes. But sometimes it is only 7 and sometimes it is 9.
You should switch to one of the following schemes:
- Write numbers in character form, either decimal or hexadecimal, with non-number between the entries. Either put newline after each individual number or put newline at the end of a group of samples; or
- Write numbers in binary using a fixed number of bytes per entry, so that you can ask to read a fixed number of bytes with no delimiter; or
- At the beginning of each burst of numbers, write a byte (or two) which is the number of bytes that follow in that packet, with no end of line. The input side reads the size (fixed size) and uses the size to read that many bytes; or
- use a variable length binary stream with a fixed termination byte, with the binary stream having been carefully adjusted so that it never accidentally includes the termination character. For example you might use newline, and everywhere that newline would have been sent as data send 255 0 and everything 255 would have been sent, send 255 255.
Hiril Patel
2022-6-19
ok so I semi followed your advice in a way and put unique delimiters before transaction of each channel;:
channel 1 has delimiter = /A/
channel 2 has delimiter = /B/
channel 3 has delimiter = /C/
and then i used function
data = fscanf(s);
adc_data = split(data,["/A/","/B/","/C/"]);
but now the result comes in 74x1 cell with sequential results. is there any commant to split data in three seperate arrays/files/cell for seperate delimiter?
Hiril Patel
2022-6-21
Ok till now I successfull splitted till each measurements,
clear all;
clc;
%USB port config
delete(instrfind);
s = serial('COM11','BaudRate',115200,'databits',8,'stopbit',1);
%timeonut infinite
s.Timeout = 300;
s.InputBufferSize = 5000;
fopen(s);
% w = s.bytesavailable
data2 = fscanf(s);
adc_data = split(data2,'/A/');
l= strlength(adc_data);
rowsToDelete = strlength(adc_data) ~= 12;
adc_data(rowsToDelete) = [];
CH0 = extractBefore(adc_data,5);
CH1 = extractBetween(adc_data,5,8);
CH2 = extractAfter(adc_data,8);
fclose(s);
But how do I convert these AsCI to numerical values?
Walter Roberson
2022-6-23
Look at https://www.mathworks.com/matlabcentral/answers/uploaded_files/1036145/Capture.JPG in your display of the input data. That's the one that starts
ÿ ù/
Those are binary not character.
You have two choices:
- you can continue to send in binary, and do binary reads using fread() (for serial) or read() (for serialport). If you are not always sending the same number of bytes or if not everything is the same binary data type, then you may need to add some extra bytes to indicate how the following data is to be treated. If you use this fread() binary approach, you do not put any delimiters between values and you do not send newline; OR
- you can switch to sending the numbers as text. If you send as text, put a space between the values and put newline at the end of the line. On the MATLAB end, fscanf() will read the entire line of values, returning a numeric vector.
You only need things like your /A/ or similar if you are sending the channels in inconsistent order. For example if you had a series of devices that generated interrupts when it was ready, and you wanted to send the data in the order received, then there might be reason to tag each value according to the channel it is associated with.
Hiril Patel
2022-6-28
Kk I figured out solution for the whole problem but this include both python and matlab since I am a bit more proficient in it so now i am recording data in csv file in python and later importing it in matlab for furthur calculations.
Thank you million for all these advices they helped me in many ways.
regards
Hiril Patel
Hiril Patel
2022-6-30
Hello again Walter,
can you suggest me what to do with following case, as it is associated with the previous system:
i managed to get those values in matlab and working with calculation but here I am solving Mohr's circle formulas and thus I have three equation and three variables( i studied about syms and solve functions and feature but still have some error which I am not able to figure out). Perhaps I am not converting those variables to appropriate data type( I have little to no idea whats going on behind them, here is the script and a sample of data type :
ch0, ch1, ch2 are csv file i imported generated from python
clc;
clear;
% ADC and strain gauge settings
vref = 3300; % ADC reference millivolts
ADC_resolution = 8388607; % 2^23 24bit of resolution
A = 4; % if fsr = +/-2
pga = 1; % ADS1220 amplifier gain setting
E = 3.3; % Bridge excitation voltage
K = 2.04; % Gauge factor
% Importing adc values
ch0 = readmatrix('ch0.csv');
ch1 = readmatrix('ch1.csv');
ch2 = readmatrix('ch2.csv');
% Conversion to proportional millivoltage
n = vref/ADC_resolution;
Channel0 = n*ch0;
Channel1 = n*ch1;
Channel2 = n*ch2;
% Strain calculation
gauge0 = (4/2.04)*(Channel0/E);
gauge1 = (4/2.04)*(Channel1/E);
gauge2 = (4/2.04)*(Channel2/E);
% Calculation of unblanced bridge in nonstrained state:
% Vr = (bridge strained output - bridge unstrained output)/excitation voltage
% Measured strain to principle strain conversion
% Maximum principal strain
syms e_x e_y lamda_xy
eq0 = (gauge0 - (e_x*((cos(0)).^2)) +(e_y*((sin(0)).^2)) + (lamda_xy*(sin(0))*(cos(0))));
eq1 = (gauge1 - (e_x*((cos(60)).^2)) +(e_y*((sin(60)).^2)) + (lamda_xy*(sin(60))*(cos(60))));
eq2 = (gauge2 - (e_x*((cos(120)).^2)) +(e_y*((sin(120)).^2)) + (lamda_xy*(sin(120))*(cos(120))));
solve(eq0,eq1,eq2,e_x,e_y,lamda_xy);
Walter Roberson
2022-6-30
ch0 = readmatrix('ch0.csv');
Those ch0, ch1, ch2 are probably not scalars.
Channel0 = n*ch0;
so the Channel* variables are probably not scalars.
gauge0 = (4/2.04)*(Channel0/E);
and that makes the gauge* variables not scalars.
eq0 = (gauge0 - (e_x*((cos(0)).^2)) +(e_y*((sin(0)).^2)) + (lamda_xy*(sin(0))*(cos(0))));
So the eq* variables are individually probably not scalars, since they are in terms of the gauge variables that are (probably) not scalars.
solve(eq0,eq1,eq2,e_x,e_y,lamda_xy);
You are asking to solve those arrays of equations that are in terms of 3 scalar variables e_x ,e_y, lamda_xy and you are asking for a single e_x and e_y and lamda_xy that solves those arrays simultaneously.
For example if ch0 is 10 x 1 then eq0 would be 10 x 1, and your call to solve would be solve(10x1, 10x1, 10x1, scalar, scalar, scalar).
solve() is the simultaneous equation solver. When you pass it more than one equation, it has to find the values of the free variables that make all of the equations true at the same time.
What you can do is arrayfun():
sols = arrayfun(@(E0,E1,E2)) solve(E0,E1,E2,e_x,e_y,lamda_xy), eq0, eq1, eq2, 'uniform', 0);
I used uniform, 0 because there might be no solutions in some cases, or there might be multiple solutions perhaps.
Hiril Patel
2022-7-3
Thank you this works but the resulting values in sols are in cell array containing struct with symbols. I am making a for loop to extract those values but is there any efficient/direct way to do it? I read of 'extractfield' but had no success with handaling this data structure.
Hiril Patel
2022-9-18
Hello again,
I had to change the formula since this one didn't yielded true results. But right now I don't know how to ask this query on internet so I had to ask it here.
the new formula contains serveral condition in order to get correct resutls. I want to know how to apply those condtion on each cell. Here is the query:
I have three equal size csv file. I have to take one value from each file from same row of those three file and compute it to get a value. I was able to do that, it is simple. But now what I need its that those computed value needs to be passed from certain condtion in order to apply next formula in order to get true value. Can you tell me how should i take those computed value(all the computed values satishfy a certain condition on which their formula changes).
I hope I have explained it in understandable way.
for more information, I am using these base CSV value to get principle strain value and principle strain direction.( I am able to find principle strain value but the direction has some condition in order to get it calculated).
this is hte reference document:( on page 197 and 198)
thank you
回答(0 个)
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)