How can I read multiple sensors through the serial?

19 ビュー (過去 30 日間)
harold
harold 2018 年 5 月 13 日
コメント済み: harold 2019 年 6 月 8 日
Hello there, I want to read 4 sensor values into arrays and do DSP on them in MATLAB. I've already read the related issues in this platform.
I suppose my arduino code runs perfectly, but MATLAB throws an error saying "Index in position 2 exceeds array bounds (must not exceed 1)." at the second sensor reading line. Could you please help ? Thx ;)
% MATLAB code is as follows
clear all
clc
delete(instrfind)
arduino=serial('COM9');
set(arduino,'BaudRate',38400);
fopen(arduino);
%Handshake
fprintf(arduino,'R'); % Send Read Request to Arduino
x=linspace(1,500); % 500 samples are recorded
y = {}; % all data is thrown in y.
for i=1:length(x)
data =fscanf(arduino,'%d'); % '%d' get ints
y = char(data); % The incoming data is converted to characters
y = regexp(y, '\s*', 'split'); % The data is split up into spaces and in columns.
% Data format: data1-tab-data2-tab-data3-tab-data4
reading1(i,1)= y(1,1); % reads in column 1
reading2(i,1)= y(1,3); % reads in column 2
reading3(i,1)= y(1,5); % reads in column 3
reading4(i,1)= y(1,7); % reads in column 4
end
% Done reading !
fclose(arduino);
delete(instrfind);
reading1plot = str2double(reading1); % Converts data that is on cell array to double data
figure(1)
plot(reading1plot);
title('sensor 1'); xlabel('Sample Index'); ylabel('Analog Reading1');
reading2plot = str2double(reading2); % Converts data that is on cell array to double data
figure(2)
plot(reading2plot);
title('sensor 2'); xlabel('Sample Index'); ylabel('Analog Reading2');
reading3plot = str2double(reading3); % Converts data that is on cell array to double data
figure(3)
plot(reading3plot);
title('sensor 3'); xlabel('Sample Index'); ylabel('Analog Reading3');
reading4plot = str2double(reading4); % Converts data that is on cell array to double data
figure(4)
plot(reading4plot);
title('sensor 4'); xlabel('Sample Index'); ylabel('Analog Reading4');
end
Arduino Code:
int flag= 0;
int ctr = 0;
int ReadReq=0;
int reading1;
int reading2;
int reading3;
int reading4;
void setup() {
Serial.begin(38400);
cli();//stop interrupts
// Sampling rate is 1000 Hz.
//set timer1 interrupt at 1000 Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set timer count for 100Hz increments
OCR1A = 1999;// = (16*10^6) / (1000*8) - 1
//had to use 16 bit timer1 for this bc 1999>255, but could switch to timers 0 or 2 with larger prescaler
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
}
void loop(){
if(Serial.available()>0) { // Check if any data has been sent by the PC
ReadReq = Serial.read();
if((ReadReq=='R')&&(flag == 0)){
ctr = 0;
flag= 1;
}
}
}
ISR(TIMER1_COMPA_vect) { // FREQ 1000 Hz.
if(flag == 1)
{ // takes 500 samples and send it to the MATLAB
reading1 = analogRead(A0);
reading2 = analogRead(A1);
reading3 = analogRead(A2);
reading4 = analogRead(A3);
Serial.print(reading1);
Serial.print("\t");
Serial.print(reading2);
Serial.print("\t");
Serial.print(reading3);
Serial.print("\t");
Serial.print(reading4);
Serial.print("\n");
ctr = ctr + 1;
if(ctr == 499)
{
flag = 0;
}
}
};
  2 件のコメント
Daniela Maldonado
Daniela Maldonado 2019 年 5 月 27 日
I also have the same error, could you solve the problem?
harold
harold 2019 年 6 月 3 日
編集済み: harold 2019 年 6 月 8 日
Hey hello, I just saw your post. We solved the problem, it was a couples line of code. When I have acces the code, I will post the solution here, next week i suppose.
EDIT on 8 Jun 2019
ARDUINO CODE is below. We read 4 different radar sensor data into 700 elements long int arrays. Then we print them into the serial screen which we read it by MATLAB script.
int flag = 0;
int ctr = 0;
int ctr_arr = 0;
char ReadReq;
unsigned int a, b, c, d, e, f, g, h = 0;
unsigned int radar1[700];
unsigned int radar2[700];
unsigned int radar3[700];
unsigned int radar4[700];
void setup() {
Serial.begin(230400);
cli(); //stop interrupts
//set timer1 interrupt at 100 Hz
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 1999;// = (16*10^6) / (1000*8) - 1
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11);
TIMSK1 |= (1 << OCIE1A);
sei(); //allow interrupts
}
void loop() {
if (Serial.available() > 0) {
// Check if any data has been sent by the PC
ReadReq = Serial.read();
// Use character R to indicate starting of Readings
if ((ReadReq == 'R') && (flag == 0)) {
ctr = 0;
flag = 1; // go to Interrupt Service Routine
}
}
}
ISR(TIMER1_COMPA_vect) { // FREQ 1 KHz.
if (flag == 1)
{ // takes 700 samples and send it to the MATLAB through serial
a = analogRead(A0); // 000000aaaaaaaaaa
b = analogRead(A1); // 000000bbbbbbbbbb
c = analogRead(A2); // 000000cccccccccc
d = analogRead(A3); // 000000dddddddddd
radar1[ctr] = a;
radar2[ctr] = b;
radar3[ctr] = c;
radar4[ctr] = d;
ctr = ctr + 1;
if (ctr == 700) // means we had it 700 times
{
flag = 0;
ctr = 0;
Serial.println("D"); // means DONE Reading. Now we proceed sending.
SendData();
}
}
};
void SendData(){
for (int i=0; i<700; i++){
// Send arrays of sensor reading to MATLAB
Serial.print(radar1[i]);
Serial.print(",");
Serial.print(radar2[i]);
Serial.print(",");
Serial.print(radar3[i]);
Serial.print(",");
Serial.print(radar4[i]);
Serial.print("\n");
}
}
NOW, MATLAB CODE is reading the serial and taking the formatted data as follows. I assume it is self explanatory and its been a year since the last time I looked the code. The point is that delete (instrfind), settings of arduino and closing them at the end. Of course the reading of formated data through serial is also done in this code, pay attention to handshaking (usage of R and D).
clear all
close all
clc
delete(instrfind);
arduino=serial('COM9');
set(arduino,'BaudRate',230400);
fopen(arduino);
% Now get the data from arduino
for j=1:10 % 10 Trial Loop
fprintf(arduino,'R'); % Send Read Request to Arduino
disp('Measuring...');
pause(1)
output = '';
while (output == 'D')
output = fscanf(arduino); % is Arduino done? Check and get data if so.
end
output = fscanf(arduino); % is Arduino done? Check and get data if so.
% get 700x4 arrays from MATLAB and save it into a mat file
array1 = zeros(700,1);
array2 = zeros(700,1);
array3 = zeros(700,1);
array4 = zeros(700,1);
for i=1:700 % get encoded arrays from arduino.
data = fscanf(arduino);
commas = strfind(data,',');
array1(i) = str2num(data(1:commas(1)-1));
array2(i) = str2num(data(commas(1):commas(2)-1));
array3(i) = str2num(data(commas(2):commas(3)-1));
array4(i) = str2num(data(commas(3):end));
end
% save all those 4 arrays into the related mat file.
filename = sprintf('sample_gesture_%d_trial_%d.mat',k,j);
save(filename,'array1','array2','array3','array4')
disp('Measured for this trial');
% move on to other trial
pause(1)
end
% Close serial port
fclose(arduino);
delete(arduino);
clear arduino;
Hope this helps.

サインインしてコメントする。

採用された回答

Walter Roberson
Walter Roberson 2018 年 5 月 14 日
You have
data =fscanf(arduino,'%d'); % '%d' get ints
so data will be a vector of numbers, text representation of decimal having been converted to numeric form
y = char(data); % The incoming data is converted to characters
This implicitly looks up the character codes associated with each numeric value, such as 97 being associated with 'a' . For example '97' received in text form from the arduino would have been converted to 97.0 decimal by the fscanf(), and char(97.0) would be 'a'
y = regexp(y, '\s*', 'split'); % The data is split up into spaces and in columns.
This splits at any number of whitespace, including none. This will happen to work the same as if you had specified '\s+' . But remember for char(data) to match whitespace, the data would have had to be numeric 9 (tab), 10 (newline), 12 (formfeed), 13 (carriage return), 32 (space), and possibly some others. As in if the arduino had sent '49 50 9 51 52 53 9 54' which got parsed to [49 50 9 51 52 53 9 54] and then char() of that became '12\t345\t6' and then regexp split would make it {'12' '345' '6'}
  7 件のコメント
Walter Roberson
Walter Roberson 2018 年 5 月 14 日
I suggest you try with something like Tera Term to see what is being sent on the line.
I also recommend configuring the line terminator specifically instead of trying to remember what the default is; and I recommend setting BytesAvailableFcnMode to 'terminator' for the same reason. Also on the MATLAB side you could try using
temp = fgets(arduino);
If you do not get anything then you know the problem is reading from the device rather than problems with incorrect format to scan the data.
harold
harold 2019 年 6 月 8 日
Maybe some people want to chek this out for their projects.
Good Day !

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeMATLAB Support Package for Arduino Hardware についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by